Qt/CheatManager: Add manual watch address

This commit is contained in:
Connor McLaughlin 2020-12-18 19:04:31 +10:00
parent a6a0b660d2
commit 980aa0a8bc
7 changed files with 66 additions and 38 deletions

View File

@ -17,6 +17,10 @@
#include <array>
#include <utility>
static constexpr std::array<const char*, 6> 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<uint>(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<unsigned> 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<MemoryAccessSize>(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<const char*, 6> 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<u32>(res.size) + (res.is_signed ? 3 : 0)]));
new QTableWidgetItem(tr(s_size_strings[static_cast<u32>(res.size) + (res.is_signed ? 3 : 0)]));
size_item->setFlags(address_item->flags() & ~(Qt::ItemIsEditable));
m_ui.watchTable->setItem(row, 3, size_item);

View File

@ -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);

View File

@ -510,9 +510,6 @@
</item>
<item>
<widget class="QPushButton" name="scanAddManualAddress">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Add Manual Address</string>
</property>

View File

@ -2,10 +2,10 @@
#include "core/cpu_core_private.h"
#include "debuggermodels.h"
#include "qthostinterface.h"
#include "qtutils.h"
#include <QtCore/QSignalBlocker>
#include <QtGui/QFontDatabase>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
DebuggerWindow::DebuggerWindow(QWidget* parent /* = nullptr */)
@ -103,7 +103,8 @@ void DebuggerWindow::onGoToPCTriggered()
void DebuggerWindow::onGoToAddressTriggered()
{
std::optional<VirtualMemoryAddress> address = promptForAddress(tr("Enter code address:"));
std::optional<VirtualMemoryAddress> 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<VirtualMemoryAddress> address = promptForAddress(tr("Enter memory address:"));
std::optional<VirtualMemoryAddress> 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<VirtualMemoryAddress> address = promptForAddress(tr("Enter code address:"));
std::optional<VirtualMemoryAddress> 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<VirtualMemoryAddress> 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<VirtualMemoryAddress> DebuggerWindow::getSelectedCodeAddress()
{
QItemSelectionModel* sel_model = m_ui.codeView->selectionModel();

View File

@ -60,7 +60,6 @@ private:
void setMemoryViewRegion(Bus::MemoryRegion region);
void toggleBreakpoint(VirtualMemoryAddress address);
void clearBreakpoints();
std::optional<VirtualMemoryAddress> promptForAddress(const QString& label);
std::optional<VirtualMemoryAddress> getSelectedCodeAddress();
bool tryFollowLoadStore(VirtualMemoryAddress address);
void scrollToCodeAddress(VirtualMemoryAddress address);

View File

@ -8,6 +8,7 @@
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialog>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QScrollBar>
@ -736,4 +737,31 @@ void FillComboBoxWithEmulationSpeeds(QComboBox* cb)
}
}
std::optional<unsigned> 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

View File

@ -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<unsigned> PromptForAddress(QWidget* parent, const QString& title, const QString& label);
} // namespace QtUtils