Duckstation/src/duckstation-qt/memoryscannerwindow.cpp
PugsyMAME 7adbedd341
Renamed Mem Scanner Op Text&added Virtual Address (#3172)
* Renamed Mem Scanner Op Text&added Virtual Address

Renamed the Memory Scanner Operator Text for clarity. Replaced '...' with 'Value' and 'Previous' with 'Previous Result'.
Also changed "Any Value" to "Any Value ('New Search' or 'Reset Result Value')", Any Valur should really be at the top of the index and the Previous Results should come before the other Value operators. But that's a job for another time.
The Virtual Address extra will display the virtual address of DuckStation's PSX RAM so it can be easily edited with the likes of HXD or another tool where the location of the virtual memory needs to be known.

* Replaced Mem Scanner Op Text with latest English text

Not touched the translations, just added the updated english text for the Memory Scanner "Operator:" text

* Rearranged  Memory Scanner Operator class

Re-arranged Memory Scanner Operator class into a more logical order - with likely frequency of use moving item up the list.

New Order:-
Better Order:-
Any Value ('New Search' or 'Reset Result Value')         x    Any.
Less Than Previous Result                                x    LessThanLast,
Less or Equal to Previous Result                         x    LessEqualLast,
Greater Than Previous Result                             x    GreaterThanLast,
Greater or Equal to Previous Result                      x    GreaterEqualLast,
Not Equal to Previous Result (Changed Value)             x    NotEqualLast,
Equal to Previous Result (Unchanged Value)               x    EqualLast,
Decreased By Value                                       x    DecreasedBy,
Increased By Value                                       x    IncreasedBy,
Changed By Value                                         x    ChangedBy,
Equal to Value                                           x    Equal,
Not Equal to Value                                       x    NotEqual,
Less Than Value                                          x    LessThan,
Less or Equal to Value	                                 x    LessEqual,
Greater Than Value                                       x    GreaterThan,
Greater or Equal to Value                                x    GreaterEqual

* Rearranged  Memory Scanner Operator class

Changes operator order to:-
Any Value ('New Search' or 'Reset Result Value')        
Less Than Previous Result                               
Less or Equal to Previous Result                        
Greater Than Previous Result                            
Greater or Equal to Previous Result                     
Not Equal to Previous Result (Changed Value)            
Equal to Previous Result (Unchanged Value)              
Decreased By Value                                      
Increased By Value                                      
Changed By Value                                        
Equal to Value                                          
Not Equal to Value                                      
Less Than Value                                         
Less or Equal to Value	                                
Greater Than Value                                      
Greater or Equal to Value

* Memory Scanner line references updates

Updated <location filename="../memoryscannerwindow.ui" line="???"/> line numbers for the Memory Scanner operation re-ordering.
These are currently the only 4 translation files that make reference to memoryscannerwindow.ui, the other 12 still reference cheatmanagerdialog.ui so not replicated for them as this would only partially fix them - so I left them alone as I hope there's some automated tools to handle it.

* Update src/duckstation-qt/memoryscannerwindow.cpp
2024-04-13 19:57:12 +10:00

595 lines
19 KiB
C++

// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> and contributors.
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "memoryscannerwindow.h"
#include "cheatcodeeditordialog.h"
#include "common/assert.h"
#include "common/string_util.h"
#include "core/bus.h"
#include "core/cpu_core.h"
#include "core/host.h"
#include "core/system.h"
#include "qthost.h"
#include "qtutils.h"
#include <QtCore/QFileInfo>
#include <QtGui/QColor>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QTreeWidgetItemIterator>
#include <array>
#include <utility>
static constexpr std::array<const char*, 6> s_size_strings = {
{TRANSLATE_NOOP("MemoryScannerWindow", "Byte"), TRANSLATE_NOOP("MemoryScannerWindow", "Halfword"),
TRANSLATE_NOOP("MemoryScannerWindow", "Word"), TRANSLATE_NOOP("MemoryScannerWindow", "Signed Byte"),
TRANSLATE_NOOP("MemoryScannerWindow", "Signed Halfword"), TRANSLATE_NOOP("MemoryScannerWindow", "Signed Word")}};
static QString formatHexValue(u32 value, u8 size)
{
return QStringLiteral("0x%1").arg(static_cast<uint>(value), size, 16, QChar('0'));
}
static QString formatHexAndDecValue(u32 value, u8 size, bool is_signed)
{
if (is_signed)
{
u32 value_raw = value;
if (size == 2)
value_raw &= 0xFF;
else if (size == 4)
value_raw &= 0xFFFF;
return QStringLiteral("0x%1 (%2)")
.arg(static_cast<u32>(value_raw), size, 16, QChar('0'))
.arg(static_cast<int>(value));
}
else
return QStringLiteral("0x%1 (%2)").arg(static_cast<u32>(value), size, 16, QChar('0')).arg(static_cast<uint>(value));
}
static QString formatCheatCode(u32 address, u32 value, const MemoryAccessSize size)
{
if (size == MemoryAccessSize::Byte && address <= 0x00200000)
return QStringLiteral("CHEAT CODE: %1 %2")
.arg(static_cast<u32>(address) + 0x30000000, 8, 16, QChar('0'))
.toUpper()
.arg(static_cast<u16>(value), 4, 16, QChar('0'))
.toUpper();
else if (size == MemoryAccessSize::HalfWord && address <= 0x001FFFFE)
return QStringLiteral("CHEAT CODE: %1 %2")
.arg(static_cast<u32>(address) + 0x80000000, 8, 16, QChar('0'))
.toUpper()
.arg(static_cast<u16>(value), 4, 16, QChar('0'))
.toUpper();
else if (size == MemoryAccessSize::Word && address <= 0x001FFFFC)
return QStringLiteral("CHEAT CODE: %1 %2")
.arg(static_cast<u32>(address) + 0x90000000, 8, 16, QChar('0'))
.toUpper()
.arg(static_cast<u32>(value), 8, 16, QChar('0'))
.toUpper();
else
return QStringLiteral("OUTSIDE RAM RANGE. POKE %1 with %2")
.arg(static_cast<u32>(address), 8, 16, QChar('0'))
.toUpper()
.arg(static_cast<u16>(value), 8, 16, QChar('0'))
.toUpper();
}
static QString formatValue(u32 value, bool is_signed)
{
if (is_signed)
return QString::number(static_cast<int>(value));
else
return QString::number(static_cast<uint>(value));
}
MemoryScannerWindow::MemoryScannerWindow() : QWidget()
{
m_ui.setupUi(this);
connectUi();
m_ui.cheatEngineAddress->setText(tr("Address of RAM for HxD Usage: 0x%1").arg(reinterpret_cast<qulonglong>(Bus::g_unprotected_ram), 16, 16, QChar('0')));
}
MemoryScannerWindow::~MemoryScannerWindow() = default;
void MemoryScannerWindow::connectUi()
{
m_ui.scanStartAddress->setText(formatHexValue(m_scanner.GetStartAddress(), 8));
m_ui.scanEndAddress->setText(formatHexValue(m_scanner.GetEndAddress(), 8));
connect(m_ui.scanValue, &QLineEdit::textChanged, this, &MemoryScannerWindow::updateScanValue);
connect(m_ui.scanValueBase, QOverload<int>::of(&QComboBox::currentIndexChanged),
[this](int index) { updateScanValue(); });
connect(m_ui.scanSize, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) {
m_scanner.SetSize(static_cast<MemoryAccessSize>(index));
m_scanner.ResetSearch();
updateResults();
});
connect(m_ui.scanValueSigned, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) {
m_scanner.SetValueSigned(index == 0);
m_scanner.ResetSearch();
updateResults();
});
connect(m_ui.scanOperator, QOverload<int>::of(&QComboBox::currentIndexChanged),
[this](int index) { m_scanner.SetOperator(static_cast<MemoryScan::Operator>(index)); });
connect(m_ui.scanStartAddress, &QLineEdit::textChanged, [this](const QString& value) {
uint address;
if (value.startsWith(QStringLiteral("0x")) && value.length() > 2)
address = value.mid(2).toUInt(nullptr, 16);
else
address = value.toUInt(nullptr, 16);
m_scanner.SetStartAddress(static_cast<PhysicalMemoryAddress>(address));
});
connect(m_ui.scanEndAddress, &QLineEdit::textChanged, [this](const QString& value) {
uint address;
if (value.startsWith(QStringLiteral("0x")) && value.length() > 2)
address = value.mid(2).toUInt(nullptr, 16);
else
address = value.toUInt(nullptr, 16);
m_scanner.SetEndAddress(static_cast<PhysicalMemoryAddress>(address));
});
connect(m_ui.scanPresetRange, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) {
if (index == 0)
{
m_ui.scanStartAddress->setText(formatHexValue(0, 8));
m_ui.scanEndAddress->setText(formatHexValue(Bus::g_ram_size, 8));
}
else if (index == 1)
{
m_ui.scanStartAddress->setText(formatHexValue(CPU::SCRATCHPAD_ADDR, 8));
m_ui.scanEndAddress->setText(formatHexValue(CPU::SCRATCHPAD_ADDR + CPU::SCRATCHPAD_SIZE, 8));
}
else
{
m_ui.scanStartAddress->setText(formatHexValue(Bus::BIOS_BASE, 8));
m_ui.scanEndAddress->setText(formatHexValue(Bus::BIOS_BASE + Bus::BIOS_SIZE, 8));
}
});
connect(m_ui.scanNewSearch, &QPushButton::clicked, [this]() {
m_scanner.Search();
updateResults();
});
connect(m_ui.scanSearchAgain, &QPushButton::clicked, [this]() {
m_scanner.SearchAgain();
updateResults();
});
connect(m_ui.scanResetSearch, &QPushButton::clicked, [this]() {
m_scanner.ResetSearch();
updateResults();
});
connect(m_ui.scanAddWatch, &QPushButton::clicked, this, &MemoryScannerWindow::addToWatchClicked);
connect(m_ui.scanAddManualAddress, &QPushButton::clicked, this, &MemoryScannerWindow::addManualWatchAddressClicked);
connect(m_ui.scanRemoveWatch, &QPushButton::clicked, this, &MemoryScannerWindow::removeWatchClicked);
connect(m_ui.scanTable, &QTableWidget::currentItemChanged, this, &MemoryScannerWindow::scanCurrentItemChanged);
connect(m_ui.watchTable, &QTableWidget::currentItemChanged, this, &MemoryScannerWindow::watchCurrentItemChanged);
connect(m_ui.scanTable, &QTableWidget::itemChanged, this, &MemoryScannerWindow::scanItemChanged);
connect(m_ui.watchTable, &QTableWidget::itemChanged, this, &MemoryScannerWindow::watchItemChanged);
m_update_timer = new QTimer(this);
connect(m_update_timer, &QTimer::timeout, this, &MemoryScannerWindow::updateScanUi);
connect(g_emu_thread, &EmuThread::systemStarted, this, &MemoryScannerWindow::onSystemStarted);
connect(g_emu_thread, &EmuThread::systemDestroyed, this, &MemoryScannerWindow::onSystemDestroyed);
if (QtHost::IsSystemValid())
onSystemStarted();
else
enableUi(false);
}
void MemoryScannerWindow::enableUi(bool enabled)
{
const bool has_results = (m_scanner.GetResultCount() > 0);
m_ui.scanValue->setEnabled(enabled);
m_ui.scanValueBase->setEnabled(enabled);
m_ui.scanValueSigned->setEnabled(enabled);
m_ui.scanSize->setEnabled(enabled);
m_ui.scanOperator->setEnabled(enabled);
m_ui.scanStartAddress->setEnabled(enabled);
m_ui.scanEndAddress->setEnabled(enabled);
m_ui.scanPresetRange->setEnabled(enabled);
m_ui.scanResultCount->setEnabled(enabled);
m_ui.scanNewSearch->setEnabled(enabled);
m_ui.scanSearchAgain->setEnabled(enabled && has_results);
m_ui.scanResetSearch->setEnabled(enabled && has_results);
m_ui.scanAddWatch->setEnabled(enabled && !m_ui.scanTable->selectedItems().empty());
m_ui.watchTable->setEnabled(enabled);
m_ui.scanAddManualAddress->setEnabled(enabled);
m_ui.scanRemoveWatch->setEnabled(enabled && !m_ui.watchTable->selectedItems().empty());
}
void MemoryScannerWindow::showEvent(QShowEvent* event)
{
QWidget::showEvent(event);
resizeColumns();
}
void MemoryScannerWindow::closeEvent(QCloseEvent* event)
{
QWidget::closeEvent(event);
emit closed();
}
void MemoryScannerWindow::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
resizeColumns();
}
void MemoryScannerWindow::resizeColumns()
{
QtUtils::ResizeColumnsForTableView(m_ui.scanTable, {-1, 130, 130});
QtUtils::ResizeColumnsForTableView(m_ui.watchTable, {-1, 100, 100, 100, 40});
}
int MemoryScannerWindow::getSelectedResultIndexFirst() const
{
QList<QTableWidgetSelectionRange> sel = m_ui.scanTable->selectedRanges();
if (sel.isEmpty())
return -1;
return sel.front().topRow();
}
int MemoryScannerWindow::getSelectedResultIndexLast() const
{
QList<QTableWidgetSelectionRange> sel = m_ui.scanTable->selectedRanges();
if (sel.isEmpty())
return -1;
return sel.front().bottomRow();
}
int MemoryScannerWindow::getSelectedWatchIndexFirst() const
{
QList<QTableWidgetSelectionRange> sel = m_ui.watchTable->selectedRanges();
if (sel.isEmpty())
return -1;
return sel.front().topRow();
}
int MemoryScannerWindow::getSelectedWatchIndexLast() const
{
QList<QTableWidgetSelectionRange> sel = m_ui.watchTable->selectedRanges();
if (sel.isEmpty())
return -1;
return sel.front().bottomRow();
}
void MemoryScannerWindow::onSystemStarted()
{
if (!m_update_timer->isActive())
m_update_timer->start(SCAN_INTERVAL);
enableUi(true);
}
void MemoryScannerWindow::onSystemDestroyed()
{
if (m_update_timer->isActive())
m_update_timer->stop();
enableUi(false);
}
void MemoryScannerWindow::addToWatchClicked()
{
const int indexFirst = getSelectedResultIndexFirst();
const int indexLast = getSelectedResultIndexLast();
if (indexFirst < 0)
return;
for (int index = indexFirst; index <= indexLast; index++)
{
const MemoryScan::Result& res = m_scanner.GetResults()[static_cast<u32>(index)];
m_watch.AddEntry(fmt::format("0x{:08x}", res.address), res.address, m_scanner.GetSize(), m_scanner.GetValueSigned(),
false);
updateWatch();
}
}
void MemoryScannerWindow::addManualWatchAddressClicked()
{
std::optional<unsigned> address = QtUtils::PromptForAddress(this, windowTitle(), tr("Enter manual address:"), false);
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;
if (index == 1 || index == 4)
address.value() &= 0xFFFFFFFE;
else if (index == 2 || index == 5)
address.value() &= 0xFFFFFFFC;
m_watch.AddEntry(fmt::format("0x{:08x}", address.value()), address.value(), static_cast<MemoryAccessSize>(index % 3),
(index > 3), false);
updateWatch();
}
void MemoryScannerWindow::removeWatchClicked()
{
const int indexFirst = getSelectedWatchIndexFirst();
const int indexLast = getSelectedWatchIndexLast();
if (indexFirst < 0)
return;
for (int index = indexLast; index >= indexFirst; index--)
{
m_watch.RemoveEntry(static_cast<u32>(index));
updateWatch();
}
}
void MemoryScannerWindow::scanCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
{
m_ui.scanAddWatch->setEnabled((current != nullptr));
}
void MemoryScannerWindow::watchCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
{
m_ui.scanRemoveWatch->setEnabled((current != nullptr));
}
void MemoryScannerWindow::scanItemChanged(QTableWidgetItem* item)
{
const u32 index = static_cast<u32>(item->row());
switch (item->column())
{
case 1:
{
bool value_ok = false;
if (m_scanner.GetValueSigned())
{
int value = item->text().toInt(&value_ok);
if (value_ok)
m_scanner.SetResultValue(index, static_cast<u32>(value));
}
else
{
uint value = item->text().toUInt(&value_ok);
if (value_ok)
m_scanner.SetResultValue(index, static_cast<u32>(value));
}
}
break;
default:
break;
}
}
void MemoryScannerWindow::watchItemChanged(QTableWidgetItem* item)
{
const u32 index = static_cast<u32>(item->row());
if (index >= m_watch.GetEntryCount())
return;
switch (item->column())
{
case 4:
{
m_watch.SetEntryFreeze(index, (item->checkState() == Qt::Checked));
}
break;
case 0:
{
m_watch.SetEntryDescription(index, item->text().toStdString());
}
break;
case 3:
{
const MemoryWatchList::Entry& entry = m_watch.GetEntry(index);
bool value_ok = false;
if (entry.is_signed)
{
int value = item->text().toInt(&value_ok);
if (value_ok)
m_watch.SetEntryValue(index, static_cast<u32>(value));
}
else
{
uint value;
if (item->text()[1] == 'x' || item->text()[1] == 'X')
value = item->text().toUInt(&value_ok, 16);
else
value = item->text().toUInt(&value_ok);
if (value_ok)
m_watch.SetEntryValue(index, static_cast<u32>(value));
}
}
break;
default:
break;
}
}
void MemoryScannerWindow::updateScanValue()
{
QString value = m_ui.scanValue->text();
if (value.startsWith(QStringLiteral("0x")))
value.remove(0, 2);
bool ok = false;
uint uint_value = value.toUInt(&ok, (m_ui.scanValueBase->currentIndex() > 0) ? 16 : 10);
if (ok)
m_scanner.SetValue(uint_value);
}
void MemoryScannerWindow::updateResults()
{
QSignalBlocker sb(m_ui.scanTable);
m_ui.scanTable->setRowCount(0);
int row = 0;
const MemoryScan::ResultVector& results = m_scanner.GetResults();
for (const MemoryScan::Result& res : results)
{
if (row == MAX_DISPLAYED_SCAN_RESULTS)
break;
m_ui.scanTable->insertRow(row);
QTableWidgetItem* address_item = new QTableWidgetItem(formatHexValue(res.address, 8));
address_item->setFlags(address_item->flags() & ~(Qt::ItemIsEditable));
m_ui.scanTable->setItem(row, 0, address_item);
QTableWidgetItem* value_item;
if (m_ui.scanValueBase->currentIndex() == 0)
value_item = new QTableWidgetItem(formatValue(res.value, m_scanner.GetValueSigned()));
else if (m_scanner.GetSize() == MemoryAccessSize::Byte)
value_item = new QTableWidgetItem(formatHexValue(res.value, 2));
else if (m_scanner.GetSize() == MemoryAccessSize::HalfWord)
value_item = new QTableWidgetItem(formatHexValue(res.value, 4));
else
value_item = new QTableWidgetItem(formatHexValue(res.value, 8));
m_ui.scanTable->setItem(row, 1, value_item);
QTableWidgetItem* previous_item;
if (m_ui.scanValueBase->currentIndex() == 0)
previous_item = new QTableWidgetItem(formatValue(res.last_value, m_scanner.GetValueSigned()));
else if (m_scanner.GetSize() == MemoryAccessSize::Byte)
previous_item = new QTableWidgetItem(formatHexValue(res.last_value, 2));
else if (m_scanner.GetSize() == MemoryAccessSize::HalfWord)
previous_item = new QTableWidgetItem(formatHexValue(res.last_value, 4));
else
previous_item = new QTableWidgetItem(formatHexValue(res.last_value, 8));
previous_item->setFlags(address_item->flags() & ~(Qt::ItemIsEditable));
m_ui.scanTable->setItem(row, 2, previous_item);
row++;
}
m_ui.scanResultCount->setText((row < static_cast<int>(results.size())) ?
tr("%1 (only showing first %2)").arg(results.size()).arg(row) :
QString::number(m_scanner.GetResultCount()));
m_ui.scanResetSearch->setEnabled(!results.empty());
m_ui.scanSearchAgain->setEnabled(!results.empty());
m_ui.scanAddWatch->setEnabled(false);
}
void MemoryScannerWindow::updateResultsValues()
{
QSignalBlocker sb(m_ui.scanTable);
int row = 0;
for (const MemoryScan::Result& res : m_scanner.GetResults())
{
if (res.value_changed)
{
QTableWidgetItem* item = m_ui.scanTable->item(row, 1);
if (m_ui.scanValueBase->currentIndex() == 0)
item->setText(formatValue(res.value, m_scanner.GetValueSigned()));
else if (m_scanner.GetSize() == MemoryAccessSize::Byte)
item->setText(formatHexValue(res.value, 2));
else if (m_scanner.GetSize() == MemoryAccessSize::HalfWord)
item->setText(formatHexValue(res.value, 4));
else
item->setText(formatHexValue(res.value, 8));
item->setForeground(Qt::red);
}
row++;
if (row == MAX_DISPLAYED_SCAN_RESULTS)
break;
}
}
void MemoryScannerWindow::updateWatch()
{
m_watch.UpdateValues();
QSignalBlocker sb(m_ui.watchTable);
m_ui.watchTable->setRowCount(0);
const MemoryWatchList::EntryVector& entries = m_watch.GetEntries();
if (!entries.empty())
{
int row = 0;
for (const MemoryWatchList::Entry& res : entries)
{
m_ui.watchTable->insertRow(row);
QTableWidgetItem* description_item = new QTableWidgetItem(formatCheatCode(res.address, res.value, res.size));
m_ui.watchTable->setItem(row, 0, description_item);
QTableWidgetItem* address_item = new QTableWidgetItem(formatHexValue(res.address, 8));
address_item->setFlags(address_item->flags() & ~(Qt::ItemIsEditable));
m_ui.watchTable->setItem(row, 1, address_item);
QTableWidgetItem* size_item =
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, 2, size_item);
QTableWidgetItem* value_item;
if (res.size == MemoryAccessSize::Byte)
value_item = new QTableWidgetItem(formatHexAndDecValue(res.value, 2, res.is_signed));
else if (res.size == MemoryAccessSize::HalfWord)
value_item = new QTableWidgetItem(formatHexAndDecValue(res.value, 4, res.is_signed));
else
value_item = new QTableWidgetItem(formatHexAndDecValue(res.value, 8, res.is_signed));
m_ui.watchTable->setItem(row, 3, value_item);
QTableWidgetItem* freeze_item = new QTableWidgetItem();
freeze_item->setFlags(freeze_item->flags() | (Qt::ItemIsEditable | Qt::ItemIsUserCheckable));
freeze_item->setCheckState(res.freeze ? Qt::Checked : Qt::Unchecked);
m_ui.watchTable->setItem(row, 4, freeze_item);
row++;
}
}
m_ui.scanSaveWatch->setEnabled(!entries.empty());
m_ui.scanRemoveWatch->setEnabled(false);
}
void MemoryScannerWindow::updateWatchValues()
{
QSignalBlocker sb(m_ui.watchTable);
int row = 0;
for (const MemoryWatchList::Entry& res : m_watch.GetEntries())
{
if (res.changed)
{
if (m_ui.scanValueBase->currentIndex() == 0)
m_ui.watchTable->item(row, 3)->setText(formatValue(res.value, res.is_signed));
else if (m_scanner.GetSize() == MemoryAccessSize::Byte)
m_ui.watchTable->item(row, 3)->setText(formatHexValue(res.value, 2));
else if (m_scanner.GetSize() == MemoryAccessSize::HalfWord)
m_ui.watchTable->item(row, 3)->setText(formatHexValue(res.value, 4));
else
m_ui.watchTable->item(row, 3)->setText(formatHexValue(res.value, 8));
}
row++;
}
}
void MemoryScannerWindow::updateScanUi()
{
m_scanner.UpdateResultsValues();
m_watch.UpdateValues();
updateResultsValues();
updateWatchValues();
}