all repos — mgba @ b399afdf9f2113bfefee04d89c481b4ca1a8a61f

mGBA Game Boy Advance Emulator

src/platform/qt/MemorySearch.cpp (view raw)

  1/* Copyright (c) 2013-2017 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6
  7#include "MemorySearch.h"
  8
  9#include <mgba/core/core.h>
 10
 11#include "GameController.h"
 12#include "MemoryView.h"
 13
 14using namespace QGBA;
 15
 16MemorySearch::MemorySearch(GameController* controller, QWidget* parent)
 17	: QWidget(parent)
 18	, m_controller(controller)
 19{
 20	m_ui.setupUi(this);
 21
 22	mCoreMemorySearchResultsInit(&m_results, 0);
 23	connect(m_ui.search, &QPushButton::clicked, this, &MemorySearch::search);
 24	connect(m_ui.searchWithin, &QPushButton::clicked, this, &MemorySearch::searchWithin);
 25	connect(m_ui.refresh, &QPushButton::clicked, this, &MemorySearch::refresh);
 26	connect(m_ui.numHex, &QPushButton::clicked, this, &MemorySearch::refresh);
 27	connect(m_ui.numDec, &QPushButton::clicked, this, &MemorySearch::refresh);
 28	connect(m_ui.viewMem, &QPushButton::clicked, this, &MemorySearch::openMemory);
 29}
 30
 31MemorySearch::~MemorySearch() {
 32	mCoreMemorySearchResultsDeinit(&m_results);
 33}
 34
 35bool MemorySearch::createParams(mCoreMemorySearchParams* params) {
 36	params->memoryFlags = mCORE_MEMORY_RW;
 37	mCore* core = m_controller->thread()->core;
 38
 39	QByteArray string;
 40	bool ok = false;
 41	if (m_ui.typeNum->isChecked()) {
 42		if (m_ui.bits8->isChecked()) {
 43			params->type = mCORE_MEMORY_SEARCH_8;
 44		}
 45		if (m_ui.bits16->isChecked()) {
 46			params->type = mCORE_MEMORY_SEARCH_16;
 47		}
 48		if (m_ui.bits32->isChecked()) {
 49			params->type = mCORE_MEMORY_SEARCH_32;
 50		}
 51		if (m_ui.numHex->isChecked()) {
 52			uint32_t v = m_ui.value->text().toUInt(&ok, 16);
 53			if (ok) {
 54				switch (params->type) {
 55				case mCORE_MEMORY_SEARCH_8:
 56					ok = v < 0x100;
 57					params->value8 = v;
 58					break;
 59				case mCORE_MEMORY_SEARCH_16:
 60					ok = v < 0x10000;
 61					params->value16 = v;
 62					break;
 63				case mCORE_MEMORY_SEARCH_32:
 64					params->value32 = v;
 65					break;
 66				default:
 67					ok = false;
 68				}
 69			}
 70		}
 71		if (m_ui.numDec->isChecked()) {
 72			uint32_t v = m_ui.value->text().toUInt(&ok, 10);
 73			if (ok) {
 74				switch (params->type) {
 75				case mCORE_MEMORY_SEARCH_8:
 76					ok = v < 0x100;
 77					params->value8 = v;
 78					break;
 79				case mCORE_MEMORY_SEARCH_16:
 80					ok = v < 0x10000;
 81					params->value16 = v;
 82					break;
 83				case mCORE_MEMORY_SEARCH_32:
 84					params->value32 = v;
 85					break;
 86				default:
 87					ok = false;
 88				}
 89			}
 90		}
 91		if (m_ui.numGuess->isChecked()) {
 92			params->type = mCORE_MEMORY_SEARCH_GUESS;
 93			m_string = m_ui.value->text().toLocal8Bit();
 94			params->valueStr = m_string.constData();
 95			ok = true;
 96		}
 97	}
 98	if (m_ui.typeStr->isChecked()) {
 99		params->type = mCORE_MEMORY_SEARCH_STRING;
100		m_string = m_ui.value->text().toLocal8Bit();
101		params->valueStr = m_string.constData();
102		ok = true;
103	}
104	return ok;
105}
106
107void MemorySearch::search() {
108	mCoreMemorySearchResultsClear(&m_results);
109
110	mCoreMemorySearchParams params;
111
112	GameController::Interrupter interrupter(m_controller);
113	if (!m_controller->isLoaded()) {
114		return;
115	}
116	mCore* core = m_controller->thread()->core;
117
118	if (createParams(&params)) {
119		mCoreMemorySearch(core, &params, &m_results, LIMIT);
120	}
121
122	refresh();
123}
124
125void MemorySearch::searchWithin() {
126	mCoreMemorySearchParams params;
127
128	GameController::Interrupter interrupter(m_controller);
129	if (!m_controller->isLoaded()) {
130		return;
131	}
132	mCore* core = m_controller->thread()->core;
133
134	if (createParams(&params)) {
135		mCoreMemorySearchRepeat(core, &params, &m_results);
136	}
137
138	refresh();
139}
140
141void MemorySearch::refresh() {
142	GameController::Interrupter interrupter(m_controller);
143	if (!m_controller->isLoaded()) {
144		return;
145	}
146	mCore* core = m_controller->thread()->core;
147
148	m_ui.results->clearContents();
149	m_ui.results->setRowCount(mCoreMemorySearchResultsSize(&m_results));
150	for (size_t i = 0; i < mCoreMemorySearchResultsSize(&m_results); ++i) {
151		mCoreMemorySearchResult* result = mCoreMemorySearchResultsGetPointer(&m_results, i);
152		QTableWidgetItem* item = new QTableWidgetItem(QString("%1").arg(result->address, 8, 16, QChar('0')));
153		m_ui.results->setItem(i, 0, item);
154		if (m_ui.numHex->isChecked()) {
155			switch (result->type) {
156			case mCORE_MEMORY_SEARCH_8:
157				item = new QTableWidgetItem(QString("%1").arg(core->rawRead8(core, result->address, result->segment), 2, 16, QChar('0')));
158				break;
159			case mCORE_MEMORY_SEARCH_16:
160				item = new QTableWidgetItem(QString("%1").arg(core->rawRead16(core, result->address, result->segment), 4, 16, QChar('0')));
161				break;
162			case mCORE_MEMORY_SEARCH_GUESS:
163			case mCORE_MEMORY_SEARCH_32:
164				item = new QTableWidgetItem(QString("%1").arg(core->rawRead32(core, result->address, result->segment), 8, 16, QChar('0')));
165				break;
166			case mCORE_MEMORY_SEARCH_STRING:
167				item = new QTableWidgetItem("?"); // TODO
168			}
169		} else {
170			switch (result->type) {
171			case mCORE_MEMORY_SEARCH_8:
172				item = new QTableWidgetItem(QString::number(core->rawRead8(core, result->address, result->segment)));
173				break;
174			case mCORE_MEMORY_SEARCH_16:
175				item = new QTableWidgetItem(QString::number(core->rawRead16(core, result->address, result->segment)));
176				break;
177			case mCORE_MEMORY_SEARCH_GUESS:
178			case mCORE_MEMORY_SEARCH_32:
179				item = new QTableWidgetItem(QString::number(core->rawRead32(core, result->address, result->segment)));
180				break;
181			case mCORE_MEMORY_SEARCH_STRING:
182				item = new QTableWidgetItem("?"); // TODO
183			}
184		}
185		m_ui.results->setItem(i, 1, item);
186	}
187	m_ui.results->sortItems(0);
188}
189
190void MemorySearch::openMemory() {
191	auto items = m_ui.results->selectedItems();
192	if (items.empty()) {
193		return;
194	}
195	QTableWidgetItem* item = items[0];
196	uint32_t address = item->text().toUInt(nullptr, 16);
197
198	MemoryView* memView = new MemoryView(m_controller);
199	memView->jumpToAddress(address);
200
201	connect(m_controller, &GameController::gameStopped, memView, &QWidget::close);
202	memView->setAttribute(Qt::WA_DeleteOnClose);
203	memView->show();
204}