1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3 #include "searchwidget.h"
4 #include "dockwidget.h"
5 #include "utils.h"
6 #include "../../core/schedule.h"
7 #include "../../core/link.h"
8 #include "../../core/mem.h"
9
10 #include <QtGui/QClipboard>
11 #include <QtCore/QFileInfo>
12 #include <QtCore/QRegularExpression>
13 #include <QtWidgets/QMessageBox>
14 #include <QtWidgets/QInputDialog>
15 #include <QtWidgets/QScrollBar>
16
17 #ifdef _MSC_VER
18 #include <direct.h>
19 #define chdir _chdir
20 #else
21 #include <unistd.h>
22 #endif
23
24 // ------------------------------------------------
25 // Hex Editor Things
26 // ------------------------------------------------
27
getAddressString(const QString & string,bool * ok)28 QString MainWindow::getAddressString(const QString& string, bool* ok) {
29 QString address = QInputDialog::getText(this, tr("Goto"),
30 tr("Input Address (Or Equate):"), QLineEdit::Normal,
31 string, ok).toUpper();
32
33 QString exists = getAddressOfEquate(address.toUpper().toStdString());
34 if (!exists.isEmpty()) {
35 return exists;
36 }
37
38 return int2hex(static_cast<uint32_t>(hex2int(address)), 6);
39 }
40
flashUpdate()41 void MainWindow::flashUpdate() {
42 if (!guiEmuValid) {
43 return;
44 }
45
46 ui->flashEdit->setData({reinterpret_cast<const char *>(mem.flash.block), 0x400000});
47 }
48
ramUpdate()49 void MainWindow::ramUpdate() {
50 if (!guiEmuValid) {
51 return;
52 }
53
54 ui->ramEdit->setBase(0xD00000);
55 ui->ramEdit->setData({reinterpret_cast<const char *>(mem.ram.block), 0x65800});
56 }
57
memUpdateEdit(HexWidget * edit,bool force)58 void MainWindow::memUpdateEdit(HexWidget *edit, bool force) {
59 if (edit == Q_NULLPTR || !guiEmuValid) {
60 return;
61 }
62
63 QByteArray data;
64
65 if (force || edit->getScrolled() || !edit->getSize()) {
66 bool second = edit->getCursorOffset() & 1;
67 int off = edit->getOffset();
68 int base = edit->getBase();
69 int addr = off + base;
70 int start = addr - 0x1000;
71 int end = addr + 0x1000;
72 off = 0x1000;
73
74 if (start < 0) {
75 off += start;
76 start = 0;
77 }
78 if (end > 0xFFFFFF) {
79 end = 0xFFFFFF;
80 }
81 data.resize(end - start + 1);
82
83 for (int j = 0, i = start; i < end; j++, i++) {
84 data[j] = static_cast<char>(mem_peek_byte(static_cast<uint32_t>(i)));
85 }
86
87 edit->setBase(start);
88 edit->setData(data);
89 if (second) {
90 edit->setCursorOffset(off * 2 + 1);
91 } else {
92 edit->setOffset(off);
93 }
94 } else {
95 int start = edit->getBase();
96 int len = edit->getSize();
97 data.resize(len);
98
99 for (int j = 0, i = start; j < len; j++, i++) {
100 data[j] = static_cast<char>(mem_peek_byte(static_cast<uint32_t>(i)));
101 }
102
103 edit->setData(data);
104 }
105 }
106
flashGotoPressed()107 void MainWindow::flashGotoPressed() {
108 bool accept = false;
109 QString addrStr = getAddressString(m_flashGotoAddr, &accept);
110
111 if (accept) {
112 m_flashGotoAddr = addrStr;
113 ui->flashEdit->setFocus();
114 ui->flashEdit->setOffset(hex2int(addrStr));
115 }
116 }
117
ramGotoPressed()118 void MainWindow::ramGotoPressed() {
119 bool accept = false;
120 QString addrStr = getAddressString(m_RamGotoAddr, &accept);
121
122 if (accept) {
123 m_RamGotoAddr = addrStr;
124 ui->ramEdit->setFocus();
125 ui->ramEdit->setOffset(hex2int(addrStr) - 0xD00000);
126 }
127 }
128
memSearchEdit(HexWidget * edit)129 void MainWindow::memSearchEdit(HexWidget *edit) {
130 if (edit == Q_NULLPTR) {
131 return;
132 }
133
134 SearchWidget search(m_searchStr, m_searchMode);
135 int searchMode, found = 0;
136 search.show();
137
138 if ((searchMode = search.exec()) == SearchWidget::Cancel) {
139 return;
140 }
141
142 m_searchMode = search.getType();
143 m_searchStr = search.getSearchString();
144
145 QString searchString;
146 if (m_searchMode == SearchWidget::Hex) {
147 searchString = m_searchStr;
148 } else {
149 searchString = QString::fromStdString(m_searchStr.toLatin1().toHex().toStdString());
150 }
151
152 edit->setFocus();
153 std::string s = searchString.toUpper().toStdString();
154 if (searchString.isEmpty() || (searchString.length() & 1) || s.find_first_not_of("0123456789ABCDEF") != std::string::npos) {
155 QMessageBox::critical(this, MSG_ERROR, tr("Error when reading input string"));
156 return;
157 }
158
159 QByteArray searchBa = QByteArray::fromHex(searchString.toLatin1());
160
161 switch (searchMode) {
162 default:
163 case SearchWidget::NextNot:
164 found = edit->indexNotOf(searchBa);
165 break;
166 case SearchWidget::Prev:
167 found = edit->indexPrevOf(searchBa);
168 break;
169 case SearchWidget::PrevNot:
170 found = edit->indexPrevNotOf(searchBa);
171 break;
172 case SearchWidget::Next:
173 found = edit->indexOf(searchBa);
174 break;
175 }
176
177 if (found == -1) {
178 QMessageBox::warning(this, MSG_WARNING, tr("String not found."));
179 }
180 }
181
memGoto(HexWidget * edit,uint32_t address)182 void MainWindow::memGoto(HexWidget *edit, uint32_t address) {
183 if (edit == Q_NULLPTR) {
184 return;
185 }
186
187 edit->setBase(static_cast<int>(address));
188 edit->setOffset(0);
189 memUpdateEdit(edit, true);
190 }
191
memGotoEdit(HexWidget * edit)192 void MainWindow::memGotoEdit(HexWidget *edit) {
193 if (edit == Q_NULLPTR) {
194 return;
195 }
196
197 bool accept = false;
198 QString address = getAddressString(m_memGotoAddr, &accept);
199
200 if (accept) {
201 memGoto(edit, static_cast<uint32_t>(hex2int(m_memGotoAddr = address)));
202 }
203 }
204
memSync(HexWidget * edit)205 void MainWindow::memSync(HexWidget *edit) {
206 if (edit == Q_NULLPTR) {
207 return;
208 }
209
210 debugPopulate();
211 disasmUpdateAddr(m_disasmAddr, m_disasmPane);
212 edit->setFocus();
213 }
214
flashSyncPressed()215 void MainWindow::flashSyncPressed() {
216 if (ui->flashEdit->modifiedCount()) {
217 memcpy(mem.flash.block, ui->flashEdit->data(), 0x400000);
218 }
219 memSync(ui->flashEdit);
220 }
221
ramSyncPressed()222 void MainWindow::ramSyncPressed() {
223 if (ui->ramEdit->modifiedCount()) {
224 memcpy(mem.ram.block, ui->ramEdit->data(), 0x65800);
225 }
226 memSync(ui->ramEdit);
227 }
228
memSyncEdit(HexWidget * edit)229 void MainWindow::memSyncEdit(HexWidget *edit) {
230 if (edit == Q_NULLPTR) {
231 return;
232 }
233
234 int base = edit->getBase();
235 int count = edit->modifiedCount();
236 for (int i = 0; count && i < edit->getSize(); i++) {
237 if (edit->modified()[i]) {
238 mem_poke_byte(static_cast<uint32_t>(base + i), edit->data()[i]);
239 count--;
240 }
241 qApp->processEvents();
242 }
243
244 memSync(edit);
245 }
246
memAsciiToggle(HexWidget * edit)247 void MainWindow::memAsciiToggle(HexWidget *edit) {
248 if (edit == Q_NULLPTR) {
249 return;
250 }
251
252 edit->setAsciiArea(!edit->getAsciiArea());
253 }
254
contextMem(const QPoint & posa)255 void MainWindow::contextMem(const QPoint &posa) {
256 HexWidget *p = qobject_cast<HexWidget*>(sender());
257 contextMemWidget(p->mapToGlobal(posa), static_cast<uint32_t>(p->getOffset() + p->getBase()));
258 }
259
contextMemWidget(const QPoint & pos,uint32_t address)260 void MainWindow::contextMemWidget(const QPoint &pos, uint32_t address) {
261 QString copyAddr = tr("Copy Address");
262 QString toggleBreak = tr("Toggle Breakpoint");
263 QString toggleWrite = tr("Toggle Write Watchpoint");
264 QString toggleRead = tr("Toggle Read Watchpoint");
265 QString toggleReadWrite = tr("Toggle Read/Write Watchpoint");
266 QString addr = int2hex(address, 6);
267
268 copyAddr += QStringLiteral(" '") + addr + QStringLiteral("'");
269
270 QMenu menu;
271 menu.addAction(copyAddr);
272 menu.addSeparator();
273 menu.addAction(toggleBreak);
274 menu.addAction(toggleRead);
275 menu.addAction(toggleWrite);
276 menu.addAction(toggleReadWrite);
277
278 QAction* item = menu.exec(pos);
279 if (item) {
280 if (item->text() == copyAddr) {
281 qApp->clipboard()->setText(addr.toLatin1());
282 } else if (item->text() == toggleBreak) {
283 breakAdd(breakNextLabel(), address, true, true, false);
284 memDocksUpdate();
285 } else if (item->text() == toggleRead) {
286 watchAdd(watchNextLabel(), address, address, DBG_MASK_READ, true, false);
287 memDocksUpdate();
288 } else if (item->text() == toggleWrite) {
289 watchAdd(watchNextLabel(), address, address, DBG_MASK_WRITE, true, false);
290 memDocksUpdate();
291 } else if (item->text() == toggleReadWrite) {
292 watchAdd(watchNextLabel(), address, address, DBG_MASK_READ | DBG_MASK_WRITE, true, false);
293 memDocksUpdate();
294 }
295 }
296 }
297