diff options
Diffstat (limited to 'src/osd/modules/debugger/qt/memorywindow.cpp')
-rw-r--r-- | src/osd/modules/debugger/qt/memorywindow.cpp | 558 |
1 files changed, 329 insertions, 229 deletions
diff --git a/src/osd/modules/debugger/qt/memorywindow.cpp b/src/osd/modules/debugger/qt/memorywindow.cpp index c799ab66c65..ec250055383 100644 --- a/src/osd/modules/debugger/qt/memorywindow.cpp +++ b/src/osd/modules/debugger/qt/memorywindow.cpp @@ -1,9 +1,23 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" +#include "memorywindow.h" + +#include "debugger.h" +#include "debug/dvmemory.h" +#include "debug/debugcon.h" +#include "debug/debugcpu.h" + +#include "util/xmlfile.h" + #include <QtGui/QClipboard> +#include <QtGui/QKeyEvent> #include <QtGui/QMouseEvent> +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include <QtGui/QActionGroup> +#else #include <QtWidgets/QActionGroup> +#endif #include <QtWidgets/QApplication> #include <QtWidgets/QHBoxLayout> #include <QtWidgets/QMenu> @@ -12,19 +26,16 @@ #include <QtWidgets/QToolTip> #include <QtWidgets/QVBoxLayout> -#include "memorywindow.h" - -#include "debug/dvmemory.h" -#include "debug/debugcon.h" -#include "debug/debugcpu.h" +namespace osd::debugger::qt { -MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : - WindowQt(machine, nullptr) +MemoryWindow::MemoryWindow(DebuggerQt &debugger, QWidget *parent) : + WindowQt(debugger, nullptr), + m_inputHistory() { setWindowTitle("Debug: Memory View"); - if (parent != nullptr) + if (parent) { QPoint parentPos = parent->pos(); setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400); @@ -33,32 +44,34 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : // // The main frame and its input and log widgets // - QFrame* mainWindowFrame = new QFrame(this); + QFrame *mainWindowFrame = new QFrame(this); // The top frame & groupbox that contains the input widgets - QFrame* topSubFrame = new QFrame(mainWindowFrame); + QFrame *topSubFrame = new QFrame(mainWindowFrame); // The input edit m_inputEdit = new QLineEdit(topSubFrame); connect(m_inputEdit, &QLineEdit::returnPressed, this, &MemoryWindow::expressionSubmitted); + connect(m_inputEdit, &QLineEdit::textEdited, this, &MemoryWindow::expressionEdited); + m_inputEdit->installEventFilter(this); // The memory space combo box m_memoryComboBox = new QComboBox(topSubFrame); m_memoryComboBox->setObjectName("memoryregion"); m_memoryComboBox->setMinimumWidth(300); - connect(m_memoryComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &MemoryWindow::memoryRegionChanged); + connect(m_memoryComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &MemoryWindow::memoryRegionChanged); // The main memory window m_memTable = new DebuggerMemView(DVT_MEMORY, m_machine, this); // Layout - QHBoxLayout* subLayout = new QHBoxLayout(topSubFrame); + QHBoxLayout *subLayout = new QHBoxLayout(topSubFrame); subLayout->addWidget(m_inputEdit); subLayout->addWidget(m_memoryComboBox); subLayout->setSpacing(3); subLayout->setContentsMargins(2,2,2,2); - QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame); + QVBoxLayout *vLayout = new QVBoxLayout(mainWindowFrame); vLayout->setSpacing(3); vLayout->setContentsMargins(2,2,2,2); vLayout->addWidget(topSubFrame); @@ -71,26 +84,38 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : // // Create a data format group - QActionGroup* dataFormat = new QActionGroup(this); + QActionGroup *dataFormat = new QActionGroup(this); dataFormat->setObjectName("dataformat"); - QAction* formatActOne = new QAction("1-byte chunks", this); - QAction* formatActTwo = new QAction("2-byte chunks", this); - QAction* formatActFour = new QAction("4-byte chunks", this); - QAction* formatActEight = new QAction("8-byte chunks", this); - QAction* formatAct32bitFloat = new QAction("32 bit floating point", this); - QAction* formatAct64bitFloat = new QAction("64 bit floating point", this); - QAction* formatAct80bitFloat = new QAction("80 bit floating point", this); - formatActOne->setObjectName("formatActOne"); - formatActTwo->setObjectName("formatActTwo"); - formatActFour->setObjectName("formatActFour"); - formatActEight->setObjectName("formatActEight"); - formatAct32bitFloat->setObjectName("formatAct32bitFloat"); - formatAct64bitFloat->setObjectName("formatAct64bitFloat"); - formatAct80bitFloat->setObjectName("formatAct80bitFloat"); + QAction *formatActOne = new QAction("1-byte Chunks (Hex)", this); + QAction *formatActTwo = new QAction("2-byte Chunks (Hex)", this); + QAction *formatActFour = new QAction("4-byte Chunks (Hex)", this); + QAction *formatActEight = new QAction("8-byte Chunks (Hex)", this); + QAction *formatActOneOctal = new QAction("1-byte Chunks (Octal)", this); + QAction *formatActTwoOctal = new QAction("2-byte Chunks (Octal)", this); + QAction *formatActFourOctal = new QAction("4-byte Chunks (Octal)", this); + QAction *formatActEightOctal = new QAction("8-byte Chunks (Octal)", this); + QAction *formatAct32bitFloat = new QAction("32-bit Floating Point", this); + QAction *formatAct64bitFloat = new QAction("64-bit Floating Point", this); + QAction *formatAct80bitFloat = new QAction("80-bit Floating Point", this); + formatActOne->setData(int(debug_view_memory::data_format::HEX_8BIT)); + formatActTwo->setData(int(debug_view_memory::data_format::HEX_16BIT)); + formatActFour->setData(int(debug_view_memory::data_format::HEX_32BIT)); + formatActEight->setData(int(debug_view_memory::data_format::HEX_64BIT)); + formatActOneOctal->setData(int(debug_view_memory::data_format::OCTAL_8BIT)); + formatActTwoOctal->setData(int(debug_view_memory::data_format::OCTAL_16BIT)); + formatActFourOctal->setData(int(debug_view_memory::data_format::OCTAL_32BIT)); + formatActEightOctal->setData(int(debug_view_memory::data_format::OCTAL_64BIT)); + formatAct32bitFloat->setData(int(debug_view_memory::data_format::FLOAT_32BIT)); + formatAct64bitFloat->setData(int(debug_view_memory::data_format::FLOAT_64BIT)); + formatAct80bitFloat->setData(int(debug_view_memory::data_format::FLOAT_80BIT)); formatActOne->setCheckable(true); formatActTwo->setCheckable(true); formatActFour->setCheckable(true); formatActEight->setCheckable(true); + formatActOneOctal->setCheckable(true); + formatActTwoOctal->setCheckable(true); + formatActFourOctal->setCheckable(true); + formatActEightOctal->setCheckable(true); formatAct32bitFloat->setCheckable(true); formatAct64bitFloat->setCheckable(true); formatAct80bitFloat->setCheckable(true); @@ -98,6 +123,10 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : formatActTwo->setActionGroup(dataFormat); formatActFour->setActionGroup(dataFormat); formatActEight->setActionGroup(dataFormat); + formatActOneOctal->setActionGroup(dataFormat); + formatActTwoOctal->setActionGroup(dataFormat); + formatActFourOctal->setActionGroup(dataFormat); + formatActEightOctal->setActionGroup(dataFormat); formatAct32bitFloat->setActionGroup(dataFormat); formatAct64bitFloat->setActionGroup(dataFormat); formatAct80bitFloat->setActionGroup(dataFormat); @@ -105,14 +134,23 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : formatActTwo->setShortcut(QKeySequence("Ctrl+2")); formatActFour->setShortcut(QKeySequence("Ctrl+4")); formatActEight->setShortcut(QKeySequence("Ctrl+8")); - formatAct32bitFloat->setShortcut(QKeySequence("Ctrl+9")); + formatActOneOctal->setShortcut(QKeySequence("Ctrl+3")); + formatActTwoOctal->setShortcut(QKeySequence("Ctrl+5")); + formatActFourOctal->setShortcut(QKeySequence("Ctrl+7")); + formatActEightOctal->setShortcut(QKeySequence("Ctrl+9")); + formatAct32bitFloat->setShortcut(QKeySequence("Ctrl+Shift+F")); + formatAct64bitFloat->setShortcut(QKeySequence("Ctrl+Shift+D")); + formatAct80bitFloat->setShortcut(QKeySequence("Ctrl+Shift+E")); formatActOne->setChecked(true); connect(dataFormat, &QActionGroup::triggered, this, &MemoryWindow::formatChanged); - // Create a address display group - QActionGroup* addressGroup = new QActionGroup(this); + + // Create an address display group + QActionGroup *addressGroup = new QActionGroup(this); addressGroup->setObjectName("addressgroup"); - QAction* addressActLogical = new QAction("Logical Addresses", this); - QAction* addressActPhysical = new QAction("Physical Addresses", this); + QAction *addressActLogical = new QAction("Logical Addresses", this); + QAction *addressActPhysical = new QAction("Physical Addresses", this); + addressActLogical->setData(false); + addressActPhysical->setData(true); addressActLogical->setCheckable(true); addressActPhysical->setCheckable(true); addressActLogical->setActionGroup(addressGroup); @@ -122,27 +160,49 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : addressActLogical->setChecked(true); connect(addressGroup, &QActionGroup::triggered, this, &MemoryWindow::addressChanged); + // Create an address radix group + QActionGroup *radixGroup = new QActionGroup(this); + radixGroup->setObjectName("radixgroup"); + QAction *radixActHexadecimal = new QAction("Hexadecimal Addresses", this); + QAction *radixActDecimal = new QAction("Decimal Addresses", this); + QAction *radixActOctal = new QAction("Octal Addresses", this); + radixActHexadecimal->setData(16); + radixActDecimal->setData(10); + radixActOctal->setData(8); + radixActHexadecimal->setCheckable(true); + radixActDecimal->setCheckable(true); + radixActOctal->setCheckable(true); + radixActHexadecimal->setActionGroup(radixGroup); + radixActDecimal->setActionGroup(radixGroup); + radixActOctal->setActionGroup(radixGroup); + radixActHexadecimal->setShortcut(QKeySequence("Ctrl+Shift+H")); + radixActOctal->setShortcut(QKeySequence("Ctrl+Shift+O")); + radixActHexadecimal->setChecked(true); + connect(radixGroup, &QActionGroup::triggered, this, &MemoryWindow::radixChanged); + // Create a reverse view radio - QAction* reverseAct = new QAction("Reverse View", this); + QAction *reverseAct = new QAction("Reverse View", this); reverseAct->setObjectName("reverse"); reverseAct->setCheckable(true); reverseAct->setShortcut(QKeySequence("Ctrl+R")); connect(reverseAct, &QAction::toggled, this, &MemoryWindow::reverseChanged); // Create increase and decrease bytes-per-line actions - QAction* increaseBplAct = new QAction("Increase Bytes Per Line", this); - QAction* decreaseBplAct = new QAction("Decrease Bytes Per Line", this); + QAction *increaseBplAct = new QAction("Increase Bytes Per Line", this); + QAction *decreaseBplAct = new QAction("Decrease Bytes Per Line", this); increaseBplAct->setShortcut(QKeySequence("Ctrl+P")); decreaseBplAct->setShortcut(QKeySequence("Ctrl+O")); connect(increaseBplAct, &QAction::triggered, this, &MemoryWindow::increaseBytesPerLine); connect(decreaseBplAct, &QAction::triggered, this, &MemoryWindow::decreaseBytesPerLine); // Assemble the options menu - QMenu* optionsMenu = menuBar()->addMenu("&Options"); + QMenu *optionsMenu = menuBar()->addMenu("&Options"); optionsMenu->addActions(dataFormat->actions()); optionsMenu->addSeparator(); optionsMenu->addActions(addressGroup->actions()); optionsMenu->addSeparator(); + optionsMenu->addActions(radixGroup->actions()); + optionsMenu->addSeparator(); optionsMenu->addAction(reverseAct); optionsMenu->addSeparator(); optionsMenu->addAction(increaseBplAct); @@ -164,98 +224,213 @@ MemoryWindow::~MemoryWindow() } -void MemoryWindow::memoryRegionChanged(int index) +void MemoryWindow::restoreConfiguration(util::xml::data_node const &node) { - m_memTable->view()->set_source(*m_memTable->view()->source_list().find(index)); - m_memTable->viewport()->update(); + WindowQt::restoreConfiguration(node); + + debug_view_memory &memView = *m_memTable->view<debug_view_memory>(); + + auto const region = node.get_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_memTable->sourceIndex()); + if ((0 <= region) && (m_memoryComboBox->count() > region)) + m_memoryComboBox->setCurrentIndex(region); + + auto const reverse = node.get_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView.reverse() ? 1 : 0); + if (memView.reverse() != bool(reverse)) + { + memView.set_reverse(bool(reverse)); + findChild<QAction *>("reverse")->setChecked(bool(reverse)); + } - // Update the data format radio buttons to the memory region's default - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); - switch(memView->get_data_format()) + auto const mode = node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView.physical() ? 1 : 0); + QActionGroup *const addressGroup = findChild<QActionGroup *>("addressgroup"); + for (QAction *action : addressGroup->actions()) { - case 1: dataFormatMenuItem("formatActOne")->setChecked(true); break; - case 2: dataFormatMenuItem("formatActTwo")->setChecked(true); break; - case 4: dataFormatMenuItem("formatActFour")->setChecked(true); break; - case 8: dataFormatMenuItem("formatActEight")->setChecked(true); break; - case 9: dataFormatMenuItem("formatAct32bitFloat")->setChecked(true); break; - case 10: dataFormatMenuItem("formatAct64bitFloat")->setChecked(true); break; - case 11: dataFormatMenuItem("formatAct80bitFloat")->setChecked(true); break; - default: break; + if (action->data().toBool() == mode) + { + action->trigger(); + break; + } } + + auto const radix = node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView.address_radix()); + QActionGroup *const radixGroup = findChild<QActionGroup *>("radixgroup"); + for (QAction *action : radixGroup->actions()) + { + if (action->data().toInt() == radix) + { + action->trigger(); + break; + } + } + + auto const format = node.get_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView.get_data_format())); + QActionGroup *const dataFormat = findChild<QActionGroup *>("dataformat"); + for (QAction *action : dataFormat->actions()) + { + if (action->data().toInt() == format) + { + action->trigger(); + break; + } + } + + auto const chunks = node.get_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView.chunks_per_row()); + memView.set_chunks_per_row(chunks); + + util::xml::data_node const *const expression = node.get_child(NODE_WINDOW_EXPRESSION); + if (expression && expression->get_value()) + { + m_inputEdit->setText(QString::fromUtf8(expression->get_value())); + expressionSubmitted(); + } + + m_memTable->restoreConfigurationFromNode(node); + m_inputHistory.restoreConfigurationFromNode(node); } -void MemoryWindow::expressionSubmitted() +void MemoryWindow::saveConfigurationToNode(util::xml::data_node &node) { - const QString expression = m_inputEdit->text(); - downcast<debug_view_memory*>(m_memTable->view())->set_expression(expression.toLocal8Bit().data()); + WindowQt::saveConfigurationToNode(node); - // Make the cursor pop - m_memTable->view()->set_cursor_visible(true); + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_MEMORY_VIEWER); - // Check where the cursor is and adjust the scroll accordingly - debug_view_xy cursorPosition = m_memTable->view()->cursor_position(); - // TODO: check if the region is already visible? - m_memTable->verticalScrollBar()->setValue(cursorPosition.y); + debug_view_memory &memView = *m_memTable->view<debug_view_memory>(); + node.set_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_memTable->sourceIndex()); + node.set_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView.reverse() ? 1 : 0); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView.physical() ? 1 : 0); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView.address_radix()); + node.set_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView.get_data_format())); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView.chunks_per_row()); + node.add_child(NODE_WINDOW_EXPRESSION, memView.expression()); - m_memTable->update(); - m_memTable->viewport()->update(); + m_memTable->saveConfigurationToNode(node); + m_inputHistory.saveConfigurationToNode(node); } -void MemoryWindow::formatChanged(QAction* changedTo) +void MemoryWindow::memoryRegionChanged(int index) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); - if (changedTo->text() == "1-byte chunks") - { - memView->set_data_format(1); - } - else if (changedTo->text() == "2-byte chunks") + if (index < m_memTable->view()->source_count()) { - memView->set_data_format(2); - } - else if (changedTo->text() == "4-byte chunks") - { - memView->set_data_format(4); + m_memTable->view()->set_source(*m_memTable->view()->source(index)); + m_memTable->viewport()->update(); + + // Update the data format radio buttons to the memory region's default + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); + + QActionGroup *const dataFormat = findChild<QActionGroup *>("dataformat"); + for (QAction *action : dataFormat->actions()) + { + if (debug_view_memory::data_format(action->data().toInt()) == memView->get_data_format()) + { + action->setChecked(true); + break; + } + } + + QActionGroup *radixGroup = findChild<QActionGroup *>("radixgroup"); + for (QAction *action : radixGroup->actions()) + { + if (action->data().toInt() == memView->address_radix()) + { + action->setChecked(true); + break; + } + } } - else if (changedTo->text() == "8-byte chunks") +} + + +// Used to intercept the user hitting the up arrow in the input widget +bool MemoryWindow::eventFilter(QObject *obj, QEvent *event) +{ + // Only filter keypresses + if (event->type() != QEvent::KeyPress) + return QObject::eventFilter(obj, event); + + QKeyEvent const &keyEvent = *static_cast<QKeyEvent *>(event); + + // Catch up & down keys + if (keyEvent.key() == Qt::Key_Escape) { - memView->set_data_format(8); + m_inputEdit->setText(QString::fromUtf8(m_memTable->view<debug_view_memory>()->expression())); + m_inputEdit->selectAll(); + m_inputHistory.reset(); + return true; } - else if (changedTo->text() == "32 bit floating point") + else if (keyEvent.key() == Qt::Key_Up) { - memView->set_data_format(9); + QString const *const hist = m_inputHistory.previous(m_inputEdit->text()); + if (hist) + { + m_inputEdit->setText(*hist); + m_inputEdit->setSelection(hist->size(), 0); + } + return true; } - else if (changedTo->text() == "64 bit floating point") + else if (keyEvent.key() == Qt::Key_Down) { - memView->set_data_format(10); + QString const *const hist = m_inputHistory.next(m_inputEdit->text()); + if (hist) + { + m_inputEdit->setText(*hist); + m_inputEdit->setSelection(hist->size(), 0); + } + return true; } - else if (changedTo->text() == "80 bit floating point") + else { - memView->set_data_format(11); + return QObject::eventFilter(obj, event); } +} + + +void MemoryWindow::expressionSubmitted() +{ + const QString expression = m_inputEdit->text(); + m_memTable->view<debug_view_memory>()->set_expression(expression.toUtf8().data()); + m_inputEdit->selectAll(); + + // Add history + if (!expression.isEmpty()) + m_inputHistory.add(expression); +} + + +void MemoryWindow::expressionEdited(QString const &text) +{ + m_inputHistory.edit(); +} + + +void MemoryWindow::formatChanged(QAction* changedTo) +{ + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); + memView->set_data_format(debug_view_memory::data_format(changedTo->data().toInt())); m_memTable->viewport()->update(); } void MemoryWindow::addressChanged(QAction* changedTo) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); - if (changedTo->text() == "Logical Addresses") - { - memView->set_physical(false); - } - else if (changedTo->text() == "Physical Addresses") - { - memView->set_physical(true); - } + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); + memView->set_physical(changedTo->data().toBool()); + m_memTable->viewport()->update(); +} + + +void MemoryWindow::radixChanged(QAction* changedTo) +{ + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); + memView->set_address_radix(changedTo->data().toInt()); m_memTable->viewport()->update(); } void MemoryWindow::reverseChanged(bool changedTo) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); memView->set_reverse(changedTo); m_memTable->viewport()->update(); } @@ -263,7 +438,7 @@ void MemoryWindow::reverseChanged(bool changedTo) void MemoryWindow::increaseBytesPerLine(bool changedTo) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); memView->set_chunks_per_row(memView->chunks_per_row() + 1); m_memTable->viewport()->update(); } @@ -271,7 +446,7 @@ void MemoryWindow::increaseBytesPerLine(bool changedTo) void MemoryWindow::decreaseBytesPerLine(bool checked) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); memView->set_chunks_per_row(memView->chunks_per_row() - 1); m_memTable->viewport()->update(); } @@ -279,173 +454,98 @@ void MemoryWindow::decreaseBytesPerLine(bool checked) void MemoryWindow::populateComboBox() { - if (m_memTable == nullptr) + if (!m_memTable) return; m_memoryComboBox->clear(); - for (const debug_view_source &source : m_memTable->view()->source_list()) - { - m_memoryComboBox->addItem(source.name()); - } + for (auto &source : m_memTable->view()->source_list()) + m_memoryComboBox->addItem(source->name()); } void MemoryWindow::setToCurrentCpu() { - device_t* curCpu = m_machine->debugger().cpu().get_visible_cpu(); - const debug_view_source *source = m_memTable->view()->source_for_device(curCpu); - const int listIndex = m_memTable->view()->source_list().indexof(*source); - m_memoryComboBox->setCurrentIndex(listIndex); -} - - -// I have a hard time storing QActions as class members. This is a substitute. -QAction* MemoryWindow::dataFormatMenuItem(const QString& itemName) -{ - QList<QMenu*> menus = menuBar()->findChildren<QMenu*>(); - for (int i = 0; i < menus.length(); i++) + device_t *curCpu = m_machine.debugger().console().get_visible_cpu(); + if (curCpu) { - if (menus[i]->title() != "&Options") continue; - QList<QAction*> actions = menus[i]->actions(); - for (int j = 0; j < actions.length(); j++) + const debug_view_source *source = m_memTable->view()->source_for_device(curCpu); + if (source) { - if (actions[j]->objectName() == itemName) - return actions[j]; + const int listIndex = m_memTable->view()->source_index(*source); + m_memoryComboBox->setCurrentIndex(listIndex); } } - return nullptr; } //========================================================================= // DebuggerMemView //========================================================================= -void DebuggerMemView::mousePressEvent(QMouseEvent* event) +void DebuggerMemView::addItemsToContextMenu(QMenu *menu) { - const bool leftClick = event->button() == Qt::LeftButton; - const bool rightClick = event->button() == Qt::RightButton; + DebuggerView::addItemsToContextMenu(menu); - if (leftClick || rightClick) + if (view()->cursor_visible()) { - QFontMetrics actualFont = fontMetrics(); - const double fontWidth = actualFont.width(QString(100, '_')) / 100.; - const int fontHeight = std::max(1, actualFont.lineSpacing()); - - debug_view_xy topLeft = view()->visible_position(); - debug_view_xy clickViewPosition; - clickViewPosition.x = topLeft.x + (event->x() / fontWidth); - clickViewPosition.y = topLeft.y + (event->y() / fontHeight); - if (leftClick) - { - view()->process_click(DCK_LEFT_CLICK, clickViewPosition); - } - else if (rightClick) + debug_view_memory &memView = *view<debug_view_memory>(); + debug_view_memory_source const &source = downcast<debug_view_memory_source const &>(*memView.source()); + address_space *const addressSpace = source.space(); + if (addressSpace) { - // Display the last known PC to write to this memory location & copy it onto the clipboard - debug_view_memory* memView = downcast<debug_view_memory*>(view()); - const offs_t address = memView->addressAtCursorPosition(clickViewPosition); - const debug_view_memory_source* source = downcast<const debug_view_memory_source*>(memView->source()); - address_space* addressSpace = source->space(); - const int nativeDataWidth = addressSpace->data_width() / 8; - const uint64_t memValue = source->device()->machine().debugger().cpu().read_memory(*addressSpace, - addressSpace->address_to_byte(address), - nativeDataWidth, - true); - const offs_t pc = source->device()->debug()->track_mem_pc_from_space_address_data(addressSpace->spacenum(), - address, - memValue); - if (pc != (offs_t)(-1)) + // get the last known PC to write to this memory location + debug_view_xy const pos = memView.cursor_position(); + offs_t const address = addressSpace->byte_to_address(memView.addressAtCursorPosition(pos)); + offs_t a = address & addressSpace->logaddrmask(); + bool good = false; + address_space *tspace; + if (!addressSpace->device().memory().translate(addressSpace->spacenum(), device_memory_interface::TR_READ, a, tspace)) { - // TODO: You can specify a box that the tooltip stays alive within - might be good? - const QString addressAndPc = QString("Address %1 written at PC=%2").arg(address, 2, 16).arg(pc, 2, 16); - QToolTip::showText(QCursor::pos(), addressAndPc, nullptr); - - // Copy the PC into the clipboard as well - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(QString("%1").arg(pc, 2, 16)); + m_lastPc = "Bad address"; } else { - QToolTip::showText(QCursor::pos(), "UNKNOWN PC", nullptr); + uint64_t memValue = tspace->unmap(); + auto dis = tspace->device().machine().disable_side_effects(); + switch (tspace->data_width()) + { + case 8: memValue = tspace->read_byte(a); break; + case 16: memValue = tspace->read_word_unaligned(a); break; + case 32: memValue = tspace->read_dword_unaligned(a); break; + case 64: memValue = tspace->read_qword_unaligned(a); break; + } + + offs_t const pc = source.device()->debug()->track_mem_pc_from_space_address_data( + tspace->spacenum(), + address, + memValue); + if (pc != offs_t(-1)) + { + if (tspace->is_octal()) + m_lastPc = QString("Address %1 written at PC=%2").arg(address, 2, 8).arg(pc, 2, 8); + else + m_lastPc = QString("Address %1 written at PC=%2").arg(address, 2, 16).arg(pc, 2, 16); + good = true; + } + else + { + m_lastPc = "Unknown PC"; + } } - } - viewport()->update(); - update(); + if (!menu->isEmpty()) + menu->addSeparator(); + QAction *const act = new QAction(m_lastPc, menu); + act->setEnabled(good); + connect(act, &QAction::triggered, this, &DebuggerMemView::copyLastPc); + menu->addAction(act); + } } } -//========================================================================= -// MemoryWindowQtConfig -//========================================================================= -void MemoryWindowQtConfig::buildFromQWidget(QWidget* widget) -{ - WindowQtConfig::buildFromQWidget(widget); - MemoryWindow* window = dynamic_cast<MemoryWindow*>(widget); - QComboBox* memoryRegion = window->findChild<QComboBox*>("memoryregion"); - m_memoryRegion = memoryRegion->currentIndex(); - - QAction* reverse = window->findChild<QAction*>("reverse"); - m_reverse = reverse->isChecked(); - - QActionGroup* addressGroup = window->findChild<QActionGroup*>("addressgroup"); - if (addressGroup->checkedAction()->text() == "Logical Addresses") - m_addressMode = 0; - else if (addressGroup->checkedAction()->text() == "Physical Addresses") - m_addressMode = 1; - - QActionGroup* dataFormat = window->findChild<QActionGroup*>("dataformat"); - if (dataFormat->checkedAction()->text() == "1-byte chunks") - m_dataFormat = 0; - else if (dataFormat->checkedAction()->text() == "2-byte chunks") - m_dataFormat = 1; - else if (dataFormat->checkedAction()->text() == "4-byte chunks") - m_dataFormat = 2; - else if (dataFormat->checkedAction()->text() == "8-byte chunks") - m_dataFormat = 3; - else if (dataFormat->checkedAction()->text() == "32 bit floating point") - m_dataFormat = 4; - else if (dataFormat->checkedAction()->text() == "64 bit floating point") - m_dataFormat = 5; - else if (dataFormat->checkedAction()->text() == "80 bit floating point") - m_dataFormat = 6; -} - - -void MemoryWindowQtConfig::applyToQWidget(QWidget* widget) +void DebuggerMemView::copyLastPc() { - WindowQtConfig::applyToQWidget(widget); - MemoryWindow* window = dynamic_cast<MemoryWindow*>(widget); - QComboBox* memoryRegion = window->findChild<QComboBox*>("memoryregion"); - memoryRegion->setCurrentIndex(m_memoryRegion); - - QAction* reverse = window->findChild<QAction*>("reverse"); - if (m_reverse) reverse->trigger(); - - QActionGroup* addressGroup = window->findChild<QActionGroup*>("addressgroup"); - addressGroup->actions()[m_addressMode]->trigger(); - - QActionGroup* dataFormat = window->findChild<QActionGroup*>("dataformat"); - dataFormat->actions()[m_dataFormat]->trigger(); + QApplication::clipboard()->setText(m_lastPc); } - -void MemoryWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const -{ - WindowQtConfig::addToXmlDataNode(node); - node.set_attribute_int("memoryregion", m_memoryRegion); - node.set_attribute_int("reverse", m_reverse); - node.set_attribute_int("addressmode", m_addressMode); - node.set_attribute_int("dataformat", m_dataFormat); -} - - -void MemoryWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) -{ - WindowQtConfig::recoverFromXmlNode(node); - m_memoryRegion = node.get_attribute_int("memoryregion", m_memoryRegion); - m_reverse = node.get_attribute_int("reverse", m_reverse); - m_addressMode = node.get_attribute_int("addressmode", m_addressMode); - m_dataFormat = node.get_attribute_int("dataformat", m_dataFormat); -} +} // namespace osd::debugger::qt |