/** * Show requested command information. */ int DebugInfo_Command(int nArgc, char *psArgs[]) { Uint32 value; const char *cmd; bool ok, lock; int i, sub; sub = -1; if (nArgc > 1) { cmd = psArgs[1]; /* which subcommand? */ for (i = 0; i < ARRAYSIZE(infotable); i++) { if (strcmp(cmd, infotable[i].name) == 0) { sub = i; break; } } } if (infotable[sub].args) { /* value needs callback specific conversion */ value = infotable[sub].args(nArgc-2, psArgs+2); ok = !!value; } else { if (nArgc > 2) { /* value is normal number */ ok = Eval_Number(psArgs[2], &value); } else { value = 0; ok = true; } } lock = (strcmp(psArgs[0], "lock") == 0); if (sub < 0 || !ok) { /* no subcommand or something wrong with value, show info */ fprintf(stderr, "%s subcommands are:\n", psArgs[0]); for (i = 0; i < ARRAYSIZE(infotable); i++) { if (!lock && infotable[i].lock) { continue; } fprintf(stderr, "- %s: %s\n", infotable[i].name, infotable[i].info); } return DEBUGGER_CMDDONE; } if (lock) { /* lock given subcommand and value */ LockedFunction = sub; LockedArgument = value; fprintf(stderr, "Locked %s output.\n", psArgs[1]); } else { /* do actual work */ infotable[sub].func(value); } return DEBUGGER_CMDDONE; }
/** * Dump memory from an address to a binary file. */ static int DebugCpu_SaveBin(int nArgc, char *psArgs[]) { FILE *fp; unsigned char c; Uint32 address; Uint32 bytes, i = 0; if (nArgc < 4) { DebugUI_PrintCmdHelp(psArgs[0]); return DEBUGGER_CMDDONE; } if (!Eval_Number(psArgs[2], &address)) { fprintf(stderr, " Invalid address!\n"); return DEBUGGER_CMDDONE; } if (!Eval_Number(psArgs[3], &bytes)) { fprintf(stderr, " Invalid length!\n"); return DEBUGGER_CMDDONE; } if ((fp = fopen(psArgs[1], "wb")) == NULL) { fprintf(stderr," Cannot open file '%s'!\n", psArgs[1]); return DEBUGGER_CMDDONE; } while (i < bytes) { c = DBGMemory_ReadByte(address++); fputc(c, fp); i++; } fclose(fp); fprintf(stderr, " Wrote 0x%x bytes.\n", bytes); return DEBUGGER_CMDDONE; }
/** * Command: Write to memory, arg = starting address, followed by bytes. */ static int DebugCpu_MemWrite(int nArgc, char *psArgs[]) { int i, numBytes; Uint32 write_addr, d; unsigned char bytes[256]; /* store bytes */ if (nArgc < 3) { DebugUI_PrintCmdHelp(psArgs[0]); return DEBUGGER_CMDDONE; } /* Read address */ if (!Eval_Number(psArgs[1], &write_addr)) { fprintf(stderr, "Bad address!\n"); return DEBUGGER_CMDDONE; } numBytes = 0; /* get bytes data */ for (i = 2; i < nArgc; i++) { if (!Eval_Number(psArgs[i], &d) || d > 255) { fprintf(stderr, "Bad byte argument: '%s'!\n", psArgs[i]); return DEBUGGER_CMDDONE; } bytes[numBytes] = d & 0x0FF; numBytes++; } /* write the data */ for (i = 0; i < numBytes; i++) DBGMemory_WriteByte(write_addr + i, bytes[i]); return DEBUGGER_CMDDONE; }
/** * Convert arguments to Uint32 arg suitable for DSP memdump callback */ static Uint32 DebugInfo_DspMemArgs(int argc, char *argv[]) { Uint32 value; char space; if (argc != 2) { return 0; } space = toupper(argv[0][0]); if ((space != 'X' && space != 'Y' && space != 'P') || argv[0][1]) { fprintf(stderr, "ERROR: invalid DSP address space '%s'!\n", argv[0]); return 0; } if (!Eval_Number(argv[1], &value) || value > 0xffff) { fprintf(stderr, "ERROR: invalid DSP address '%s'!\n", argv[1]); return 0; } return ((Uint32)space<<16) | value; }
/** * Load a binary file to a memory address. */ static int DebugCpu_LoadBin(int nArgc, char *psArgs[]) { FILE *fp; unsigned char c; Uint32 address; int i=0; if (nArgc < 3) { return DebugUI_PrintCmdHelp(psArgs[0]); } if (!Eval_Number(psArgs[2], &address)) { fprintf(stderr, "Invalid address!\n"); return DEBUGGER_CMDDONE; } if ((fp = fopen(psArgs[1], "rb")) == NULL) { fprintf(stderr, "Cannot open file '%s'!\n", psArgs[1]); return DEBUGGER_CMDDONE; } /* TODO: more efficient would be to: * - check file size * - verify that it fits into valid memory area * - flush emulated CPU data cache * - read file contents directly into memory */ c = fgetc(fp); while (!feof(fp)) { i++; STMemory_WriteByte(address++, c); c = fgetc(fp); } fprintf(stderr," Read 0x%x bytes.\n", i); fclose(fp); return DEBUGGER_CMDDONE; }
/** * Command: Dump or set a DSP register */ int DebugDsp_Register(int nArgc, char *psArgs[]) { char *assign; Uint32 value; char *arg; if (!bDspEnabled) { fprintf(stderr, "DSP isn't present or initialized.\n"); return DEBUGGER_CMDDONE; } if (nArgc == 1) { /* No parameter - dump all registers */ DSP_DisasmRegisters(); return DEBUGGER_CMDDONE; } arg = psArgs[1]; assign = strchr(arg, '='); if (!assign) goto error_msg; *assign++ = '\0'; if (!Eval_Number(Str_Trim(assign), &value)) goto error_msg; if (DSP_Disasm_SetRegister(Str_Trim(arg), value)) return DEBUGGER_CMDDONE; error_msg: fprintf(stderr,"\tError, usage: dr or dr xx=yyyy\n" "\tWhere: xx=A0-A2, B0-B2, X0, X1, Y0, Y1, R0-R7,\n" "\t N0-N7, M0-M7, LA, LC, PC, SR, SP, OMR, SSH, SSL\n"); return DEBUGGER_CMDDONE; }
/** * Load a binary file to a memory address. */ static int DebugCpu_LoadBin(int nArgc, char *psArgs[]) { FILE *fp; unsigned char c; Uint32 address; int i=0; if (nArgc < 3) { DebugUI_PrintCmdHelp(psArgs[0]); return DEBUGGER_CMDDONE; } if (!Eval_Number(psArgs[2], &address)) { fprintf(stderr, "Invalid address!\n"); return DEBUGGER_CMDDONE; } if ((fp = fopen(psArgs[1], "rb")) == NULL) { fprintf(stderr, "Cannot open file '%s'!\n", psArgs[1]); return DEBUGGER_CMDDONE; } c = fgetc(fp); while (!feof(fp)) { i++; DBGMemory_WriteByte(address++, c); c = fgetc(fp); } fprintf(stderr," Read 0x%x bytes.\n", i); fclose(fp); return DEBUGGER_CMDDONE; }
/** * Dump or set CPU registers */ int DebugCpu_Register(int nArgc, char *psArgs[]) { char reg[3], *assign; Uint32 value; char *arg; /* If no parameter has been given, simply dump all registers */ if (nArgc == 1) { uaecptr nextpc; /* use the UAE function instead */ #ifdef WINUAE_FOR_HATARI m68k_dumpstate_file(debugOutput, &nextpc); #else m68k_dumpstate(debugOutput, &nextpc); #endif fflush(debugOutput); return DEBUGGER_CMDDONE; } arg = psArgs[1]; assign = strchr(arg, '='); if (!assign) { goto error_msg; } *assign++ = '\0'; if (!Eval_Number(Str_Trim(assign), &value)) { goto error_msg; } arg = Str_Trim(arg); if (strlen(arg) != 2) { goto error_msg; } reg[0] = toupper((unsigned char)arg[0]); reg[1] = toupper((unsigned char)arg[1]); reg[2] = '\0'; /* set SR and update conditional flags for the UAE CPU core. */ if (reg[0] == 'S' && reg[1] == 'R') { M68000_SetSR(value); } else if (reg[0] == 'P' && reg[1] == 'C') /* set PC? */ { M68000_SetPC(value); } else { Uint32 *regaddr; /* check&set data and address registers */ if (DebugCpu_GetRegisterAddress(reg, ®addr)) { *regaddr = value; } else { goto error_msg; } } return DEBUGGER_CMDDONE; error_msg: fprintf(stderr,"\tError, usage: r or r xx=yyyy\n\tWhere: xx=A0-A7, D0-D7, PC or SR.\n"); return DEBUGGER_CMDDONE; }