Commit | Line | Data |
---|---|---|
cf76e892 JPM |
1 | // |
2 | // cpubrowser.cpp - Jaguar CPU browser | |
3 | // | |
4 | // by James Hammons | |
5 | // (C) 2012 Underground Software | |
6 | // | |
7 | // JLH = James Hammons <jlhamm@acm.org> | |
8 | // JPM = Jean-Paul Mari <djipi.mari@gmail.com> | |
9 | // | |
10 | // Who When What | |
11 | // --- ---------- ----------------------------------------------------------- | |
12 | // JLH 08/14/2012 Created this file | |
13 | // JPM 08/09/2017 Added windows display detection in order to avoid the refresh | |
1081a838 | 14 | // JPM 10/13/2018 Added BPM hit counts |
cf76e892 JPM |
15 | // |
16 | ||
17 | // STILL TO DO: | |
18 | // | |
19 | ||
20 | #include "cpubrowser.h" | |
21 | //#include "memory.h" | |
22 | #include "m68000/m68kinterface.h" | |
23 | #include "dsp.h" | |
24 | #include "gpu.h" | |
25 | #include "jaguar.h" | |
26 | ||
27 | ||
28 | CPUBrowserWindow::CPUBrowserWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Dialog), | |
29 | layout(new QVBoxLayout), text(new QLabel), | |
30 | refresh(new QPushButton(tr("Refresh"))), | |
31 | bpm(new QCheckBox(tr("BPM"))), bpmAddress(new QLineEdit), | |
32 | bpmContinue(new QPushButton(tr("Resume"))) | |
33 | { | |
34 | setWindowTitle(tr("CPU Browser")); | |
35 | ||
36 | // Need to set the size as well... | |
37 | // resize(560, 480); | |
38 | ||
39 | // Limit input to 6 hex digits | |
40 | bpmAddress->setInputMask("hhhhhh"); | |
41 | QHBoxLayout * hbox1 = new QHBoxLayout; | |
42 | hbox1->addWidget(bpm); | |
43 | hbox1->addWidget(bpmAddress); | |
44 | hbox1->addWidget(bpmContinue); | |
45 | ||
46 | QFont fixedFont("Lucida Console", 8, QFont::Normal); | |
47 | // QFont fixedFont("", 8, QFont::Normal); | |
48 | fixedFont.setStyleHint(QFont::TypeWriter); | |
49 | text->setFont(fixedFont); | |
50 | //// layout->setSizeConstraint(QLayout::SetFixedSize); | |
51 | setLayout(layout); | |
52 | ||
53 | layout->addWidget(text); | |
54 | layout->addLayout(hbox1); | |
55 | layout->addWidget(refresh); | |
56 | ||
57 | connect(refresh, SIGNAL(clicked()), this, SLOT(RefreshContents())); | |
58 | connect(bpm, SIGNAL(clicked(bool)), this, SLOT(HandleBPM(bool))); | |
59 | connect(bpmAddress, SIGNAL(textChanged(const QString &)), this, SLOT(HandleBPMAddress(const QString &))); | |
60 | connect(bpmContinue, SIGNAL(clicked()), this, SLOT(HandleBPMContinue())); | |
61 | } | |
62 | ||
63 | ||
64 | void CPUBrowserWindow::RefreshContents(void) | |
65 | { | |
66 | char string[2048]; | |
67 | QString s; | |
68 | ||
69 | if (isVisible()) | |
70 | { | |
71 | // 68K | |
72 | uint32_t m68kPC = m68k_get_reg(NULL, M68K_REG_PC); | |
73 | uint32_t m68kSR = m68k_get_reg(NULL, M68K_REG_SR); | |
e09d2abd | 74 | sprintf(string, "PC: %06X SR: %04X : %c%c%c%c%c%c%c<br><br>", m68kPC, m68kSR, ((m68kSR & 0x8000) ? 'T': '-'), ((m68kSR & 0x2000) ? 'S' : '-'), ((m68kSR & 0x10) ? 'X' : '-'), ((m68kSR & 0x8) ? 'N' : '-'), ((m68kSR & 0x4) ? 'Z' : '-'), ((m68kSR & 0x2) ? 'V' : '-'), ((m68kSR & 0x1) ? 'C' : '-')); |
cf76e892 JPM |
75 | s += QString(string); |
76 | /* | |
77 | SR format: | |
78 | +--+--+--+--+ +--+--+--+--+ +--+--+--+--+ +--+--+--+--+ | |
79 | |T1|T0| S| M| |--|I2|I1|I0| |--|--|--| X| | N| Z| V| C| | |
80 | +--+--+--+--+ +--+--+--+--+ +--+--+--+--+ +--+--+--+--+ | |
81 | T - Trace (T1 only in 68K, T0 = 0) | |
82 | S - Supervisor flag | |
83 | M - Master/Interrupt flag (= 0 in 68K) | |
84 | I - Interrupt level mask | |
85 | X - Extend flag | |
86 | N - Negative flag | |
87 | Z - Zero flag | |
88 | V - Overflow flag | |
89 | C - Carry flag | |
90 | */ | |
91 | ||
92 | uint32_t m68kA0 = m68k_get_reg(NULL, M68K_REG_A0); | |
93 | uint32_t m68kA1 = m68k_get_reg(NULL, M68K_REG_A1); | |
94 | uint32_t m68kA2 = m68k_get_reg(NULL, M68K_REG_A2); | |
95 | uint32_t m68kA3 = m68k_get_reg(NULL, M68K_REG_A3); | |
96 | sprintf(string, "A0: %08X A1: %08X A2: %08X A3: %08X<br>", m68kA0, m68kA1, m68kA2, m68kA3); | |
97 | s += QString(string); | |
98 | ||
99 | uint32_t m68kA4 = m68k_get_reg(NULL, M68K_REG_A4); | |
100 | uint32_t m68kA5 = m68k_get_reg(NULL, M68K_REG_A5); | |
101 | uint32_t m68kA6 = m68k_get_reg(NULL, M68K_REG_A6); | |
102 | uint32_t m68kA7 = m68k_get_reg(NULL, M68K_REG_A7); | |
103 | sprintf(string, "A4: %08X A5: %08X A6: %08X A7: %08X<br><br>", m68kA4, m68kA5, m68kA6, m68kA7); | |
104 | s += QString(string); | |
105 | ||
106 | uint32_t m68kD0 = m68k_get_reg(NULL, M68K_REG_D0); | |
107 | uint32_t m68kD1 = m68k_get_reg(NULL, M68K_REG_D1); | |
108 | uint32_t m68kD2 = m68k_get_reg(NULL, M68K_REG_D2); | |
109 | uint32_t m68kD3 = m68k_get_reg(NULL, M68K_REG_D3); | |
110 | sprintf(string, "D0: %08X D1: %08X D2: %08X D3: %08X<br>", m68kD0, m68kD1, m68kD2, m68kD3); | |
111 | s += QString(string); | |
112 | ||
113 | uint32_t m68kD4 = m68k_get_reg(NULL, M68K_REG_D4); | |
114 | uint32_t m68kD5 = m68k_get_reg(NULL, M68K_REG_D5); | |
115 | uint32_t m68kD6 = m68k_get_reg(NULL, M68K_REG_D6); | |
116 | uint32_t m68kD7 = m68k_get_reg(NULL, M68K_REG_D7); | |
117 | sprintf(string, "D4: %08X D5: %08X D6: %08X D7: %08X<br><br>", m68kD4, m68kD5, m68kD6, m68kD7); | |
118 | s += QString(string); | |
119 | ||
120 | // GPU | |
121 | sprintf(string, "GPU PC: %06X FLAGS: %04X SR: %04X<br><br>", GPUReadLong(0xF02110, DEBUG), GPUReadLong(0xF02100, DEBUG), GPUReadLong(0xF02114, DEBUG)); | |
122 | s += QString(string); | |
123 | /* | |
124 | GPU Flags: | |
125 | 0 - Zero flag | |
126 | 1 - Carry flag | |
127 | 2 - Negative flag | |
128 | 3 - IMASK (writing 0 clears, 1 has no effect) | |
129 | 4-8 - IRQ enable 0 - 4 | |
130 | 9-13 - IRQ latch clear 0 - 4 | |
131 | 14 - REGPAGE | |
132 | 15 - DMAEN | |
133 | ||
134 | GPU Control: | |
135 | 0 - GPU Go | |
136 | 1 - CPUINT | |
137 | 2 - GPUINT0 | |
138 | 3 - Single Step | |
139 | 4 - Single step go | |
140 | 5 - Unused | |
141 | 6-10 - IRQ Latch 0 - 4 | |
142 | 11 - Bus Hog | |
143 | 12-15 - Version | |
144 | */ | |
145 | ||
146 | sprintf(string, "Bank 0:<br>" | |
147 | "R00: %08X R01: %08X R02: %08X R03: %08X<br>" | |
148 | "R04: %08X R05: %08X R06: %08X R07: %08X<br>" | |
149 | "R08: %08X R09: %08X R10: %08X R11: %08X<br>" | |
150 | "R12: %08X R13: %08X R14: %08X R15: %08X<br>" | |
151 | "R16: %08X R17: %08X R18: %08X R19: %08X<br>" | |
152 | "R20: %08X R21: %08X R22: %08X R23: %08X<br>" | |
153 | "R24: %08X R25: %08X R26: %08X R27: %08X<br>" | |
154 | "R28: %08X R29: %08X R30: %08X R31: %08X<br><br>", | |
155 | gpu_reg_bank_0[0], gpu_reg_bank_0[1], gpu_reg_bank_0[2], gpu_reg_bank_0[3], | |
156 | gpu_reg_bank_0[4], gpu_reg_bank_0[5], gpu_reg_bank_0[6], gpu_reg_bank_0[7], | |
157 | gpu_reg_bank_0[8], gpu_reg_bank_0[9], gpu_reg_bank_0[10], gpu_reg_bank_0[11], | |
158 | gpu_reg_bank_0[12], gpu_reg_bank_0[13], gpu_reg_bank_0[14], gpu_reg_bank_0[15], | |
159 | gpu_reg_bank_0[16], gpu_reg_bank_0[17], gpu_reg_bank_0[18], gpu_reg_bank_0[19], | |
160 | gpu_reg_bank_0[20], gpu_reg_bank_0[21], gpu_reg_bank_0[22], gpu_reg_bank_0[23], | |
161 | gpu_reg_bank_0[24], gpu_reg_bank_0[25], gpu_reg_bank_0[26], gpu_reg_bank_0[27], | |
162 | gpu_reg_bank_0[28], gpu_reg_bank_0[29], gpu_reg_bank_0[30], gpu_reg_bank_0[31]); | |
163 | s += QString(string); | |
164 | ||
165 | sprintf(string, "Bank 1:<br>" | |
166 | "R00: %08X R01: %08X R02: %08X R03: %08X<br>" | |
167 | "R04: %08X R05: %08X R06: %08X R07: %08X<br>" | |
168 | "R08: %08X R09: %08X R10: %08X R11: %08X<br>" | |
169 | "R12: %08X R13: %08X R14: %08X R15: %08X<br>" | |
170 | "R16: %08X R17: %08X R18: %08X R19: %08X<br>" | |
171 | "R20: %08X R21: %08X R22: %08X R23: %08X<br>" | |
172 | "R24: %08X R25: %08X R26: %08X R27: %08X<br>" | |
173 | "R28: %08X R29: %08X R30: %08X R31: %08X<br><br>", | |
174 | gpu_reg_bank_1[0], gpu_reg_bank_1[1], gpu_reg_bank_1[2], gpu_reg_bank_1[3], | |
175 | gpu_reg_bank_1[4], gpu_reg_bank_1[5], gpu_reg_bank_1[6], gpu_reg_bank_1[7], | |
176 | gpu_reg_bank_1[8], gpu_reg_bank_1[9], gpu_reg_bank_1[10], gpu_reg_bank_1[11], | |
177 | gpu_reg_bank_1[12], gpu_reg_bank_1[13], gpu_reg_bank_1[14], gpu_reg_bank_1[15], | |
178 | gpu_reg_bank_1[16], gpu_reg_bank_1[17], gpu_reg_bank_1[18], gpu_reg_bank_1[19], | |
179 | gpu_reg_bank_1[20], gpu_reg_bank_1[21], gpu_reg_bank_1[22], gpu_reg_bank_1[23], | |
180 | gpu_reg_bank_1[24], gpu_reg_bank_1[25], gpu_reg_bank_1[26], gpu_reg_bank_1[27], | |
181 | gpu_reg_bank_1[28], gpu_reg_bank_1[29], gpu_reg_bank_1[30], gpu_reg_bank_1[31]); | |
182 | s += QString(string); | |
183 | ||
184 | // DSP | |
185 | sprintf(string, "DSP PC: %06X FLAGS: %05X SR: %05X<br><br>", DSPReadLong(0xF1A110, DEBUG), DSPReadLong(0xF1A100, DEBUG), DSPReadLong(0xF1A114, DEBUG)); | |
186 | s += QString(string); | |
187 | /* | |
188 | DSP Flags: | |
189 | 0 - Zero flag | |
190 | 1 - Carry flag | |
191 | 2 - Negative flag | |
192 | 3 - IMASK (writing 0 clears, 1 has no effect) | |
193 | 4-8 - IRQ enable 0 - 4 | |
194 | 9-13 - IRQ latch clear 0 - 4 | |
195 | 14 - REGPAGE | |
196 | 15 - DMAEN | |
197 | 16 - IRQ enable 5 | |
198 | 17 - IRQ latch clear 5 | |
199 | ||
200 | DSP Control: | |
201 | 0 - DSP Go | |
202 | 1 - CPUINT | |
203 | 2 - DSPINT0 | |
204 | 3 - Single Step | |
205 | 4 - Single step go | |
206 | 5 - Unused | |
207 | 6-10 - IRQ Latch 0 - 4 | |
208 | 11 - Bus Hog | |
209 | 12-15 - Version | |
210 | 16 - IRQ Latch 5 | |
211 | */ | |
212 | ||
213 | sprintf(string, "Bank 0:<br>" | |
214 | "R00: %08X R01: %08X R02: %08X R03: %08X<br>" | |
215 | "R04: %08X R05: %08X R06: %08X R07: %08X<br>" | |
216 | "R08: %08X R09: %08X R10: %08X R11: %08X<br>" | |
217 | "R12: %08X R13: %08X R14: %08X R15: %08X<br>" | |
218 | "R16: %08X R17: %08X R18: %08X R19: %08X<br>" | |
219 | "R20: %08X R21: %08X R22: %08X R23: %08X<br>" | |
220 | "R24: %08X R25: %08X R26: %08X R27: %08X<br>" | |
221 | "R28: %08X R29: %08X R30: %08X R31: %08X<br><br>", | |
222 | dsp_reg_bank_0[0], dsp_reg_bank_0[1], dsp_reg_bank_0[2], dsp_reg_bank_0[3], | |
223 | dsp_reg_bank_0[4], dsp_reg_bank_0[5], dsp_reg_bank_0[6], dsp_reg_bank_0[7], | |
224 | dsp_reg_bank_0[8], dsp_reg_bank_0[9], dsp_reg_bank_0[10], dsp_reg_bank_0[11], | |
225 | dsp_reg_bank_0[12], dsp_reg_bank_0[13], dsp_reg_bank_0[14], dsp_reg_bank_0[15], | |
226 | dsp_reg_bank_0[16], dsp_reg_bank_0[17], dsp_reg_bank_0[18], dsp_reg_bank_0[19], | |
227 | dsp_reg_bank_0[20], dsp_reg_bank_0[21], dsp_reg_bank_0[22], dsp_reg_bank_0[23], | |
228 | dsp_reg_bank_0[24], dsp_reg_bank_0[25], dsp_reg_bank_0[26], dsp_reg_bank_0[27], | |
229 | dsp_reg_bank_0[28], dsp_reg_bank_0[29], dsp_reg_bank_0[30], dsp_reg_bank_0[31]); | |
230 | s += QString(string); | |
231 | ||
232 | sprintf(string, "Bank 1:<br>" | |
233 | "R00: %08X R01: %08X R02: %08X R03: %08X<br>" | |
234 | "R04: %08X R05: %08X R06: %08X R07: %08X<br>" | |
235 | "R08: %08X R09: %08X R10: %08X R11: %08X<br>" | |
236 | "R12: %08X R13: %08X R14: %08X R15: %08X<br>" | |
237 | "R16: %08X R17: %08X R18: %08X R19: %08X<br>" | |
238 | "R20: %08X R21: %08X R22: %08X R23: %08X<br>" | |
239 | "R24: %08X R25: %08X R26: %08X R27: %08X<br>" | |
240 | "R28: %08X R29: %08X R30: %08X R31: %08X<br>", | |
241 | dsp_reg_bank_1[0], dsp_reg_bank_1[1], dsp_reg_bank_1[2], dsp_reg_bank_1[3], | |
242 | dsp_reg_bank_1[4], dsp_reg_bank_1[5], dsp_reg_bank_1[6], dsp_reg_bank_1[7], | |
243 | dsp_reg_bank_1[8], dsp_reg_bank_1[9], dsp_reg_bank_1[10], dsp_reg_bank_1[11], | |
244 | dsp_reg_bank_1[12], dsp_reg_bank_1[13], dsp_reg_bank_1[14], dsp_reg_bank_1[15], | |
245 | dsp_reg_bank_1[16], dsp_reg_bank_1[17], dsp_reg_bank_1[18], dsp_reg_bank_1[19], | |
246 | dsp_reg_bank_1[20], dsp_reg_bank_1[21], dsp_reg_bank_1[22], dsp_reg_bank_1[23], | |
247 | dsp_reg_bank_1[24], dsp_reg_bank_1[25], dsp_reg_bank_1[26], dsp_reg_bank_1[27], | |
248 | dsp_reg_bank_1[28], dsp_reg_bank_1[29], dsp_reg_bank_1[30], dsp_reg_bank_1[31]); | |
249 | s += QString(string); | |
250 | ||
251 | text->clear(); | |
252 | text->setText(s); | |
253 | } | |
254 | } | |
255 | ||
256 | ||
257 | // | |
258 | void CPUBrowserWindow::HoldBPM(void) | |
259 | { | |
260 | bpmSaveActive = bpmActive; | |
261 | bpmActive = false; | |
262 | } | |
263 | ||
264 | ||
265 | // | |
266 | void CPUBrowserWindow::UnholdBPM(void) | |
267 | { | |
268 | bpmActive = bpmSaveActive; | |
269 | } | |
270 | ||
271 | ||
1081a838 JPM |
272 | // Disable BPM |
273 | void CPUBrowserWindow::DisableBPM(void) | |
274 | { | |
275 | // Uncheck the BPM checkbox and handle BPM | |
276 | if (bpm->checkState()) | |
277 | { | |
278 | bpm->setCheckState(Qt::Unchecked); | |
279 | } | |
280 | HandleBPM(false); | |
281 | } | |
282 | ||
283 | ||
284 | // BPM reset | |
285 | // Disable checkbox and breakpoint address | |
286 | void CPUBrowserWindow::ResetBPM(void) | |
287 | { | |
288 | DisableBPM(); | |
289 | bpmAddress->setText(""); | |
290 | } | |
291 | ||
292 | ||
cf76e892 JPM |
293 | // Toggle breakpoint set |
294 | void CPUBrowserWindow::HandleBPM(bool state) | |
295 | { | |
296 | bpmSaveActive = bpmActive = state; | |
1081a838 | 297 | bpmHitCounts = 0; |
cf76e892 JPM |
298 | |
299 | if (bpmActive) | |
300 | { | |
301 | printf("BPM Set: $%06X\n", bpmAddress1); | |
302 | } | |
303 | else | |
304 | { | |
305 | printf("BPM Unset: $%06X\n", bpmAddress1); | |
306 | } | |
307 | } | |
308 | ||
309 | ||
1081a838 | 310 | // Breakpoint address set and reset the hit counts |
cf76e892 JPM |
311 | void CPUBrowserWindow::HandleBPMAddress(const QString & newText) |
312 | { | |
313 | bool ok; | |
314 | bpmAddress1 = newText.toUInt(&ok, 16); | |
315 | } | |
316 | ||
317 | ||
318 | void CPUBrowserWindow::HandleBPMContinue(void) | |
319 | { | |
320 | M68KDebugResume(); | |
321 | } | |
322 | ||
323 | ||
324 | // | |
325 | void CPUBrowserWindow::keyPressEvent(QKeyEvent * e) | |
326 | { | |
327 | if (e->key() == Qt::Key_Escape) | |
328 | { | |
329 | hide(); | |
330 | } | |
331 | else | |
332 | { | |
333 | if (e->key() == Qt::Key_Return) | |
334 | { | |
335 | HandleBPM(true); | |
336 | bpm->setChecked(true); | |
337 | } | |
338 | #if 0 | |
339 | else if (e->key() == Qt::Key_PageUp) | |
340 | { | |
341 | memBase -= 480; | |
342 | ||
343 | if (memBase < 0) | |
344 | memBase = 0; | |
345 | ||
346 | RefreshContents(); | |
347 | } | |
348 | else if (e->key() == Qt::Key_PageDown) | |
349 | { | |
350 | memBase += 480; | |
351 | ||
352 | if (memBase > (0x200000 - 480)) | |
353 | memBase = 0x200000 - 480; | |
354 | ||
355 | RefreshContents(); | |
356 | } | |
357 | else if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Minus) | |
358 | { | |
359 | memBase -= 16; | |
360 | ||
361 | if (memBase < 0) | |
362 | memBase = 0; | |
363 | ||
364 | RefreshContents(); | |
365 | } | |
366 | else if (e->key() == Qt::Key_Down || e->key() == Qt::Key_Equal) | |
367 | { | |
368 | memBase += 16; | |
369 | ||
370 | if (memBase > (0x200000 - 480)) | |
371 | memBase = 0x200000 - 480; | |
372 | ||
373 | RefreshContents(); | |
374 | } | |
375 | #endif | |
376 | } | |
377 | } | |
378 |