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(¶ms)) {
119 mCoreMemorySearch(core, ¶ms, &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(¶ms)) {
135 mCoreMemorySearchRepeat(core, ¶ms, &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}