all repos — mgba @ cf7017dd867a542f3808f1e6287b683da92d0553

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	}
 91	if (m_ui.typeStr->isChecked()) {
 92		params->type = mCORE_MEMORY_SEARCH_STRING;
 93		m_string = m_ui.value->text().toLocal8Bit();
 94		params->valueStr = m_string.constData();
 95		ok = true;
 96	}
 97	return ok;
 98}
 99
100void MemorySearch::search() {
101	mCoreMemorySearchResultsClear(&m_results);
102
103	mCoreMemorySearchParams params;
104
105	GameController::Interrupter interrupter(m_controller);
106	if (!m_controller->isLoaded()) {
107		return;
108	}
109	mCore* core = m_controller->thread()->core;
110
111	if (createParams(&params)) {
112		mCoreMemorySearch(core, &params, &m_results, LIMIT);
113	}
114
115	refresh();
116}
117
118void MemorySearch::searchWithin() {
119	mCoreMemorySearchParams params;
120
121	GameController::Interrupter interrupter(m_controller);
122	if (!m_controller->isLoaded()) {
123		return;
124	}
125	mCore* core = m_controller->thread()->core;
126
127	if (createParams(&params)) {
128		mCoreMemorySearchRepeat(core, &params, &m_results);
129	}
130
131	refresh();
132}
133
134void MemorySearch::refresh() {
135	GameController::Interrupter interrupter(m_controller);
136	if (!m_controller->isLoaded()) {
137		return;
138	}
139	mCore* core = m_controller->thread()->core;
140
141	m_ui.results->clearContents();
142	m_ui.results->setRowCount(mCoreMemorySearchResultsSize(&m_results));
143	for (size_t i = 0; i < mCoreMemorySearchResultsSize(&m_results); ++i) {
144		mCoreMemorySearchResult* result = mCoreMemorySearchResultsGetPointer(&m_results, i);
145		QTableWidgetItem* item = new QTableWidgetItem(QString("%1").arg(result->address, 8, 16, QChar('0')));
146		m_ui.results->setItem(i, 0, item);
147		if (m_ui.numHex->isChecked()) {
148			switch (result->type) {
149			case mCORE_MEMORY_SEARCH_8:
150				item = new QTableWidgetItem(QString("%1").arg(core->rawRead8(core, result->address, result->segment), 2, 16, QChar('0')));
151				break;
152			case mCORE_MEMORY_SEARCH_16:
153				item = new QTableWidgetItem(QString("%1").arg(core->rawRead16(core, result->address, result->segment), 4, 16, QChar('0')));
154				break;
155			case mCORE_MEMORY_SEARCH_GUESS:
156			case mCORE_MEMORY_SEARCH_32:
157				item = new QTableWidgetItem(QString("%1").arg(core->rawRead32(core, result->address, result->segment), 8, 16, QChar('0')));
158				break;
159			case mCORE_MEMORY_SEARCH_STRING:
160				item = new QTableWidgetItem("?"); // TODO
161			}
162		} else {
163			switch (result->type) {
164			case mCORE_MEMORY_SEARCH_8:
165				item = new QTableWidgetItem(QString::number(core->rawRead8(core, result->address, result->segment)));
166				break;
167			case mCORE_MEMORY_SEARCH_16:
168				item = new QTableWidgetItem(QString::number(core->rawRead16(core, result->address, result->segment)));
169				break;
170			case mCORE_MEMORY_SEARCH_GUESS:
171			case mCORE_MEMORY_SEARCH_32:
172				item = new QTableWidgetItem(QString::number(core->rawRead32(core, result->address, result->segment)));
173				break;
174			case mCORE_MEMORY_SEARCH_STRING:
175				item = new QTableWidgetItem("?"); // TODO
176			}
177		}
178		m_ui.results->setItem(i, 1, item);
179	}
180	m_ui.results->sortItems(0);
181}