void debug_prompt() { char s[81] = { 0 }; UINT8 done = 0; struct cpudef *cpu = get_cpu_struct(g_which_cpu); unsigned int addr = cpu->getpc_callback(); // this function relies on addr being initialized to PC g_break = 0; // once they get here, don't break anymore // they have to issue a proper command to get out of the prompt while (!done && !get_quitflag()) { newline(); print_cpu_context(); // show registers and stuff sprintf(s, "[#%u][%04x Command,'?']-> ", g_which_cpu, cpu->getpc_callback()); outstr(s); con_getline(s, 80); switch(toupper(s[0])) { case 'S': // this might help with debugging *shrug* g_ldp->pre_step_forward(); printline("Stepping forward one frame..."); break; case 'C': // continue execution g_cpu_trace = 0; done = 1; break; case 'D': // disassemble // if they entered in an address to disassemble at ... if (strlen(s) > 1) { addr = (unsigned int) strtol(&s[1], NULL, 16); // convert base 16 text to a number } // else if they entered no parameters, disassemble from PC debug_disassemble(addr); break; case 'F': // display current laserdisc frame g_ldp->print_frame_info(); print_ldv1000_info(); break; case 'I': // break at end of interrupt printline("This feature not implemented yet =]"); break; case '=': // set a new breakpoint // if they entered in an address to disassemble at ... if (strlen(s) > 1) { g_breakpoint = (UINT32) strtol(&s[1], NULL, 16); // convert base 16 text to a number g_break = 1; g_cpu_trace = 0; done = 1; } // else if they entered no parameters, disassemble from PC else { printline("You must specify an address to break at."); } break; case 'M': // memory dump if (strlen(s) > 1) { addr = (unsigned int) strtol(&s[1], NULL, 16); } print_memory_dump(addr); break; case 'N': // next CPU g_which_cpu++; // if we've run out of CPU's to debug, wrap back around to the first cpu if (get_cpu_struct(g_which_cpu) == NULL) g_which_cpu = 0; break; case 0: // carriage return g_cpu_trace = 1; done = 1; break; case 'Q': // quit emulator set_quitflag(); break; case 'W': // write byte at address if (strlen(s) > 1) { int i = 2; // skip the W and the first whitespace Uint32 addr = 0; Uint8 val = 0; // find next whitespace while (s[i] != ' ') { i++; } s[i] = 0; // terminate string so we can do a strtol addr = (Uint32) strtol(&s[1], NULL, 16); // convert base 16 text to a number val = (Uint8) strtol(&s[i+1], NULL, 16); // i+1 because we skip the NULL-terminator we added before g_game->cpu_mem_write((Uint16) addr, val); // assume 16-bit for now } break; case '?': // get menu debug_menu(); break; default: printline("Unknown command, press ? to get a menu"); break; } } // end while }
void debugger_do() { int c, d, e, f; int params; uint8_t temp; char outs[256]; char ins[256]; if (!opcode) { sprintf(outs, "BRK %04X! %04X %04X\n", pc, oldpc, oldoldpc); debug_out(outs); } if (!opcode) debug = 1; for (c = 0; c < 8; c++) { if (breakpoints[c] == pc) { debug = 1; sprintf(outs, " Break at %04X\n", pc); debug_out(outs); } } if (!debug) return; // if (!opcode) printf("BRK at %04X\n",pc); if (debugstep) { debugstep--; if (debugstep) return; } indebug = 1; while (1) { d = debug_disaddr; debug_disaddr = pc; debug_disassemble(); debug_disaddr = d; sprintf(outs, " >"); debug_out(outs); #ifdef WIN32 c = ReadConsoleA(cinf, ins, 255, (LPDWORD)&d, NULL); ins[d] = 0; #else d = (int)fgets(ins, 255, stdin); #endif d = 0; while (ins[d] != 32 && ins[d] != 0xA && ins[d] != 0xD && ins[d] != 0) d++; while (ins[d] == 32) d++; if (ins[d] == 0xA || ins[d] == 0xD || ins[d] == 0) params = 0; else params = 1; if (ins[0] == 0xA || ins[0] == 0xD) ins[0] = debug_lastcommand; //debug_out("Processing!\n"); switch (ins[0]) { case 'c': case 'C': debug = 0; indebug = 0; return; case 'm': case 'M': if (params) sscanf(&ins[d], "%X", (unsigned int *)&debug_memaddr); for (c = 0; c < 16; c++) { sprintf(outs, " %04X : ", debug_memaddr); debug_out(outs); for (d = 0; d < 16; d++) { sprintf(outs, "%02X ", debug_readmem(debug_memaddr + d)); debug_out(outs); } debug_out(" "); for (d = 0; d < 16; d++) { temp = debug_readmem(debug_memaddr + d); if (temp < 32) sprintf(outs, "."); else sprintf(outs, "%c", temp); debug_out(outs); } debug_memaddr += 16; debug_out("\n"); } break; case 'd': case 'D': if (params) sscanf(&ins[d], "%X", (unsigned int *)&debug_disaddr); for (c = 0; c < 12; c++) { debug_out(" "); debug_disassemble(); debug_out("\n"); } break; case 'r': case 'R': if (params) { if (!strncasecmp(&ins[d], "sysvia", 6)) { sprintf(outs, " System VIA registers :\n"); debug_out(outs); sprintf(outs, " ORA %02X ORB %02X IRA %02X IRB %02X\n", sysvia.ora, sysvia.orb, sysvia.ira, sysvia.irb); debug_out(outs); sprintf(outs, " DDRA %02X DDRB %02X ACR %02X PCR %02X\n", sysvia.ddra, sysvia.ddrb, sysvia.acr, sysvia.pcr); debug_out(outs); sprintf(outs, " Timer 1 latch %04X count %04X\n", sysvia.t1l / 2, (sysvia.t1c / 2) & 0xFFFF); debug_out(outs); sprintf(outs, " Timer 2 latch %04X count %04X\n", sysvia.t2l / 2, (sysvia.t2c / 2) & 0xFFFF); debug_out(outs); sprintf(outs, " IER %02X IFR %02X\n", sysvia.ier, sysvia.ifr); debug_out(outs); } if (!strncasecmp(&ins[d], "uservia", 7)) { sprintf(outs, " User VIA registers :\n"); debug_out(outs); sprintf(outs, " ORA %02X ORB %02X IRA %02X IRB %02X\n", uservia.ora, uservia.orb, uservia.ira, uservia.irb); debug_out(outs); sprintf(outs, " DDRA %02X DDRB %02X ACR %02X PCR %02X\n", uservia.ddra, uservia.ddrb, uservia.acr, uservia.pcr); debug_out(outs); sprintf(outs, " Timer 1 latch %04X count %04X\n", uservia.t1l / 2, (uservia.t1c / 2) & 0xFFFF); debug_out(outs); sprintf(outs, " Timer 2 latch %04X count %04X\n", uservia.t2l / 2, (uservia.t2c / 2) & 0xFFFF); debug_out(outs); sprintf(outs, " IER %02X IFR %02X\n", uservia.ier, uservia.ifr); debug_out(outs); } if (!strncasecmp(&ins[d], "crtc", 4)) { sprintf(outs, " CRTC registers :\n"); debug_out(outs); sprintf(outs, " Index=%i\n", crtc_i); debug_out(outs); sprintf(outs, " R0 =%02X R1 =%02X R2 =%02X R3 =%02X R4 =%02X R5 =%02X R6 =%02X R7 =%02X R8 =%02X\n", crtc[0], crtc[1], crtc[2], crtc[3], crtc[4], crtc[5], crtc[6], crtc[7], crtc[8]); debug_out(outs); sprintf(outs, " R9 =%02X R10=%02X R11=%02X R12=%02X R13=%02X R14=%02X R15=%02X R16=%02X R17=%02X\n", crtc[9], crtc[10], crtc[11], crtc[12], crtc[13], crtc[14], crtc[15], crtc[16], crtc[17]); debug_out(outs); sprintf(outs, " VC=%i SC=%i HC=%i MA=%04X\n", vc, sc, hc, ma); debug_out(outs); } if (!strncasecmp(&ins[d],"vidproc",7)) { sprintf(outs, " VIDPROC registers :\n"); debug_out(outs); sprintf(outs, " Control=%02X\n", ula_ctrl); debug_out(outs); sprintf(outs, " Palette entries :\n"); debug_out(outs); sprintf(outs, " 0=%01X 1=%01X 2=%01X 3=%01X 4=%01X 5=%01X 6=%01X 7=%01X\n", ula_palbak[0], ula_palbak[1], ula_palbak[2], ula_palbak[3], ula_palbak[4], ula_palbak[5], ula_palbak[6], ula_palbak[7]); debug_out(outs); sprintf(outs, " 8=%01X 9=%01X 10=%01X 11=%01X 12=%01X 13=%01X 14=%01X 15=%01X\n", ula_palbak[8], ula_palbak[9], ula_palbak[10], ula_palbak[11], ula_palbak[12], ula_palbak[13], ula_palbak[14], ula_palbak[15]); debug_out(outs); } if (!strncasecmp(&ins[d],"sound",5)) { sprintf(outs, " Sound registers :\n"); debug_out(outs); sprintf(outs, " Voice 0 frequency = %04X volume = %i control = %02X\n", sn_latch[0] >> 6, sn_vol[0], sn_noise); debug_out(outs); sprintf(outs, " Voice 1 frequency = %04X volume = %i\n", sn_latch[1] >> 6, sn_vol[1]); debug_out(outs); sprintf(outs, " Voice 2 frequency = %04X volume = %i\n", sn_latch[2] >> 6, sn_vol[2]); debug_out(outs); sprintf(outs, " Voice 3 frequency = %04X volume = %i\n", sn_latch[3] >> 6, sn_vol[3]); debug_out(outs); } } else { sprintf(outs, " 6502 registers :\n"); debug_out(outs); sprintf(outs, " A=%02X X=%02X Y=%02X S=01%02X PC=%04X\n", a, x, y, s, pc); debug_out(outs); sprintf(outs, " Status : %c%c%c%c%c%c\n", (p.n) ? 'N' : ' ', (p.v) ? 'V' : ' ', (p.d) ? 'D' : ' ', (p.i) ? 'I' : ' ', (p.z) ? 'Z' : ' ', (p.c) ? 'C' : ' '); debug_out(outs); } break; case 's': case 'S': if (params) sscanf(&ins[d], "%i", &debugstep); else debugstep = 1; debug_lastcommand = ins[0]; indebug = 0; return; case 'b': case 'B': if (!strncasecmp(ins, "breakr", 6)) { if (!params) break; for (c = 0; c < 8; c++) { if (breakpoints[c] == -1) { sscanf(&ins[d], "%X", &breakr[c]); sprintf(outs, " Read breakpoint %i set to %04X\n", c, breakr[c]); debug_out(outs); break; } } } else if (!strncasecmp(ins, "breakw", 6)) { if (!params) break; for (c = 0; c < 8; c++) { if (breakpoints[c] == -1) { sscanf(&ins[d], "%X", &breakw[c]); sprintf(outs, " Write breakpoint %i set to %04X\n", c, breakw[c]); debug_out(outs); break; } } } else if (!strncasecmp(ins, "break", 5)) { if (!params) break; for (c = 0; c < 8; c++) { if (breakpoints[c] == -1) { sscanf(&ins[d], "%X", &breakpoints[c]); sprintf(outs, " Breakpoint %i set to %04X\n", c, breakpoints[c]); debug_out(outs); break; } } } if (!strncasecmp(ins, "blist", 5)) { for (c = 0; c < 8; c++) { if (breakpoints[c] != -1) { sprintf(outs, " Breakpoint %i : %04X\n", c, breakpoints[c]); debug_out(outs); } } for (c = 0; c < 8; c++) { if (breakr[c] != -1) { sprintf(outs, " Read breakpoint %i : %04X\n", c, breakr[c]); debug_out(outs); } } for (c = 0; c < 8; c++) { if (breakw[c] != -1) { sprintf(outs, " Write breakpoint %i : %04X\n", c, breakw[c]); debug_out(outs); } } } if (!strncasecmp(ins, "bclearr", 7)) { if (!params) break; sscanf(&ins[d], "%X", &e); for (c = 0; c < 8; c++) { if (breakr[c] == e) breakr[c] = -1; if (c == e) breakr[c] = -1; } } else if (!strncasecmp(ins, "bclearw", 7)) { if (!params) break; sscanf(&ins[d], "%X", &e); for (c = 0; c < 8; c++) { if (breakw[c] == e) breakw[c] = -1; if (c == e) breakw[c] = -1; } } else if (!strncasecmp(ins, "bclear", 6)) { if (!params) break; sscanf(&ins[d], "%X", &e); for (c = 0; c < 8; c++) { if (breakpoints[c] == e) breakpoints[c] = -1; if (c == e) breakpoints[c] = -1; } } break; case 'w': case 'W': if (!strncasecmp(ins, "watchr", 6)) { if (!params) break; for (c = 0; c < 8; c++) { if (watchr[c] == -1) { sscanf(&ins[d], "%X", &watchr[c]); sprintf(outs, " Read watchpoint %i set to %04X\n", c, watchr[c]); debug_out(outs); break; } } break; } if (!strncasecmp(ins, "watchw", 6)) { if (!params) break; for (c = 0; c < 8; c++) { if (watchw[c] == -1) { sscanf(&ins[d], "%X", &watchw[c]); sprintf(outs, " Write watchpoint %i set to %04X\n", c, watchw[c]); debug_out(outs); break; } } break; } if (!strncasecmp(ins, "wlist", 5)) { for (c = 0; c < 8; c++) { if (watchr[c] != -1) { sprintf(outs, " Read watchpoint %i : %04X\n", c, watchr[c]); debug_out(outs); } } for (c = 0; c < 8; c++) { if (watchw[c] != -1) { sprintf(outs, " Write watchpoint %i : %04X\n", c, watchw[c]); debug_out(outs); } } } if (!strncasecmp(ins, "wclearr", 7)) { if (!params) break; sscanf(&ins[d], "%X", &e); for (c = 0; c < 8; c++) { if (watchr[c] == e) watchr[c] = -1; if (c == e) watchr[c] = -1; } } else if (!strncasecmp(ins, "wclearw", 7)) { if (!params) break; sscanf(&ins[d], "%X", &e); for (c = 0; c < 8; c++) { if (watchw[c] == e) watchw[c] = -1; if (c == e) watchw[c] = -1; } } else if (!strncasecmp(ins, "writem", 6)) { if (!params) break; sscanf(&ins[d], "%X %X", &e, &f); rpclog("WriteM %04X %04X\n", e, f); writemem(e, f); } break; case 'q': case 'Q': setquit(); while (1); break; case 'h': case 'H': case '?': sprintf(outs, "\n Debugger commands :\n\n"); debug_out(outs); sprintf(outs, " bclear n - clear breakpoint n or breakpoint at n\n"); debug_out(outs); sprintf(outs, " bclearr n - clear read breakpoint n or read breakpoint at n\n"); debug_out(outs); sprintf(outs, " bclearw n - clear write breakpoint n or write breakpoint at n\n"); debug_out(outs); sprintf(outs, " blist - list current breakpoints\n"); debug_out(outs); sprintf(outs, " break n - set a breakpoint at n\n"); debug_out(outs); sprintf(outs, " breakr n - break on reads from address n\n"); debug_out(outs); sprintf(outs, " breakw n - break on writes to address n\n"); debug_out(outs); sprintf(outs, " c - continue running indefinitely\n"); debug_out(outs); sprintf(outs, " d [n] - disassemble from address n\n"); debug_out(outs); sprintf(outs, " m [n] - memory dump from address n\n"); debug_out(outs); sprintf(outs, " q - force emulator exit\n"); debug_out(outs); sprintf(outs, " r - print 6502 registers\n"); debug_out(outs); sprintf(outs, " r sysvia - print System VIA registers\n"); debug_out(outs); sprintf(outs, " r uservia - print User VIA registers\n"); debug_out(outs); sprintf(outs, " r crtc - print CRTC registers\n"); debug_out(outs); sprintf(outs, " r vidproc - print VIDPROC registers\n"); debug_out(outs); sprintf(outs, " r sound - print Sound registers\n"); debug_out(outs); sprintf(outs, " s [n] - step n instructions (or 1 if no parameter)\n\n"); debug_out(outs); sprintf(outs, " watchr n - watch reads from address n\n"); debug_out(outs); sprintf(outs, " watchw n - watch writes to address n\n"); debug_out(outs); sprintf(outs, " wclearr n - clear read watchpoint n or read watchpoint at n\n"); debug_out(outs); sprintf(outs, " wclearw n - clear write watchpoint n or write watchpoint at n\n"); debug_out(outs); sprintf(outs, " writem a v - write to memory, a = address, v = value\n"); debug_out(outs); break; }