all repos — mgba @ a4faf9f07956bbb27c89be21eca9b541f6d84853

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
 13using namespace QGBA;
 14
 15MemorySearch::MemorySearch(GameController* controller, QWidget* parent)
 16	: QWidget(parent)
 17	, m_controller(controller)
 18{
 19	m_ui.setupUi(this);
 20
 21	mCoreMemorySearchResultsInit(&m_results, 0);
 22	connect(m_ui.search, &QPushButton::clicked, this, &MemorySearch::search);
 23	connect(m_ui.searchWithin, &QPushButton::clicked, this, &MemorySearch::searchWithin);
 24	connect(m_ui.refresh, &QPushButton::clicked, this, &MemorySearch::refresh);
 25	connect(m_ui.numHex, &QPushButton::clicked, this, &MemorySearch::refresh);
 26	connect(m_ui.numDec, &QPushButton::clicked, this, &MemorySearch::refresh);
 27}
 28
 29MemorySearch::~MemorySearch() {
 30	mCoreMemorySearchResultsDeinit(&m_results);
 31}
 32
 33bool MemorySearch::createParams(mCoreMemorySearchParams* params) {
 34	params->memoryFlags = mCORE_MEMORY_RW;
 35	mCore* core = m_controller->thread()->core;
 36
 37	QByteArray string;
 38	bool ok = false;
 39	if (m_ui.typeNum->isChecked()) {
 40		if (m_ui.bits8->isChecked()) {
 41			params->type = mCORE_MEMORY_SEARCH_8;
 42		}
 43		if (m_ui.bits16->isChecked()) {
 44			params->type = mCORE_MEMORY_SEARCH_16;
 45		}
 46		if (m_ui.bits32->isChecked()) {
 47			params->type = mCORE_MEMORY_SEARCH_32;
 48		}
 49		if (m_ui.numHex->isChecked()) {
 50			bool ok;
 51			uint32_t v = m_ui.value->text().toUInt(&ok, 16);
 52			if (ok) {
 53				switch (params->type) {
 54				case mCORE_MEMORY_SEARCH_8:
 55					ok = v < 0x100;
 56					params->value8 = v;
 57					break;
 58				case mCORE_MEMORY_SEARCH_16:
 59					ok = v < 0x10000;
 60					params->value16 = v;
 61					break;
 62				case mCORE_MEMORY_SEARCH_32:
 63					params->value32 = v;
 64					break;
 65				default:
 66					ok = false;
 67				}
 68			}
 69		}
 70		if (m_ui.numDec->isChecked()) {
 71			uint32_t v = m_ui.value->text().toUInt(&ok, 10);
 72			if (ok) {
 73				switch (params->type) {
 74				case mCORE_MEMORY_SEARCH_8:
 75					ok = v < 0x100;
 76					params->value8 = v;
 77					break;
 78				case mCORE_MEMORY_SEARCH_16:
 79					ok = v < 0x10000;
 80					params->value16 = v;
 81					break;
 82				case mCORE_MEMORY_SEARCH_32:
 83					params->value32 = v;
 84					break;
 85				default:
 86					ok = false;
 87				}
 88			}
 89		}
 90		if (m_ui.numGuess->isChecked()) {
 91			params->type = mCORE_MEMORY_SEARCH_GUESS;
 92			m_string = m_ui.value->text().toLocal8Bit();
 93			params->valueStr = m_string.constData();
 94			ok = true;
 95		}
 96	}
 97	if (m_ui.typeStr->isChecked()) {
 98		params->type = mCORE_MEMORY_SEARCH_STRING;
 99		m_string = m_ui.value->text().toLocal8Bit();
100		params->valueStr = m_string.constData();
101		ok = true;
102	}
103	return ok;
104}
105
106void MemorySearch::search() {
107	mCoreMemorySearchResultsClear(&m_results);
108
109	mCoreMemorySearchParams params;
110
111	GameController::Interrupter interrupter(m_controller);
112	if (!m_controller->isLoaded()) {
113		return;
114	}
115	mCore* core = m_controller->thread()->core;
116
117	if (createParams(&params)) {
118		mCoreMemorySearch(core, &params, &m_results, LIMIT);
119	}
120
121	refresh();
122}
123
124void MemorySearch::searchWithin() {
125	mCoreMemorySearchParams params;
126
127	GameController::Interrupter interrupter(m_controller);
128	if (!m_controller->isLoaded()) {
129		return;
130	}
131	mCore* core = m_controller->thread()->core;
132
133	if (createParams(&params)) {
134		mCoreMemorySearchRepeat(core, &params, &m_results);
135	}
136
137	refresh();
138}
139
140void MemorySearch::refresh() {
141	GameController::Interrupter interrupter(m_controller);
142	if (!m_controller->isLoaded()) {
143		return;
144	}
145	mCore* core = m_controller->thread()->core;
146
147	m_ui.results->clearContents();
148	m_ui.results->setRowCount(mCoreMemorySearchResultsSize(&m_results));
149	for (size_t i = 0; i < mCoreMemorySearchResultsSize(&m_results); ++i) {
150		mCoreMemorySearchResult* result = mCoreMemorySearchResultsGetPointer(&m_results, i);
151		QTableWidgetItem* item = new QTableWidgetItem(QString("%1").arg(result->address, 8, 16, QChar('0')));
152		m_ui.results->setItem(i, 0, item);
153		if (m_ui.numHex->isChecked()) {
154			switch (result->type) {
155			case mCORE_MEMORY_SEARCH_8:
156				item = new QTableWidgetItem(QString("%1").arg(core->rawRead8(core, result->address, result->segment), 2, 16, QChar('0')));
157				break;
158			case mCORE_MEMORY_SEARCH_16:
159				item = new QTableWidgetItem(QString("%1").arg(core->rawRead16(core, result->address, result->segment), 4, 16, QChar('0')));
160				break;
161			case mCORE_MEMORY_SEARCH_GUESS:
162			case mCORE_MEMORY_SEARCH_32:
163				item = new QTableWidgetItem(QString("%1").arg(core->rawRead32(core, result->address, result->segment), 8, 16, QChar('0')));
164				break;
165			case mCORE_MEMORY_SEARCH_STRING:
166				item = new QTableWidgetItem("?"); // TODO
167			}
168		} else {
169			switch (result->type) {
170			case mCORE_MEMORY_SEARCH_8:
171				item = new QTableWidgetItem(QString::number(core->rawRead8(core, result->address, result->segment)));
172				break;
173			case mCORE_MEMORY_SEARCH_16:
174				item = new QTableWidgetItem(QString::number(core->rawRead16(core, result->address, result->segment)));
175				break;
176			case mCORE_MEMORY_SEARCH_GUESS:
177			case mCORE_MEMORY_SEARCH_32:
178				item = new QTableWidgetItem(QString::number(core->rawRead32(core, result->address, result->segment)));
179				break;
180			case mCORE_MEMORY_SEARCH_STRING:
181				item = new QTableWidgetItem("?"); // TODO
182			}
183		}
184		m_ui.results->setItem(i, 1, item);
185	}
186	m_ui.results->sortItems(0);
187}