CheatSearchWidget: New feature, writing a value to all selected addresses
This commit is contained in:
parent
7317124e61
commit
0cfd28f33a
|
@ -505,6 +505,23 @@ bool Cheats::CheatSearchSession<T>::WasFirstSearchDone() const
|
||||||
return m_first_search_done;
|
return m_first_search_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool Cheats::CheatSearchSession<T>::WriteValue(const Core::CPUThreadGuard& guard,
|
||||||
|
std::span<u32> addresses) const
|
||||||
|
{
|
||||||
|
if (!m_value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
T value = m_value.value();
|
||||||
|
bool result = true;
|
||||||
|
for (auto address : addresses)
|
||||||
|
{
|
||||||
|
if (!PowerPC::MMU::HostTryWrite<T>(guard, value, address, m_address_space).has_value())
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::unique_ptr<Cheats::CheatSearchSessionBase> Cheats::CheatSearchSession<T>::Clone() const
|
std::unique_ptr<Cheats::CheatSearchSessionBase> Cheats::CheatSearchSession<T>::Clone() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -165,6 +166,8 @@ public:
|
||||||
virtual SearchResultValueState GetResultValueState(size_t index) const = 0;
|
virtual SearchResultValueState GetResultValueState(size_t index) const = 0;
|
||||||
virtual bool WasFirstSearchDone() const = 0;
|
virtual bool WasFirstSearchDone() const = 0;
|
||||||
|
|
||||||
|
virtual bool WriteValue(const Core::CPUThreadGuard& guard, std::span<u32> addresses) const = 0;
|
||||||
|
|
||||||
// Create a complete copy of this search session.
|
// Create a complete copy of this search session.
|
||||||
virtual std::unique_ptr<CheatSearchSessionBase> Clone() const = 0;
|
virtual std::unique_ptr<CheatSearchSessionBase> Clone() const = 0;
|
||||||
|
|
||||||
|
@ -212,6 +215,8 @@ public:
|
||||||
SearchResultValueState GetResultValueState(size_t index) const override;
|
SearchResultValueState GetResultValueState(size_t index) const override;
|
||||||
bool WasFirstSearchDone() const override;
|
bool WasFirstSearchDone() const override;
|
||||||
|
|
||||||
|
bool WriteValue(const Core::CPUThreadGuard& guard, std::span<u32> addresses) const override;
|
||||||
|
|
||||||
std::unique_ptr<CheatSearchSessionBase> Clone() const override;
|
std::unique_ptr<CheatSearchSessionBase> Clone() const override;
|
||||||
std::unique_ptr<CheatSearchSessionBase> ClonePartial(size_t begin_index,
|
std::unique_ptr<CheatSearchSessionBase> ClonePartial(size_t begin_index,
|
||||||
size_t end_index) const override;
|
size_t end_index) const override;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
#include <QInputDialog>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
@ -491,13 +492,14 @@ void CheatSearchWidget::OnAddressTableContextMenu()
|
||||||
if (m_address_table->selectedItems().isEmpty())
|
if (m_address_table->selectedItems().isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto* item = m_address_table->selectedItems()[0];
|
|
||||||
const u32 address = item->data(ADDRESS_TABLE_ADDRESS_ROLE).toUInt();
|
|
||||||
|
|
||||||
QMenu* menu = new QMenu(this);
|
QMenu* menu = new QMenu(this);
|
||||||
menu->setAttribute(Qt::WA_DeleteOnClose, true);
|
menu->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||||
|
|
||||||
menu->addAction(tr("Show in memory"), [this, address] { emit ShowMemory(address); });
|
menu->addAction(tr("Show in memory"), this, [this] {
|
||||||
|
auto* item = m_address_table->selectedItems()[0];
|
||||||
|
const u32 address = item->data(ADDRESS_TABLE_ADDRESS_ROLE).toUInt();
|
||||||
|
emit ShowMemory(address);
|
||||||
|
});
|
||||||
menu->addAction(tr("Add to watch"), this, [this] {
|
menu->addAction(tr("Add to watch"), this, [this] {
|
||||||
for (auto* const item : m_address_table->selectedItems())
|
for (auto* const item : m_address_table->selectedItems())
|
||||||
{
|
{
|
||||||
|
@ -507,6 +509,7 @@ void CheatSearchWidget::OnAddressTableContextMenu()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu->addAction(tr("Generate Action Replay Code(s)"), this, &CheatSearchWidget::GenerateARCodes);
|
menu->addAction(tr("Generate Action Replay Code(s)"), this, &CheatSearchWidget::GenerateARCodes);
|
||||||
|
menu->addAction(tr("Write value"), this, &CheatSearchWidget::WriteValue);
|
||||||
|
|
||||||
menu->exec(QCursor::pos());
|
menu->exec(QCursor::pos());
|
||||||
}
|
}
|
||||||
|
@ -589,10 +592,40 @@ void CheatSearchWidget::GenerateARCodes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheatSearchWidget::WriteValue()
|
||||||
|
{
|
||||||
|
if (m_address_table->selectedItems().isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool ok{};
|
||||||
|
QString text = QInputDialog::getText(this, tr("Write value"), tr("Value:"), QLineEdit::Normal,
|
||||||
|
QString{}, &ok);
|
||||||
|
|
||||||
|
if (ok && m_session->SetValueFromString(text.toStdString(),
|
||||||
|
m_parse_values_as_hex_checkbox->isChecked()))
|
||||||
|
{
|
||||||
|
auto items = m_address_table->selectedItems();
|
||||||
|
std::vector<u32> addresses(items.size());
|
||||||
|
std::transform(items.begin(), items.end(), addresses.begin(), [](QTableWidgetItem* item) {
|
||||||
|
return item->data(ADDRESS_TABLE_ADDRESS_ROLE).toUInt();
|
||||||
|
});
|
||||||
|
|
||||||
|
Core::CPUThreadGuard guard{m_system};
|
||||||
|
if (!m_session->WriteValue(guard, std::span<u32>(addresses)))
|
||||||
|
{
|
||||||
|
m_info_label_1->setText(tr("There was an error writing (some) values."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_info_label_1->setText(tr("Invalid value."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CheatSearchWidget::RefreshCurrentValueTableItem(
|
void CheatSearchWidget::RefreshCurrentValueTableItem(
|
||||||
QTableWidgetItem* const current_value_table_item)
|
QTableWidgetItem* const current_value_table_item)
|
||||||
{
|
{
|
||||||
const auto address = current_value_table_item->data(ADDRESS_TABLE_ADDRESS_ROLE).toUInt();
|
const u32 address = current_value_table_item->data(ADDRESS_TABLE_ADDRESS_ROLE).toUInt();
|
||||||
const auto curr_val_iter = m_address_table_current_values.find(address);
|
const auto curr_val_iter = m_address_table_current_values.find(address);
|
||||||
if (curr_val_iter != m_address_table_current_values.end())
|
if (curr_val_iter != m_address_table_current_values.end())
|
||||||
current_value_table_item->setText(QString::fromStdString(curr_val_iter->second));
|
current_value_table_item->setText(QString::fromStdString(curr_val_iter->second));
|
||||||
|
|
|
@ -71,6 +71,7 @@ private:
|
||||||
UpdateSource source);
|
UpdateSource source);
|
||||||
void RecreateGUITable();
|
void RecreateGUITable();
|
||||||
void GenerateARCodes();
|
void GenerateARCodes();
|
||||||
|
void WriteValue();
|
||||||
int GetVisibleRowsBeginIndex() const;
|
int GetVisibleRowsBeginIndex() const;
|
||||||
int GetVisibleRowsEndIndex() const;
|
int GetVisibleRowsEndIndex() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue