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