Mercurial > repos > blastem
changeset 2720:7dcc84cb14ee default tip
Get uPD78K/II partially hooked up in debugger
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 16 Jul 2025 19:26:38 -0700 |
parents | f817aedf5e53 |
children | |
files | debug.c debug.h laseractive.c |
diffstat | 3 files changed, 230 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/debug.c Wed Jul 16 18:01:21 2025 -0700 +++ b/debug.c Wed Jul 16 19:26:38 2025 -0700 @@ -4,6 +4,7 @@ #include "segacd.h" #include "blastem.h" #include "bindings.h" +#include "upd78k2_dis.h" #include <ctype.h> #include <math.h> #include <stdlib.h> @@ -1560,7 +1561,7 @@ *out = m68k_read_long(*out, context); } else { if (*out & 1) { - fprintf(stderr, "Wword access to odd addresses ($%X) is not allowed\n", *out); + fprintf(stderr, "Word access to odd addresses ($%X) is not allowed\n", *out); return 0; } *out = m68k_read_word(*out, context); @@ -2301,9 +2302,11 @@ process_events(); #ifndef IS_LIB render_update_display(); - vdp_context *vdp = current_system->get_vdp(current_system); - if (vdp) { - vdp_update_per_frame_debug(vdp); + if (current_system->get_vdp) { + vdp_context *vdp = current_system->get_vdp(current_system); + if (vdp) { + vdp_update_per_frame_debug(vdp); + } } #endif } @@ -5033,6 +5036,138 @@ return root; } +static uint8_t read_upd_byte(upd78k2_context *upd, uint32_t address) +{ + if (address > 0xFE00 && address < 0xFF00) { + return upd->iram[address & 0xFF]; + } + return read_byte(address, (void **)upd->mem_pointers, &upd->opts->gen, upd); +} + +static uint8_t read_upd(debug_root *root, uint32_t *out, char size) +{ + upd78k2_context *upd = root->cpu_context; + uint32_t address = *out; + *out = read_upd_byte(upd, address); + if (size != 'b') { + *out |= read_upd_byte(upd, address + 1) << 8; + if (size == 'l') { + *out |= read_upd_byte(upd, address + 2) << 16; + *out |= read_upd_byte(upd, address + 3) << 24; + } + } + return 1; +} + +static void write_upd_byte(upd78k2_context *upd, uint32_t address, uint8_t value) +{ + if (address > 0xFE00 && address < 0xFF00) { + upd->iram[address & 0xFF] = value; + } else { + write_byte(address, value, (void **)upd->mem_pointers, &upd->opts->gen, upd); + } +} + +static uint8_t write_upd(debug_root *root, uint32_t address, uint32_t value, char size) +{ + upd78k2_context *upd = root->cpu_context; + write_upd_byte(upd, address, value); + if (size != 'b') { + write_upd_byte(upd, address + 1, value >> 8); + if (size == 'l') { + write_upd_byte(upd, address + 2, value >> 16); + write_upd_byte(upd, address + 3, value >> 24); + } + } + return 1; +} + +static uint32_t upd_chunk_end(debug_root *root, uint32_t start_address) +{ + upd78k2_context *upd = root->cpu_context; + memmap_chunk const *chunk = find_map_chunk(start_address, &upd->opts->gen, 0, NULL); + if (!chunk) { + return start_address; + } + if (chunk->mask == upd->opts->gen.address_mask) { + return chunk->end; + } + return (start_address & ~chunk->mask) + chunk->mask + 1; +} + +static debug_val upd_reg_get(debug_var *var) +{ + upd78k2_context *upd = var->ptr; + return debug_int(upd->main[var->val.v.u32]); +} + +static void upd_reg_set(debug_var *var, debug_val val) +{ + upd78k2_context *upd = var->ptr; + uint32_t ival; + if (!debug_cast_int(val, &ival)) { + static const char regs[] = "xacbedlh"; + fprintf(stderr, "uPD78K/II register %c can only be set to an integer\n", regs[var->val.v.u32]); + return; + } + upd->main[var->val.v.u32] = ival; +} + +static debug_val upd_regpair_get(debug_var *var) +{ + upd78k2_context *upd = var->ptr; + uint16_t val = upd->main[var->val.v.u32 * 2]; + val |= upd->main[var->val.v.u32 * 2 + 1] << 8; + return debug_int(val); +} + +static void upd_regpair_set(debug_var *var, debug_val val) +{ + upd78k2_context *upd = var->ptr; + uint32_t ival; + if (!debug_cast_int(val, &ival)) { + static const char regs[] = "xacbedlh"; + fprintf(stderr, "uPD78K/II register %c can only be set to an integer\n", regs[var->val.v.u32]); + return; + } + upd->main[var->val.v.u32 * 2] = ival; + upd->main[var->val.v.u32 * 2 + 1] = ival >> 8; +} + +debug_root *find_upd_root(upd78k2_context *upd) +{ + debug_root *root = find_root(upd); + if (root && !root->commands) { + add_commands(root, common_commands, NUM_COMMON); + root->read_mem = read_upd; + root->write_mem = write_upd; + root->chunk_end = upd_chunk_end; + root->disasm = create_upd78k2_disasm(); + static const char *regs[] = {"x","a","c","b","e","d","l","h"}; + static const char *regpairs[] = {"ax", "bc", "de", "hl"}; + debug_var *var; + for (int i = 0; i < sizeof(regs)/sizeof(*regs); i++) + { + var = calloc(1, sizeof(debug_var)); + var->get = upd_reg_get; + var->set = upd_reg_set; + var->ptr = root->cpu_context; + var->val.v.u32 = i; + root->variables = tern_insert_ptr(root->variables, regs[i], var); + } + for (int i = 0; i < sizeof(regpairs)/sizeof(*regpairs); i++) + { + var = calloc(1, sizeof(debug_var)); + var->get = upd_regpair_get; + var->set = upd_regpair_set; + var->ptr = root->cpu_context; + var->val.v.u32 = i; + root->variables = tern_insert_ptr(root->variables, regpairs[i], var); + } + } + return root; +} + #ifndef NO_Z80 #ifdef NEW_CORE #define Z80_OPTS opts @@ -5664,3 +5799,84 @@ debugger_repl(root); return; } + +static uint8_t upd_debug_fetch(uint16_t address, void *data) +{ + upd78k2_context *upd = data; + return read_byte(address, (void **)upd->mem_pointers, &upd->opts->gen, upd); +} + +void upd_debugger(upd78k2_context *upd) +{ + static char last_cmd[1024]; + char input_buf[1024]; + + init_terminal(); + + debug_root *root = find_upd_root(upd); + if (!root) { + return; + } + /* + if (upd->pc == root->branch_t) { + bp_def ** f_bp = find_breakpoint(&root->breakpoints, root->branch_f, BP_TYPE_CPU); + if (!*f_bp) { + remove_breakpoint(context, root->branch_f); + } + root->branch_t = root->branch_f = 0; + } else if(upd->pc == root->branch_f) { + bp_def ** t_bp = find_breakpoint(&root->breakpoints, root->branch_t, BP_TYPE_CPU); + if (!*t_bp) { + remove_breakpoint(context, root->branch_t); + } + root->branch_t = root->branch_f = 0; + } + */ + + root->address = upd->pc; + int debugging = 1; + //Check if this is a user set breakpoint, or just a temporary one + bp_def ** this_bp = find_breakpoint(&root->breakpoints, upd->pc, BP_TYPE_CPU); + if (*this_bp) { + if ((*this_bp)->condition) { + debug_val condres; + if (eval_expr(root, (*this_bp)->condition, &condres)) { + if (!condres.v.u32) { + return; + } + } else { + fprintf(stderr, "Failed to eval condition for uPD78K/II breakpoint %u\n", (*this_bp)->index); + free_expr((*this_bp)->condition); + (*this_bp)->condition = NULL; + } + } + for (uint32_t i = 0; debugging && i < (*this_bp)->num_commands; i++) + { + debugging = run_command(root, (*this_bp)->commands + i); + } + if (debugging) { + printf("uPD78K/II Breakpoint %d hit\n", (*this_bp)->index); + } else { + fflush(stdout); + return; + } + } else { + //remove_breakpoint(context, address); + } + upd_address_ref ref; + uint16_t after = upd78k2_disasm(input_buf, &ref, upd->pc, upd_debug_fetch, upd, root->disasm); + root->after = after; + root->inst = &ref; + for (disp_def * cur = root->displays; cur; cur = cur->next) { + char format_str[8]; + make_format_str(format_str, cur->format); + for (int i = 0; i < cur->num_args; i++) + { + eval_expr(root, cur->args[i].parsed, &cur->args[i].value); + do_print(root, format_str, cur->args[i].raw, cur->args[i].value); + } + } + printf("%X: %s\n", root->address, input_buf); + debugger_repl(root); + return; +}
--- a/debug.h Wed Jul 16 18:01:21 2025 -0700 +++ b/debug.h Wed Jul 16 19:26:38 2025 -0700 @@ -10,6 +10,7 @@ #include "m68k_core.h" #include "z80_to_x86.h" #endif +#include "upd78k2.h" #include "disasm.h" typedef enum { @@ -215,12 +216,14 @@ debug_root *find_root(void *cpu); debug_root *find_m68k_root(m68k_context *context); debug_root *find_z80_root(z80_context *context); +debug_root *find_upd_root(upd78k2_context *upd); bp_def ** find_breakpoint(bp_def ** cur, uint32_t address, uint8_t type); bp_def ** find_breakpoint_idx(bp_def ** cur, uint32_t index); void add_display(disp_def ** head, uint32_t *index, char format_char, char * param); void remove_display(disp_def ** head, uint32_t index); void debugger(void * vcontext, uint32_t address); z80_context * zdebugger(z80_context * context, uint16_t address); +void upd_debugger(upd78k2_context *upd); void print_m68k_help(); void print_z80_help();
--- a/laseractive.c Wed Jul 16 18:01:21 2025 -0700 +++ b/laseractive.c Wed Jul 16 19:26:38 2025 -0700 @@ -5,6 +5,7 @@ #include "render_audio.h" #include "blastem.h" #include "util.h" +#include "debug.h" static void gamepad_down(system_header *system, uint8_t pad, uint8_t button) { @@ -72,6 +73,12 @@ uint32_t next = next_audio < next_video ? next_audio : next_video; while (!la->header.should_exit) { +#ifndef IS_LIB + if (la->header.enter_debugger) { + la->header.enter_debugger = 0; + upd_debugger(la->upd); + } +#endif upd78k2_execute(la->upd, next); while (la->upd->cycles >= next_audio) { for (int i = 0; i < 16; i++)