Added modifier syntax to debugger: Changed watch's syntax, added format modifier to print/eval, added count option to examine command.
This commit is contained in:
parent
18ec502cfe
commit
ee51dec20e
183
Core/debugger.c
183
Core/debugger.c
@ -593,7 +593,7 @@ value_t debugger_evaluate(GB_gameboy_t *gb, const char *string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct debugger_command_s;
|
struct debugger_command_s;
|
||||||
typedef bool debugger_command_imp_t(GB_gameboy_t *gb, char *arguments, const struct debugger_command_s *command);
|
typedef bool debugger_command_imp_t(GB_gameboy_t *gb, char *arguments, char *modifiers, const struct debugger_command_s *command);
|
||||||
|
|
||||||
typedef struct debugger_command_s {
|
typedef struct debugger_command_s {
|
||||||
const char *command;
|
const char *command;
|
||||||
@ -601,6 +601,7 @@ typedef struct debugger_command_s {
|
|||||||
debugger_command_imp_t *implementation;
|
debugger_command_imp_t *implementation;
|
||||||
const char *help_string; // Null if should not appear in help
|
const char *help_string; // Null if should not appear in help
|
||||||
const char *arguments_format; // For usage message
|
const char *arguments_format; // For usage message
|
||||||
|
const char *modifiers_format; // For usage message
|
||||||
} debugger_command_t;
|
} debugger_command_t;
|
||||||
|
|
||||||
static const char *lstrip(const char *str)
|
static const char *lstrip(const char *str)
|
||||||
@ -617,18 +618,30 @@ GB_log(gb, "Program is running. \n"); \
|
|||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_usage(GB_gameboy_t *gb, const debugger_command_t *command)
|
#define NO_MODIFIERS \
|
||||||
{
|
if (modifiers) { \
|
||||||
if (command->arguments_format) {
|
print_usage(gb, command); \
|
||||||
GB_log(gb, "Usage: %s %s\n", command->command, command->arguments_format);
|
return true; \
|
||||||
}
|
|
||||||
else {
|
|
||||||
GB_log(gb, "Usage: %s\n", command->command);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cont(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static void print_usage(GB_gameboy_t *gb, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
GB_log(gb, "Usage: %s", command->command);
|
||||||
|
|
||||||
|
if (command->arguments_format) {
|
||||||
|
GB_log(gb, "[/%s]", command->modifiers_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command->arguments_format) {
|
||||||
|
GB_log(gb, " %s", command->arguments_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
GB_log(gb, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cont(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
STOPPED_ONLY
|
STOPPED_ONLY
|
||||||
|
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
@ -640,8 +653,9 @@ static bool cont(GB_gameboy_t *gb, char *arguments, const debugger_command_t *co
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool next(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool next(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
STOPPED_ONLY
|
STOPPED_ONLY
|
||||||
|
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
@ -655,8 +669,9 @@ static bool next(GB_gameboy_t *gb, char *arguments, const debugger_command_t *co
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool step(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool step(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
STOPPED_ONLY
|
STOPPED_ONLY
|
||||||
|
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
@ -667,8 +682,9 @@ static bool step(GB_gameboy_t *gb, char *arguments, const debugger_command_t *co
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool finish(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool finish(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
STOPPED_ONLY
|
STOPPED_ONLY
|
||||||
|
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
@ -682,8 +698,9 @@ static bool finish(GB_gameboy_t *gb, char *arguments, const debugger_command_t *
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stack_leak_detection(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool stack_leak_detection(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
STOPPED_ONLY
|
STOPPED_ONLY
|
||||||
|
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
@ -697,8 +714,9 @@ static bool stack_leak_detection(GB_gameboy_t *gb, char *arguments, const debugg
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool registers(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool registers(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
print_usage(gb, command);
|
print_usage(gb, command);
|
||||||
return true;
|
return true;
|
||||||
@ -739,8 +757,9 @@ static uint16_t find_breakpoint(GB_gameboy_t *gb, value_t addr)
|
|||||||
return (uint16_t) min;
|
return (uint16_t) min;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool breakpoint(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool breakpoint(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
if (strlen(lstrip(arguments)) == 0) {
|
if (strlen(lstrip(arguments)) == 0) {
|
||||||
print_usage(gb, command);
|
print_usage(gb, command);
|
||||||
return true;
|
return true;
|
||||||
@ -804,8 +823,9 @@ static bool breakpoint(GB_gameboy_t *gb, char *arguments, const debugger_command
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool delete(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool delete(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
if (strlen(lstrip(arguments)) == 0) {
|
if (strlen(lstrip(arguments)) == 0) {
|
||||||
for (unsigned i = gb->n_breakpoints; i--;) {
|
for (unsigned i = gb->n_breakpoints; i--;) {
|
||||||
if (gb->breakpoints[i].condition) {
|
if (gb->breakpoints[i].condition) {
|
||||||
@ -864,7 +884,7 @@ static uint16_t find_watchpoint(GB_gameboy_t *gb, value_t addr)
|
|||||||
return (uint16_t) min;
|
return (uint16_t) min;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool watch(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool watch(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
if (strlen(lstrip(arguments)) == 0) {
|
if (strlen(lstrip(arguments)) == 0) {
|
||||||
print_usage:
|
print_usage:
|
||||||
@ -877,9 +897,13 @@ print_usage:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!modifiers) {
|
||||||
|
modifiers = "w";
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t flags = 0;
|
uint8_t flags = 0;
|
||||||
while (*arguments != ' ' && *arguments) {
|
while (*modifiers) {
|
||||||
switch (*arguments) {
|
switch (*modifiers) {
|
||||||
case 'r':
|
case 'r':
|
||||||
flags |= GB_WATCHPOINT_R;
|
flags |= GB_WATCHPOINT_R;
|
||||||
break;
|
break;
|
||||||
@ -889,7 +913,7 @@ print_usage:
|
|||||||
default:
|
default:
|
||||||
goto print_usage;
|
goto print_usage;
|
||||||
}
|
}
|
||||||
arguments++;
|
modifiers++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flags) {
|
if (!flags) {
|
||||||
@ -956,8 +980,9 @@ print_usage:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool unwatch(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool unwatch(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
if (strlen(lstrip(arguments)) == 0) {
|
if (strlen(lstrip(arguments)) == 0) {
|
||||||
for (unsigned i = gb->n_watchpoints; i--;) {
|
for (unsigned i = gb->n_watchpoints; i--;) {
|
||||||
if (gb->watchpoints[i].condition) {
|
if (gb->watchpoints[i].condition) {
|
||||||
@ -994,8 +1019,9 @@ static bool unwatch(GB_gameboy_t *gb, char *arguments, const debugger_command_t
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool list(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool list(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
print_usage(gb, command);
|
print_usage(gb, command);
|
||||||
return true;
|
return true;
|
||||||
@ -1077,22 +1103,61 @@ static bool should_break(GB_gameboy_t *gb, uint16_t addr)
|
|||||||
return _should_break(gb, full_addr);
|
return _should_break(gb, full_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool print(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool print(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
if (strlen(lstrip(arguments)) == 0) {
|
if (strlen(lstrip(arguments)) == 0) {
|
||||||
print_usage(gb, command);
|
print_usage(gb, command);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!modifiers || !modifiers[0]) {
|
||||||
|
modifiers = "a";
|
||||||
|
}
|
||||||
|
else if (modifiers[1]) {
|
||||||
|
print_usage(gb, command);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool error;
|
bool error;
|
||||||
value_t result = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error, NULL, NULL);
|
value_t result = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error, NULL, NULL);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
switch (modifiers[0]) {
|
||||||
|
case 'a':
|
||||||
GB_log(gb, "=%s\n", debugger_value_to_string(gb, result, false));
|
GB_log(gb, "=%s\n", debugger_value_to_string(gb, result, false));
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
GB_log(gb, "=%d\n", result.value);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
GB_log(gb, "=$%x\n", result.value);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
GB_log(gb, "=0%o\n", result.value);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
{
|
||||||
|
if (!result.value) {
|
||||||
|
GB_log(gb, "=%%0\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char binary[17];
|
||||||
|
binary[16] = 0;
|
||||||
|
char *ptr = &binary[16];
|
||||||
|
while (result.value) {
|
||||||
|
*(--ptr) = (result.value & 1)? '1' : '0';
|
||||||
|
result.value >>= 1;
|
||||||
|
}
|
||||||
|
GB_log(gb, "=%%%s\n", ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool examine(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool examine(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
if (strlen(lstrip(arguments)) == 0) {
|
if (strlen(lstrip(arguments)) == 0) {
|
||||||
print_usage(gb, command);
|
print_usage(gb, command);
|
||||||
@ -1101,33 +1166,54 @@ static bool examine(GB_gameboy_t *gb, char *arguments, const debugger_command_t
|
|||||||
|
|
||||||
bool error;
|
bool error;
|
||||||
value_t addr = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error, NULL, NULL);
|
value_t addr = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error, NULL, NULL);
|
||||||
|
uint16_t count = 32;
|
||||||
|
|
||||||
|
if (modifiers) {
|
||||||
|
char *end;
|
||||||
|
count = (uint16_t) (strtol(modifiers, &end, 10));
|
||||||
|
if (*end) {
|
||||||
|
print_usage(gb, command);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
if (addr.has_bank) {
|
if (addr.has_bank) {
|
||||||
banking_state_t old_state;
|
banking_state_t old_state;
|
||||||
save_banking_state(gb, &old_state);
|
save_banking_state(gb, &old_state);
|
||||||
switch_banking_state(gb, addr.bank);
|
switch_banking_state(gb, addr.bank);
|
||||||
|
|
||||||
|
while (count) {
|
||||||
GB_log(gb, "%02x:%04x: ", addr.bank, addr.value);
|
GB_log(gb, "%02x:%04x: ", addr.bank, addr.value);
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16 && count; i++) {
|
||||||
GB_log(gb, "%02x ", GB_read_memory(gb, addr.value + i));
|
GB_log(gb, "%02x ", GB_read_memory(gb, addr.value + i));
|
||||||
|
count--;
|
||||||
}
|
}
|
||||||
|
addr.value += 16;
|
||||||
GB_log(gb, "\n");
|
GB_log(gb, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
restore_banking_state(gb, &old_state);
|
restore_banking_state(gb, &old_state);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
while (count) {
|
||||||
GB_log(gb, "%04x: ", addr.value);
|
GB_log(gb, "%04x: ", addr.value);
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16 && count; i++) {
|
||||||
GB_log(gb, "%02x ", GB_read_memory(gb, addr.value + i));
|
GB_log(gb, "%02x ", GB_read_memory(gb, addr.value + i));
|
||||||
|
count--;
|
||||||
}
|
}
|
||||||
|
addr.value += 16;
|
||||||
GB_log(gb, "\n");
|
GB_log(gb, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mbc(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool mbc(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
|
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
print_usage(gb, command);
|
print_usage(gb, command);
|
||||||
return true;
|
return true;
|
||||||
@ -1181,8 +1267,10 @@ static bool mbc(GB_gameboy_t *gb, char *arguments, const debugger_command_t *com
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool backtrace(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool backtrace(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
|
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
print_usage(gb, command);
|
print_usage(gb, command);
|
||||||
return true;
|
return true;
|
||||||
@ -1196,8 +1284,9 @@ static bool backtrace(GB_gameboy_t *gb, char *arguments, const debugger_command_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ticks(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool ticks(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
STOPPED_ONLY
|
STOPPED_ONLY
|
||||||
|
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
@ -1212,8 +1301,9 @@ static bool ticks(GB_gameboy_t *gb, char *arguments, const debugger_command_t *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool palettes(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
|
static bool palettes(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||||
{
|
{
|
||||||
|
NO_MODIFIERS
|
||||||
if (strlen(lstrip(arguments))) {
|
if (strlen(lstrip(arguments))) {
|
||||||
print_usage(gb, command);
|
print_usage(gb, command);
|
||||||
return true;
|
return true;
|
||||||
@ -1242,7 +1332,7 @@ static bool palettes(GB_gameboy_t *gb, char *arguments, const debugger_command_t
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static bool help(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command);
|
static bool help(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command);
|
||||||
|
|
||||||
#define HELP_NEWLINE "\n "
|
#define HELP_NEWLINE "\n "
|
||||||
|
|
||||||
@ -1254,24 +1344,28 @@ static const debugger_command_t commands[] = {
|
|||||||
{"finish", 1, finish, "Run until the current function returns"},
|
{"finish", 1, finish, "Run until the current function returns"},
|
||||||
{"backtrace", 2, backtrace, "Display the current call stack"},
|
{"backtrace", 2, backtrace, "Display the current call stack"},
|
||||||
{"bt", 2, }, /* Alias */
|
{"bt", 2, }, /* Alias */
|
||||||
{"sld", 3, stack_leak_detection, "Like finish, but stops if a stack leak is detected. (Experimental)"},
|
{"sld", 3, stack_leak_detection, "Like finish, but stops if a stack leak is detected (Experimental)"},
|
||||||
{"ticks", 2, ticks, "Display the number of CPU ticks since the last time 'ticks' was used. "},
|
{"ticks", 2, ticks, "Display the number of CPU ticks since the last time 'ticks' was used"},
|
||||||
{"registers", 1, registers, "Print values of processor registers and other important registers"},
|
{"registers", 1, registers, "Print values of processor registers and other important registers"},
|
||||||
{"cartridge", 2, mbc, "Displays information about the MBC and cartridge"},
|
{"cartridge", 2, mbc, "Displays information about the MBC and cartridge"},
|
||||||
{"mbc", 3, }, /* Alias */
|
{"mbc", 3, }, /* Alias */
|
||||||
{"palettes", 3, palettes, "Displays the current CGB palettes"},
|
{"palettes", 3, palettes, "Displays the current CGB palettes"},
|
||||||
{"breakpoint", 1, breakpoint, "Add a new breakpoint at the specified address/expression." HELP_NEWLINE
|
{"breakpoint", 1, breakpoint, "Add a new breakpoint at the specified address/expression" HELP_NEWLINE
|
||||||
"Can also modify the condition of existing breakpoints.",
|
"Can also modify the condition of existing breakpoints.",
|
||||||
"<expression>[ if <condition expression>]"},
|
"<expression>[ if <condition expression>]"},
|
||||||
{"delete", 2, delete, "Delete a breakpoint by its address, or all breakpoints", "[<expression>]"},
|
{"delete", 2, delete, "Delete a breakpoint by its address, or all breakpoints", "[<expression>]"},
|
||||||
{"watch", 1, watch, "Add a new watchpoint at the specified address/expression." HELP_NEWLINE
|
{"watch", 1, watch, "Add a new watchpoint at the specified address/expression." HELP_NEWLINE
|
||||||
"Can also modify the condition and type of existing watchpoints.",
|
"Can also modify the condition and type of existing watchpoints." HELP_NEWLINE
|
||||||
" (r|w|rw) <expression>[ if <condition expression>]"},
|
"Default watchpoint type is write-only.",
|
||||||
|
"<expression>[ if <condition expression>]", "(r|w|rw)"},
|
||||||
{"unwatch", 3, unwatch, "Delete a watchpoint by its address, or all watchpoints", "[<expression>]"},
|
{"unwatch", 3, unwatch, "Delete a watchpoint by its address, or all watchpoints", "[<expression>]"},
|
||||||
{"list", 1, list, "List all set breakpoints and watchpoints"},
|
{"list", 1, list, "List all set breakpoints and watchpoints"},
|
||||||
{"print", 1, print, "Evaluate and print an expression", "<expression>"},
|
{"print", 1, print, "Evaluate and print an expression" HELP_NEWLINE
|
||||||
|
"Use modifier to format as an address (a, default) or as a number in" HELP_NEWLINE
|
||||||
|
"decimal (d), hexadecimal (x), octal (o) or binary (b).",
|
||||||
|
"<expression>", "format"},
|
||||||
{"eval", 2, }, /* Alias */
|
{"eval", 2, }, /* Alias */
|
||||||
{"examine", 2, examine, "Examine values at address", "<expression>"},
|
{"examine", 2, examine, "Examine values at address", "<expression>", "count"},
|
||||||
{"x", 1, }, /* Alias */
|
{"x", 1, }, /* Alias */
|
||||||
|
|
||||||
{"help", 1, help, "List available commands or show help for the specified command", "[<command>]"},
|
{"help", 1, help, "List available commands or show help for the specified command", "[<command>]"},
|
||||||
@ -1308,7 +1402,7 @@ static void print_command_description(GB_gameboy_t *gb, const debugger_command_t
|
|||||||
GB_log(gb, (const char *)&" %s\n" + strlen(command->command), command->help_string);
|
GB_log(gb, (const char *)&" %s\n" + strlen(command->command), command->help_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool help(GB_gameboy_t *gb, char *arguments, const debugger_command_t *ignored)
|
static bool help(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *ignored)
|
||||||
{
|
{
|
||||||
const debugger_command_t *command = find_command(arguments);
|
const debugger_command_t *command = find_command(arguments);
|
||||||
if (command) {
|
if (command) {
|
||||||
@ -1512,9 +1606,16 @@ bool GB_debugger_do_command(GB_gameboy_t *gb, char *input)
|
|||||||
arguments = "";
|
arguments = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *modifiers = strchr(command_string, '/');
|
||||||
|
if (modifiers) {
|
||||||
|
/* Actually "split" the string. */
|
||||||
|
modifiers[0] = 0;
|
||||||
|
modifiers++;
|
||||||
|
}
|
||||||
|
|
||||||
const debugger_command_t *command = find_command(command_string);
|
const debugger_command_t *command = find_command(command_string);
|
||||||
if (command) {
|
if (command) {
|
||||||
return command->implementation(gb, arguments, command);
|
return command->implementation(gb, arguments, modifiers, command);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GB_log(gb, "%s: no such command.\n", command_string);
|
GB_log(gb, "%s: no such command.\n", command_string);
|
||||||
|
Loading…
Reference in New Issue
Block a user