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