diff --git a/src/core/cpu.c b/src/core/cpu.c index 651db69..16da025 100644 --- a/src/core/cpu.c +++ b/src/core/cpu.c @@ -16,6 +16,7 @@ #ifdef DEBUG #include "debug/record.h" +#include "debug/event.h" #endif cpu_t cpu; @@ -55,6 +56,11 @@ u8 cpu_step() { #ifdef DEBUG record_cpu_cycle(); + + event_t event; + event.type = EVENT_PROGRAM_COUNTER; + event.address.pc = PC; + debug_event(event); #endif cpu.op = mem_read_byte(PC++); diff --git a/src/core/joy.c b/src/core/joy.c index d038623..4d00992 100644 --- a/src/core/joy.c +++ b/src/core/joy.c @@ -7,8 +7,7 @@ #include "debug/event.h" #endif // DEBUG -#define SELECT_DIRECTION_BIT 0x10 -#define SELECT_ACTION_BIT 0x20 + joy_t joy; diff --git a/src/core/joy.h b/src/core/joy.h index f8f5523..58df6ba 100644 --- a/src/core/joy.h +++ b/src/core/joy.h @@ -15,6 +15,9 @@ #define JOY_STATE_PRESSED 0x00 #define JOY_STATE_RELEASED 0x01 +#define SELECT_DIRECTION_BIT 0x10 +#define SELECT_ACTION_BIT 0x20 + typedef struct { u8 state; u8 col; diff --git a/src/debug/break.c b/src/debug/break.c index 5b15bc8..08d6b57 100644 --- a/src/debug/break.c +++ b/src/debug/break.c @@ -38,9 +38,22 @@ void break_disable(int id) { breakpoints[id].enabled = 0; } +void break_clear() { + int i; + for (i = 0; i < BREAKPOINT_BUFFER_SIZE; i++) { + break_disable(i); + } + breakpoint_cursor = 0; +} + void break_handle_event(event_t event) { int b; for (b = 0; b < breakpoint_cursor; b++) { + if (breakpoints[b].breakpoint.type == BREAKPOINT_ADDRESS) { + if (event.type == EVENT_PROGRAM_COUNTER && event.address.pc == breakpoints[b].breakpoint.address.pc ) { + now = 1; + } + } if (breakpoints[b].breakpoint.type == BREAKPOINT_EVENT) { if (event.type == EVENT_JOY_NOTICED) { now = 1; diff --git a/src/debug/debug.c b/src/debug/debug.c index 2933334..4b1b257 100644 --- a/src/debug/debug.c +++ b/src/debug/debug.c @@ -72,6 +72,18 @@ static void cmd_break(char* tail) { int i = atoi(subsubcmd); break_disable(i); } + else if (!strcmp(subcmd, "pc")) { + char* bpc = word(&tail); + assert(*bpc != '\0'); + bp.type = BREAKPOINT_ADDRESS; + bp.address.pc = strtol(bpc, NULL, 16); + valid_bp = 1; + } + else if (!strcmp(subcmd, "clear")) { + printf("Cleared all breakpoints\n", subcmd); + break_clear(); + return; + } else { printf("Unknown break command '%s'\n", subcmd); valid_bp = 0; @@ -122,6 +134,11 @@ static void cmd_watch(char* tail) { else if (!strcmp(subcmd, "mem-w")) { watchpoint.type = WATCHPOINT_MEM_W; } + else if (!strcmp(subcmd, "clear")) { + printf("Cleared all watches\n", subcmd); + watch_clear(); + return; + } else { printf("Unknown watch subcommand '%s'\n", subcmd); return; @@ -149,6 +166,47 @@ static void cmd_watch(char* tail) { watch_enable(watchpoint); } +static void cmd_cpureg() { + printf("AF [ A = %.2X ; F = %.2X ]\n", A, F); + printf("BC [ B = %.2X ; C = %.2X ]\n", B, C); + printf("DE [ D = %.2X ; E = %.2X ]\n", D, E); + printf("HL [ H = %.2X ; L = %.2X ]\n", H, L); + printf("SP = %.4X\n", SP); + printf("PC = %.4X\n", PC); +} + +static void cmd_memdump(char* tail) { + char* startaddr = word(&tail); + assert(*startaddr != '\0'); + char* endaddr = word(&tail); + if (*endaddr == '\0') { + endaddr = startaddr; + } + + u16 curaddr = strtol(startaddr, NULL, 16); + u16 finish = strtol(endaddr, NULL, 16); + if (finish < curaddr) { + finish = curaddr + 0x10; + } + u8 needaddrmarker = 1; + int newlineat = 16; + while (curaddr <= finish) { + if (needaddrmarker != 0) { + printf("%.4X | ", curaddr); + newlineat = 16; + needaddrmarker = 0; + } + printf("%.2X ", debug_read_byte(curaddr)); + newlineat--; + if (newlineat == 0) { + needaddrmarker = 1; + printf("\n"); + } + curaddr++; + } + printf("\n"); +} + void debug_step() { int continue_emulation = !break_now(); @@ -205,6 +263,12 @@ void debug_step() { else if (!strcmp("w", cmd)) { cmd_watch(trim(tail)); } + else if (!strcmp("c", cmd)) { + cmd_cpureg(); + } + else if (!strcmp("m", cmd)) { + cmd_memdump(trim(tail)); + } else { printf("Unknown cmd '%s'\n", cmd); } diff --git a/src/debug/event.c b/src/debug/event.c index e19cd06..4f991e4 100644 --- a/src/debug/event.c +++ b/src/debug/event.c @@ -4,6 +4,7 @@ #include #include "core/joy.h" +#include "core/cpu.h" #include "break.h" #include "debug.h" @@ -40,7 +41,12 @@ static void joy_input_event() { } static void joy_read_event() { - printf("JOY READ\n"); + printf("JOY READ: Pad %.2X Buttons %.2X\n", (joy.state >> 4), (joy.state & 0x0F)); + break_handle_event(current_event); +} + +static void pc_address_event() { + // printf("PC: %.4X\n", PC); break_handle_event(current_event); } @@ -54,6 +60,7 @@ void debug_event(event_t event) { switch(event.type) { case EVENT_JOY_INPUT: joy_input_event(); break; case EVENT_JOY_NOTICED: joy_read_event(); break; + case EVENT_PROGRAM_COUNTER: pc_address_event(); break; default: assert(0); } diff --git a/src/debug/event.h b/src/debug/event.h index 9bb2216..97265d0 100644 --- a/src/debug/event.h +++ b/src/debug/event.h @@ -5,7 +5,8 @@ typedef enum { EVENT_JOY_INPUT, - EVENT_JOY_NOTICED + EVENT_JOY_NOTICED, + EVENT_PROGRAM_COUNTER } EVENT_TYPE; typedef struct { @@ -17,6 +18,10 @@ typedef struct { u8 button; u8 state; } joy; + // EVENT_PROGRAM_COUNTER + struct { + u16 pc; + } address; }; } event_t; diff --git a/src/debug/watch.c b/src/debug/watch.c index 66f41c7..d455836 100644 --- a/src/debug/watch.c +++ b/src/debug/watch.c @@ -36,6 +36,14 @@ void watch_disable(int id) { watchpoint_enabled[id] = 0; } +void watch_clear() { + int i; + for (i = 0; i < WATCHPOINT_BUFFER_SIZE; i++) { + watch_disable(i); + } + watchpoint_cursor = 0; +} + void watch_event_mem_w(u16 addr, u8 a, u8 b) { if (in_debug_scope()) { return;