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