From 0a758bbb3362b793220723bd441bdff89cee14a8 Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Sat, 14 Dec 2024 20:46:46 +0100 Subject: [PATCH] - [NEW] F12 to StepOut() on debugger (break on RET, RETI or RETN) - [FIX] Fixed visualizacion of some IX and IY opcodes - [NEW] Scroll on memory viewer with mouse wheel - [NEW] While debugging, on each step the screen refreshes, so screen redraw can be seen while happening - [NEW] Search for sequences of bytes. Example: "search AB1140" to search for the sequece $AB $11 $40. "search next" to continue searching. --- main.cpp | 10 ++++++++ symbols.txt | 3 +++ z80.cpp | 31 ++++++++++++++++++++++++ z80.h | 5 +++- z80debug.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++- z80debug.h | 2 ++ z80dis.cpp | 13 +++++----- 7 files changed, 124 insertions(+), 8 deletions(-) diff --git a/main.cpp b/main.cpp index ead64dd..86414fa 100644 --- a/main.cpp +++ b/main.cpp @@ -160,6 +160,16 @@ int main(int argc, char *argv[]) zxscreen::redraw(); z80analyze::refresh(); } + } else if (e.key.keysym.scancode==SDL_SCANCODE_F12) { + if (z80debug::debugging()) { + z80debug::show(); + z80debug::history::gototop(); + const uint8_t dt = z80debug::stepout(); + z80debug::refresh(); + zxscreen::refresh(dt); + zxscreen::redraw(); + z80analyze::refresh(); + } } result = ui::window::sendEvent(e.key.windowID, &e); } diff --git a/symbols.txt b/symbols.txt index adff646..1513005 100644 --- a/symbols.txt +++ b/symbols.txt @@ -1 +1,4 @@ +0x5e38 STACK +0xc661 CLEAR_SCR +0xed5e MAINLOOP 0xfed5 COUNT500 diff --git a/z80.cpp b/z80.cpp index ae26118..93abff7 100644 --- a/z80.cpp +++ b/z80.cpp @@ -11,6 +11,7 @@ namespace z80 static uint32_t t = 0; static uint16_t current_opcode_address = 0; bool options[Z80_NUM_OPTIONS] = { true, false }; + int calls_stacked = 0; int (*in_ports[256])(int); void (*out_ports[256])(int, int); @@ -657,6 +658,11 @@ namespace z80 { PUSH(rPC); rPC = addr; + + if (options[Z80_OPTION_BREAK_ON_RET]) { + calls_stacked++; + printf("CALL: calls stacked: %i", calls_stacked); + } } } @@ -674,6 +680,20 @@ namespace z80 { POP(_rPC); if (cond != cNO) t++; + + if (options[Z80_OPTION_BREAK_ON_RET]) { + if (calls_stacked>0) { + calls_stacked--; + printf("RET: calls still stacked: %i\n", calls_stacked); + } else { + printf("RET: BREAK\n"); + options[Z80_OPTION_BREAK_ON_RET] = false; + z80debug::setcursor(rPC); + z80debug::history::store(); + z80debug::stop(); + } + } + } else { t++; } @@ -683,6 +703,13 @@ namespace z80 { POP(_rPC); iff1 = iff2; + + if (options[Z80_OPTION_BREAK_ON_RET]) { + options[Z80_OPTION_BREAK_ON_RET] = false; + z80debug::setcursor(rPC); + z80debug::history::store(); + z80debug::stop(); + } } void RETI() @@ -2842,4 +2869,8 @@ namespace z80 options[option] = !options[option]; } + void resetStackedCalls() + { + calls_stacked=0; + } } \ No newline at end of file diff --git a/z80.h b/z80.h index 807aa2b..0dbb029 100644 --- a/z80.h +++ b/z80.h @@ -14,7 +14,8 @@ namespace z80 #define Z80_OPTION_STOP_ON_INVALID 0 #define Z80_OPTION_BREAK_ON_INTERRUPT 1 - #define Z80_NUM_OPTIONS 2 + #define Z80_OPTION_BREAK_ON_RET 2 + #define Z80_NUM_OPTIONS 3 void reset(uint8_t* mem); void connect_port(int num, int (*in_ptr)(int), void (*out_ptr)(int,int)); @@ -51,4 +52,6 @@ namespace z80 const bool getOption(const int option); void setOption(const int option, const bool value); void toggleOption(const int option); + + void resetStackedCalls(); } \ No newline at end of file diff --git a/z80debug.cpp b/z80debug.cpp index fdfd891..f5e8478 100644 --- a/z80debug.cpp +++ b/z80debug.cpp @@ -69,6 +69,10 @@ namespace z80debug int num_breakpoint_lines=0; bool sync_mem_with_cursor = false; + uint8_t search_sequence[32]; + int search_sequence_len=0; + uint16_t search_pos=0; + char temp[256]; const char *tohex(int value, int numdigits) { @@ -105,6 +109,14 @@ namespace z80debug z80debug::cursorfwd(); z80debug::refresh(); } + } else if (e->wheel.mouseXwheel.mouseY>=mem_y*CHR_H && e->wheel.mouseYwheel.y>0) { + mem_viewer_pos+=0x10; + z80debug::refresh(); + } else if (e->wheel.y<0) { + mem_viewer_pos-=0x10; + z80debug::refresh(); + } } } if (e->type == SDL_KEYDOWN) { @@ -294,6 +306,7 @@ namespace z80debug //history::gototop(); zxscreen::setTitle(" (stopped)"); pause(); + z80::resetStackedCalls(); is_debugging = true; show(); /*refresh();*/ @@ -692,7 +705,10 @@ namespace z80debug getcmd(); if (strcmp(cmd, "s")==0 || strcmp(cmd, "step")==0) { - z80::step(); + uint8_t dt = z80::step(); + zx_tape::update(dt); + zx_ula::sound_update(dt); + zxscreen::refresh(dt); z80analyze::refresh(); } else if (strcmp(cmd, "c")==0 || strcmp(cmd, "cont")==0) { z80::step(); @@ -860,6 +876,13 @@ namespace z80debug getcmd(); int value = getnum(cmd); z80::setMemTag(value, MEMTAG_IGNORE); + } else if (strcmp(cmd, "search")==0) { + getcmd(); + if (strcmp(cmd, "next")==0) { + search(); + } else { + search(cmd); + } } } @@ -876,6 +899,14 @@ namespace z80debug return t; } + uint32_t stepout() + { + z80::setOption(Z80_OPTION_BREAK_ON_RET, true); + const uint32_t t = z80::step(); + cont(); + return t; + } + void setmemmodified(const uint16_t addr) { mem_modified[addr] = true; @@ -988,6 +1019,41 @@ namespace z80debug } } + uint8_t hexchartonum(char chr) + { + int num = chr-48; + if (num<0) return 0; + if (num>9) { + num-=7; + if (num>15) { + num-=32; + if (num<10 || num>15) return 0; + } + } + return uint8_t(num); + } + void search(const char *seq) + { + if (seq) { + search_pos = 0; + search_sequence_len=0; + while (*seq!=0) search_sequence[search_sequence_len++] = (hexchartonum(*(seq++))<<4) + hexchartonum(*(seq++)); + } + int num_found=0; + uint8_t *memory = z80::getMem(); + while (search_pos<65536) { + if (search_sequence[num_found] == memory[search_pos]) { + num_found++; search_pos++; + if (num_found==search_sequence_len) { + mem_viewer_pos=search_pos-search_sequence_len; + return; + } + } else { + num_found=0; search_pos++; + } + } + sendToConsole("Sequence not found."); + } namespace history diff --git a/z80debug.h b/z80debug.h index 15d1efe..d89d13b 100644 --- a/z80debug.h +++ b/z80debug.h @@ -24,6 +24,7 @@ namespace z80debug const bool isbreak(const uint16_t address, const uint8_t type=1); uint32_t next(); + uint32_t stepout(); void savestate(const char *filename); void loadstate(const char *filename); @@ -40,6 +41,7 @@ namespace z80debug const int getNumOpcodesUsed(); void printOpcodesUsed(); + void search(const char *seq=nullptr); namespace history { void store(); diff --git a/z80dis.cpp b/z80dis.cpp index 9541918..55a7e01 100644 --- a/z80dis.cpp +++ b/z80dis.cpp @@ -123,7 +123,7 @@ namespace z80dis if (strstr(buffer, "4x")) { opcode_size+=2; - const uint16_t word = *(uint16_t*)(memory+1); + const uint16_t word = *(uint16_t*)(memory+((*memory==0xFD) || (*memory==0xDD)?2:1)); if (symbols[word][0]!=0) { char *p = strstr(buffer, "$"); (*p)='%'; p++; @@ -173,11 +173,12 @@ namespace z80dis opcode_size+=1; strcpy(base, buffer); - if (opcode_size>4) opcode_size=4; - sprintf(buffer, base, (int8_t)*(memory+3)); - //} else { - // sprintf(buffer, base, (int8_t)*(memory+1)); - //} + if (opcode_size>4) { + opcode_size=4; + sprintf(buffer, base, (int8_t)*(memory+3)); + } else { + sprintf(buffer, base, (int8_t)*(memory+2)); + } } return buffer;