Qt/CheatManager: Add manual watch address
This commit is contained in:
parent
a6a0b660d2
commit
980aa0a8bc
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue