diff --git a/src/duckstation-qt/cheatmanagerdialog.cpp b/src/duckstation-qt/cheatmanagerdialog.cpp index c8bc91a17..b78ce52ac 100644 --- a/src/duckstation-qt/cheatmanagerdialog.cpp +++ b/src/duckstation-qt/cheatmanagerdialog.cpp @@ -17,6 +17,10 @@ #include #include +static constexpr std::array s_size_strings = { + {QT_TR_NOOP("Byte"), QT_TR_NOOP("Halfword"), QT_TR_NOOP("Word"), QT_TR_NOOP("Signed Byte"), + QT_TR_NOOP("Signed Halfword"), QT_TR_NOOP("Signed Word")}}; + static QString formatHexValue(u32 value) { return QStringLiteral("0x%1").arg(static_cast(value), 8, 16, QChar('0')); @@ -126,6 +130,7 @@ void CheatManagerDialog::connectUi() updateResults(); }); connect(m_ui.scanAddWatch, &QPushButton::clicked, this, &CheatManagerDialog::addToWatchClicked); + connect(m_ui.scanAddManualAddress, &QPushButton::clicked, this, &CheatManagerDialog::addManualWatchAddressClicked); connect(m_ui.scanRemoveWatch, &QPushButton::clicked, this, &CheatManagerDialog::removeWatchClicked); connect(m_ui.scanTable, &QTableWidget::currentItemChanged, this, &CheatManagerDialog::scanCurrentItemChanged); connect(m_ui.watchTable, &QTableWidget::currentItemChanged, this, &CheatManagerDialog::watchCurrentItemChanged); @@ -628,6 +633,27 @@ void CheatManagerDialog::addToWatchClicked() updateWatch(); } +void CheatManagerDialog::addManualWatchAddressClicked() +{ + std::optional address = QtUtils::PromptForAddress(this, windowTitle(), tr("Enter memory address:")); + if (!address.has_value()) + return; + + QStringList items; + for (const char* title : s_size_strings) + items.append(tr(title)); + + bool ok = false; + QString selected_item(QInputDialog::getItem(this, windowTitle(), tr("Select data size:"), items, 0, false, &ok)); + int index = items.indexOf(selected_item); + if (index < 0 || !ok) + return; + + m_watch.AddEntry(StringUtil::StdStringFromFormat("0x%08x", address.value()), address.value(), + static_cast(index % 3), (index > 3), false); + updateWatch(); +} + void CheatManagerDialog::removeWatchClicked() { const int index = getSelectedWatchIndex(); @@ -795,10 +821,6 @@ void CheatManagerDialog::updateResultsValues() void CheatManagerDialog::updateWatch() { - static constexpr std::array size_strings = { - {QT_TR_NOOP("Byte"), QT_TR_NOOP("Halfword"), QT_TR_NOOP("Word"), QT_TR_NOOP("Signed Byte"), - QT_TR_NOOP("Signed Halfword"), QT_TR_NOOP("Signed Word")}}; - m_watch.UpdateValues(); QSignalBlocker sb(m_ui.watchTable); @@ -825,7 +847,7 @@ void CheatManagerDialog::updateWatch() m_ui.watchTable->setItem(row, 2, address_item); QTableWidgetItem* size_item = - new QTableWidgetItem(tr(size_strings[static_cast(res.size) + (res.is_signed ? 3 : 0)])); + new QTableWidgetItem(tr(s_size_strings[static_cast(res.size) + (res.is_signed ? 3 : 0)])); size_item->setFlags(address_item->flags() & ~(Qt::ItemIsEditable)); m_ui.watchTable->setItem(row, 3, size_item); diff --git a/src/duckstation-qt/cheatmanagerdialog.h b/src/duckstation-qt/cheatmanagerdialog.h index 4826f7d3a..10b7d4d19 100644 --- a/src/duckstation-qt/cheatmanagerdialog.h +++ b/src/duckstation-qt/cheatmanagerdialog.h @@ -42,6 +42,7 @@ private Q_SLOTS: void exportClicked(); void addToWatchClicked(); + void addManualWatchAddressClicked(); void removeWatchClicked(); void scanCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous); void watchCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous); diff --git a/src/duckstation-qt/cheatmanagerdialog.ui b/src/duckstation-qt/cheatmanagerdialog.ui index 45790b4f3..08c76f6f8 100644 --- a/src/duckstation-qt/cheatmanagerdialog.ui +++ b/src/duckstation-qt/cheatmanagerdialog.ui @@ -510,9 +510,6 @@ - - false - Add Manual Address diff --git a/src/duckstation-qt/debuggerwindow.cpp b/src/duckstation-qt/debuggerwindow.cpp index 90017665c..0220e3c87 100644 --- a/src/duckstation-qt/debuggerwindow.cpp +++ b/src/duckstation-qt/debuggerwindow.cpp @@ -2,10 +2,10 @@ #include "core/cpu_core_private.h" #include "debuggermodels.h" #include "qthostinterface.h" +#include "qtutils.h" #include #include #include -#include #include DebuggerWindow::DebuggerWindow(QWidget* parent /* = nullptr */) @@ -103,7 +103,8 @@ void DebuggerWindow::onGoToPCTriggered() void DebuggerWindow::onGoToAddressTriggered() { - std::optional address = promptForAddress(tr("Enter code address:")); + std::optional address = + QtUtils::PromptForAddress(this, windowTitle(), tr("Enter code address:")); if (!address.has_value()) return; @@ -112,7 +113,8 @@ void DebuggerWindow::onGoToAddressTriggered() void DebuggerWindow::onDumpAddressTriggered() { - std::optional address = promptForAddress(tr("Enter memory address:")); + std::optional address = + QtUtils::PromptForAddress(this, windowTitle(), tr("Enter memory address:")); if (!address.has_value()) return; @@ -126,7 +128,8 @@ void DebuggerWindow::onFollowAddressTriggered() void DebuggerWindow::onAddBreakpointTriggered() { - std::optional address = promptForAddress(tr("Enter code address:")); + std::optional address = + QtUtils::PromptForAddress(this, windowTitle(), tr("Enter code address:")); if (!address.has_value()) return; @@ -515,31 +518,6 @@ void DebuggerWindow::clearBreakpoints() CPU::ClearBreakpoints(); } -std::optional DebuggerWindow::promptForAddress(const QString& label) -{ - const QString address_str(QInputDialog::getText(this, windowTitle(), tr("Enter memory address:"))); - if (address_str.isEmpty()) - return std::nullopt; - - bool ok; - uint address; - if (address_str.startsWith("0x")) - address = address_str.midRef(2).toUInt(&ok, 16); - else if (address_str[0] == '0') - address = address_str.midRef(2).toUInt(&ok, 8); - else - address = address_str.midRef(2).toUInt(&ok, 8); - - if (!ok) - { - QMessageBox::critical(this, windowTitle(), - tr("Invalid address. It should be in hex (0x12345678) or decimal (12345678)")); - return std::nullopt; - } - - return address; -} - std::optional DebuggerWindow::getSelectedCodeAddress() { QItemSelectionModel* sel_model = m_ui.codeView->selectionModel(); diff --git a/src/duckstation-qt/debuggerwindow.h b/src/duckstation-qt/debuggerwindow.h index dd952efca..08e3f513a 100644 --- a/src/duckstation-qt/debuggerwindow.h +++ b/src/duckstation-qt/debuggerwindow.h @@ -60,7 +60,6 @@ private: void setMemoryViewRegion(Bus::MemoryRegion region); void toggleBreakpoint(VirtualMemoryAddress address); void clearBreakpoints(); - std::optional promptForAddress(const QString& label); std::optional getSelectedCodeAddress(); bool tryFollowLoadStore(VirtualMemoryAddress address); void scrollToCodeAddress(VirtualMemoryAddress address); diff --git a/src/duckstation-qt/qtutils.cpp b/src/duckstation-qt/qtutils.cpp index ad48dc602..c68b63e4a 100644 --- a/src/duckstation-qt/qtutils.cpp +++ b/src/duckstation-qt/qtutils.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -736,4 +737,31 @@ void FillComboBoxWithEmulationSpeeds(QComboBox* cb) } } +std::optional PromptForAddress(QWidget* parent, const QString& title, const QString& label) +{ + const QString address_str( + QInputDialog::getText(parent, title, qApp->translate("DebuggerWindow", "Enter memory address:"))); + if (address_str.isEmpty()) + return std::nullopt; + + bool ok; + uint address; + if (address_str.startsWith("0x")) + address = address_str.midRef(2).toUInt(&ok, 16); + else if (address_str[0] == '0' && address_str.length() > 1) + address = address_str.midRef(1).toUInt(&ok, 8); + else + address = address_str.toUInt(&ok, 10); + + if (!ok) + { + QMessageBox::critical( + parent, title, + qApp->translate("DebuggerWindow", "Invalid address. It should be in hex (0x12345678) or decimal (12345678)")); + return std::nullopt; + } + + return address; +} + } // namespace QtUtils \ No newline at end of file diff --git a/src/duckstation-qt/qtutils.h b/src/duckstation-qt/qtutils.h index 9bcf4c3cf..77025002a 100644 --- a/src/duckstation-qt/qtutils.h +++ b/src/duckstation-qt/qtutils.h @@ -71,4 +71,7 @@ void FillComboBoxWithMSAAModes(QComboBox* cb); /// Fills a combo box with emulation speed options. void FillComboBoxWithEmulationSpeeds(QComboBox* cb); +/// Prompts for an address in decimal, octal, or hex. +std::optional PromptForAddress(QWidget* parent, const QString& title, const QString& label); + } // namespace QtUtils \ No newline at end of file