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