SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit 29becc2870bce9c7820d84642ab0d39ccc4c5dc9 parent d209628369824f7d4bdca9e55020bd2dc5730ffc Author: Lior Halphon <LIJI32@gmail.com> Date: Sat, 29 Jul 2023 14:51:31 +0300 Treat local and non-local symbols differently Diffstat:
| M | Core/debugger.c | 68 | ++++++++++++++++++++++++++++++++++---------------------------------- |
| M | Core/debugger.h | 2 | +- |
| M | Core/sm83_disassembler.c | 4 | ++-- |
| M | Core/symbol_hash.c | 16 | +++++++++------- |
| M | Core/symbol_hash.h | 3 | ++- |
5 files changed, 48 insertions(+), 45 deletions(-)
diff --git a/Core/debugger.c b/Core/debugger.c @@ -126,10 +126,10 @@ static inline void switch_banking_state(GB_gameboy_t *gb, uint16_t bank) } } -static const char *value_to_string(GB_gameboy_t *gb, uint16_t value, bool prefer_name) +static const char *value_to_string(GB_gameboy_t *gb, uint16_t value, bool prefer_name, bool prefer_local) { static __thread char output[256]; - const GB_bank_symbol_t *symbol = GB_debugger_find_symbol(gb, value); + const GB_bank_symbol_t *symbol = GB_debugger_find_symbol(gb, value, prefer_local); if (symbol && (value - symbol->addr > 0x1000 || symbol->addr == 0) ) { symbol = NULL; @@ -167,12 +167,12 @@ static GB_symbol_map_t *get_symbol_map(GB_gameboy_t *gb, uint16_t bank) return gb->bank_symbols[bank]; } -static const char *debugger_value_to_string(GB_gameboy_t *gb, value_t value, bool prefer_name) +static const char *debugger_value_to_string(GB_gameboy_t *gb, value_t value, bool prefer_name, bool prefer_local) { - if (!value.has_bank) return value_to_string(gb, value.value, prefer_name); + if (!value.has_bank) return value_to_string(gb, value.value, prefer_name, prefer_local); static __thread char output[256]; - const GB_bank_symbol_t *symbol = GB_map_find_symbol(get_symbol_map(gb, value.bank), value.value); + const GB_bank_symbol_t *symbol = GB_map_find_symbol(get_symbol_map(gb, value.bank), value.value, prefer_local); if (symbol && (value.value - symbol->addr > 0x1000 || symbol->addr == 0) ) { symbol = NULL; @@ -890,11 +890,11 @@ static bool registers(GB_gameboy_t *gb, char *arguments, char *modifiers, const (gb->f & GB_HALF_CARRY_FLAG)? 'H' : '-', (gb->f & GB_SUBTRACT_FLAG)? 'N' : '-', (gb->f & GB_ZERO_FLAG)? 'Z' : '-'); - GB_log(gb, "BC = %s\n", value_to_string(gb, gb->bc, false)); - GB_log(gb, "DE = %s\n", value_to_string(gb, gb->de, false)); - GB_log(gb, "HL = %s\n", value_to_string(gb, gb->hl, false)); - GB_log(gb, "SP = %s\n", value_to_string(gb, gb->sp, false)); - GB_log(gb, "PC = %s\n", value_to_string(gb, gb->pc, false)); + GB_log(gb, "BC = %s\n", value_to_string(gb, gb->bc, false, false)); + GB_log(gb, "DE = %s\n", value_to_string(gb, gb->de, false, false)); + GB_log(gb, "HL = %s\n", value_to_string(gb, gb->hl, false, false)); + GB_log(gb, "SP = %s\n", value_to_string(gb, gb->sp, false, false)); + GB_log(gb, "PC = %s\n", value_to_string(gb, gb->pc, false, false)); GB_log(gb, "IME = %s\n", gb->ime? "Enabled" : "Disabled"); return true; } @@ -1067,9 +1067,9 @@ static bool breakpoint(GB_gameboy_t *gb, char *arguments, char *modifiers, const gb->has_jump_to_breakpoints = true; } - GB_log(gb, "Breakpoint %u set at %s", id, debugger_value_to_string(gb, result, true)); + GB_log(gb, "Breakpoint %u set at %s", id, debugger_value_to_string(gb, result, true, false)); if (length) { - GB_log(gb, " - %s\n", debugger_value_to_string(gb, end, true)); + GB_log(gb, " - %s\n", debugger_value_to_string(gb, end, true, true)); } else { GB_log(gb, "\n"); @@ -1124,7 +1124,7 @@ static bool delete(GB_gameboy_t *gb, char *arguments, char *modifiers, const deb value_t addr = (value_t){gb->breakpoints[i].bank != (uint16_t)-1, gb->breakpoints[i].bank, gb->breakpoints[i].addr}; - GB_log(gb, "Breakpoint %u removed from %s\n", id, debugger_value_to_string(gb, addr, addr.has_bank)); + GB_log(gb, "Breakpoint %u removed from %s\n", id, debugger_value_to_string(gb, addr, addr.has_bank, false)); return true; } @@ -1239,9 +1239,9 @@ static bool watch(GB_gameboy_t *gb, char *arguments, char *modifiers, const debu .length = length, }; - GB_log(gb, "Watchpoint %u set at %s", id, debugger_value_to_string(gb, result, true)); + GB_log(gb, "Watchpoint %u set at %s", id, debugger_value_to_string(gb, result, true, false)); if (length) { - GB_log(gb, " - %s\n", debugger_value_to_string(gb, end, true)); + GB_log(gb, " - %s\n", debugger_value_to_string(gb, end, true, true)); } else { GB_log(gb, "\n"); @@ -1284,7 +1284,7 @@ static bool unwatch(GB_gameboy_t *gb, char *arguments, char *modifiers, const de value_t addr = (value_t){gb->watchpoints[i].bank != (uint16_t)-1, gb->watchpoints[i].bank, gb->watchpoints[i].addr}; - GB_log(gb, "Watchpoint %u removed from %s\n", id, debugger_value_to_string(gb, addr, addr.has_bank)); + GB_log(gb, "Watchpoint %u removed from %s\n", id, debugger_value_to_string(gb, addr, addr.has_bank, false)); return true; } @@ -1311,11 +1311,11 @@ static bool list(GB_gameboy_t *gb, char *arguments, char *modifiers, const debug if (gb->breakpoints[i].length) { value_t end = addr; end.value += gb->breakpoints[i].length + 1; - end_string = strdup(debugger_value_to_string(gb, end, addr.has_bank)); + end_string = strdup(debugger_value_to_string(gb, end, addr.has_bank, true)); } if (gb->breakpoints[i].condition) { GB_log(gb, " %d. %s%s%s (%sCondition: %s)\n", gb->breakpoints[i].id, - debugger_value_to_string(gb, addr, addr.has_bank), + debugger_value_to_string(gb, addr, addr.has_bank, false), end_string? " - " : "", end_string ?: "", gb->breakpoints[i].is_jump_to? "Jump to, ": "", @@ -1323,7 +1323,7 @@ static bool list(GB_gameboy_t *gb, char *arguments, char *modifiers, const debug } else { GB_log(gb, " %d. %s%s%s%s\n", gb->breakpoints[i].id, - debugger_value_to_string(gb, addr, addr.has_bank), + debugger_value_to_string(gb, addr, addr.has_bank, false), end_string? " - " : "", end_string ?: "", gb->breakpoints[i].is_jump_to? " (Jump to)" : ""); @@ -1345,17 +1345,17 @@ static bool list(GB_gameboy_t *gb, char *arguments, char *modifiers, const debug if (gb->watchpoints[i].length) { value_t end = addr; end.value += gb->watchpoints[i].length + 1; - end_string = strdup(debugger_value_to_string(gb, end, addr.has_bank)); + end_string = strdup(debugger_value_to_string(gb, end, addr.has_bank, true)); } if (gb->watchpoints[i].condition) { - GB_log(gb, " %d. %s%s%s (%c%c, Condition: %s)\n", gb->watchpoints[i].id, debugger_value_to_string(gb, addr, addr.has_bank), + GB_log(gb, " %d. %s%s%s (%c%c, Condition: %s)\n", gb->watchpoints[i].id, debugger_value_to_string(gb, addr, addr.has_bank, false), end_string? " - " : "", end_string ?: "", (gb->watchpoints[i].flags & WATCHPOINT_READ)? 'r' : '-', (gb->watchpoints[i].flags & WATCHPOINT_WRITE)? 'w' : '-', gb->watchpoints[i].condition); } else { - GB_log(gb, " %d. %s%s%s (%c%c)\n", gb->watchpoints[i].id, debugger_value_to_string(gb, addr, addr.has_bank), + GB_log(gb, " %d. %s%s%s (%c%c)\n", gb->watchpoints[i].id, debugger_value_to_string(gb, addr, addr.has_bank, false), end_string? " - " : "", end_string ?: "", (gb->watchpoints[i].flags & WATCHPOINT_READ)? 'r' : '-', (gb->watchpoints[i].flags & WATCHPOINT_WRITE)? 'w' : '-'); @@ -1427,7 +1427,7 @@ static bool print(GB_gameboy_t *gb, char *arguments, char *modifiers, const debu 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, false)); break; case 'd': GB_log(gb, "=%d\n", result.value); @@ -1634,9 +1634,9 @@ static bool backtrace(GB_gameboy_t *gb, char *arguments, char *modifiers, const return true; } - GB_log(gb, " 1. %s\n", debugger_value_to_string(gb, (value_t){true, bank_for_addr(gb, gb->pc), gb->pc}, true)); + GB_log(gb, " 1. %s\n", debugger_value_to_string(gb, (value_t){true, bank_for_addr(gb, gb->pc), gb->pc}, true, false)); for (unsigned i = gb->backtrace_size; i--;) { - GB_log(gb, "%3d. %s\n", gb->backtrace_size - i + 1, debugger_value_to_string(gb, (value_t){true, gb->backtrace_returns[i].bank, gb->backtrace_returns[i].addr}, true)); + GB_log(gb, "%3d. %s\n", gb->backtrace_size - i + 1, debugger_value_to_string(gb, (value_t){true, gb->backtrace_returns[i].bank, gb->backtrace_returns[i].addr}, true, false)); } return true; @@ -2224,10 +2224,10 @@ static void test_watchpoint(GB_gameboy_t *gb, uint16_t addr, uint8_t flags, uint condition_ok: GB_debugger_break(gb); if (flags == WATCHPOINT_READ) { - GB_log(gb, "Watchpoint %u: [%s]\n", watchpoint->id, value_to_string(gb, addr, true)); + GB_log(gb, "Watchpoint %u: [%s]\n", watchpoint->id, value_to_string(gb, addr, true, false)); } else { - GB_log(gb, "Watchpoint %u: [%s] = $%02x\n", watchpoint->id, value_to_string(gb, addr, true), value); + GB_log(gb, "Watchpoint %u: [%s] = $%02x\n", watchpoint->id, value_to_string(gb, addr, true, false), value); } return; } @@ -2417,7 +2417,7 @@ next_command: unsigned breakpoint_id = 0; if (gb->breakpoints && !gb->debug_stopped && (breakpoint_id = should_break(gb, gb->pc, false))) { GB_debugger_break(gb); - GB_log(gb, "Breakpoint %u: PC = %s\n", breakpoint_id, value_to_string(gb, gb->pc, true)); + GB_log(gb, "Breakpoint %u: PC = %s\n", breakpoint_id, value_to_string(gb, gb->pc, true, false)); GB_cpu_disassemble(gb, gb->pc, 5); } @@ -2428,7 +2428,7 @@ next_command: bool should_delete_state = true; if (jump_to_result == JUMP_TO_BREAK) { GB_debugger_break(gb); - GB_log(gb, "Jumping to breakpoint %u: %s\n", breakpoint_id, value_to_string(gb, address, true)); + GB_log(gb, "Jumping to breakpoint %u: %s\n", breakpoint_id, value_to_string(gb, address, true, false)); GB_cpu_disassemble(gb, gb->pc, 5); gb->non_trivial_jump_breakpoint_occured = false; } @@ -2438,7 +2438,7 @@ next_command: } else { gb->non_trivial_jump_breakpoint_occured = true; - GB_log(gb, "Jumping to breakpoint %u: %s\n", breakpoint_id, value_to_string(gb, gb->pc, true)); + GB_log(gb, "Jumping to breakpoint %u: %s\n", breakpoint_id, value_to_string(gb, gb->pc, true, false)); GB_load_state_from_buffer(gb, gb->nontrivial_jump_state, -1); GB_cpu_disassemble(gb, gb->pc, 5); GB_debugger_break(gb); @@ -2570,20 +2570,20 @@ void GB_debugger_clear_symbols(GB_gameboy_t *gb) } } -const GB_bank_symbol_t *GB_debugger_find_symbol(GB_gameboy_t *gb, uint16_t addr) +const GB_bank_symbol_t *GB_debugger_find_symbol(GB_gameboy_t *gb, uint16_t addr, bool prefer_local) { uint16_t bank = bank_for_addr(gb, addr); - const GB_bank_symbol_t *symbol = GB_map_find_symbol(get_symbol_map(gb, bank), addr); + const GB_bank_symbol_t *symbol = GB_map_find_symbol(get_symbol_map(gb, bank), addr, prefer_local); if (symbol) return symbol; - if (bank != 0) return GB_map_find_symbol(get_symbol_map(gb, 0), addr); /* Maybe the symbol incorrectly uses bank 0? */ + if (bank != 0) return GB_map_find_symbol(get_symbol_map(gb, 0), addr, false); /* Maybe the symbol incorrectly uses bank 0? */ return NULL; } const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr) { - const GB_bank_symbol_t *symbol = GB_debugger_find_symbol(gb, addr); + const GB_bank_symbol_t *symbol = GB_debugger_find_symbol(gb, addr, false); if (symbol && symbol->addr == addr) return symbol->name; return NULL; } diff --git a/Core/debugger.h b/Core/debugger.h @@ -27,7 +27,7 @@ internal void GB_debugger_call_hook(GB_gameboy_t *gb, uint16_t call_addr); internal void GB_debugger_ret_hook(GB_gameboy_t *gb); internal void GB_debugger_test_write_watchpoint(GB_gameboy_t *gb, uint16_t addr, uint8_t value); internal void GB_debugger_test_read_watchpoint(GB_gameboy_t *gb, uint16_t addr); -internal const GB_bank_symbol_t *GB_debugger_find_symbol(GB_gameboy_t *gb, uint16_t addr); +internal const GB_bank_symbol_t *GB_debugger_find_symbol(GB_gameboy_t *gb, uint16_t addr, bool prefer_local); internal void GB_debugger_add_symbol(GB_gameboy_t *gb, uint16_t bank, uint16_t address, const char *symbol); #endif diff --git a/Core/sm83_disassembler.c b/Core/sm83_disassembler.c @@ -758,7 +758,7 @@ static opcode_t *opcodes[256] = { void GB_cpu_disassemble(GB_gameboy_t *gb, uint16_t pc, uint16_t count) { - const GB_bank_symbol_t *function_symbol = GB_debugger_find_symbol(gb, pc); + const GB_bank_symbol_t *function_symbol = GB_debugger_find_symbol(gb, pc, false); if (function_symbol && pc - function_symbol->addr > 0x1000) { function_symbol = NULL; @@ -771,7 +771,7 @@ void GB_cpu_disassemble(GB_gameboy_t *gb, uint16_t pc, uint16_t count) uint16_t current_function = function_symbol? function_symbol->addr : 0; while (count--) { - function_symbol = GB_debugger_find_symbol(gb, pc); + function_symbol = GB_debugger_find_symbol(gb, pc, false); if (function_symbol && function_symbol->addr == pc) { if (current_function != function_symbol->addr) { GB_log(gb, "\n"); diff --git a/Core/symbol_hash.c b/Core/symbol_hash.c @@ -4,7 +4,7 @@ #include <string.h> #include <sys/types.h> -static size_t map_find_symbol_index(GB_symbol_map_t *map, uint16_t addr) +static size_t map_find_symbol_index(GB_symbol_map_t *map, uint16_t addr, bool is_local) { if (!map->symbols) { return 0; @@ -13,8 +13,8 @@ static size_t map_find_symbol_index(GB_symbol_map_t *map, uint16_t addr) ssize_t max = map->n_symbols; while (min < max) { size_t pivot = (min + max) / 2; - if (map->symbols[pivot].addr == addr) return pivot; - if (map->symbols[pivot].addr > addr) { + if (map->symbols[pivot].addr == addr && map->symbols[pivot].is_local == is_local) return pivot; + if ((map->symbols[pivot].addr * 2 + !map->symbols[pivot].is_local) > (addr * 2 + !is_local)) { max = pivot; } else { @@ -26,25 +26,27 @@ static size_t map_find_symbol_index(GB_symbol_map_t *map, uint16_t addr) GB_bank_symbol_t *GB_map_add_symbol(GB_symbol_map_t *map, uint16_t addr, const char *name) { - size_t index = map_find_symbol_index(map, addr); + bool is_local = strchr(name, '.'); + size_t index = map_find_symbol_index(map, addr, is_local); map->symbols = realloc(map->symbols, (map->n_symbols + 1) * sizeof(map->symbols[0])); memmove(&map->symbols[index + 1], &map->symbols[index], (map->n_symbols - index) * sizeof(map->symbols[0])); map->symbols[index].addr = addr; map->symbols[index].name = strdup(name); + map->symbols[index].is_local = is_local; map->n_symbols++; return &map->symbols[index]; } -const GB_bank_symbol_t *GB_map_find_symbol(GB_symbol_map_t *map, uint16_t addr) +const GB_bank_symbol_t *GB_map_find_symbol(GB_symbol_map_t *map, uint16_t addr, bool prefer_local) { if (!map) return NULL; - size_t index = map_find_symbol_index(map, addr); + size_t index = map_find_symbol_index(map, addr, prefer_local); if (index >= map->n_symbols || map->symbols[index].addr != addr) { index--; } if (index < map->n_symbols) { - while (index && map->symbols[index].addr == map->symbols[index - 1].addr) { + while (index && map->symbols[index].addr == map->symbols[index - 1].addr && map->symbols[index].is_local == map->symbols[index - 1].is_local) { index--; } return &map->symbols[index]; diff --git a/Core/symbol_hash.h b/Core/symbol_hash.h @@ -8,6 +8,7 @@ typedef struct { char *name; uint16_t addr; + bool is_local; } GB_bank_symbol_t; typedef struct GB_symbol_s { @@ -30,7 +31,7 @@ typedef struct { internal void GB_reversed_map_add_symbol(GB_reversed_symbol_map_t *map, uint16_t bank, GB_bank_symbol_t *symbol); internal const GB_symbol_t *GB_reversed_map_find_symbol(GB_reversed_symbol_map_t *map, const char *name); internal GB_bank_symbol_t *GB_map_add_symbol(GB_symbol_map_t *map, uint16_t addr, const char *name); -internal const GB_bank_symbol_t *GB_map_find_symbol(GB_symbol_map_t *map, uint16_t addr); +internal const GB_bank_symbol_t *GB_map_find_symbol(GB_symbol_map_t *map, uint16_t addr, bool prefer_local); internal GB_symbol_map_t *GB_map_alloc(void); internal void GB_map_free(GB_symbol_map_t *map); #endif
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.