- [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.
This commit is contained in:
2024-12-14 20:46:46 +01:00
parent 14d047cbb9
commit 0a758bbb33
7 changed files with 124 additions and 8 deletions

View File

@@ -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);
}

View File

@@ -1 +1,4 @@
0x5e38 STACK
0xc661 CLEAR_SCR
0xed5e MAINLOOP
0xfed5 COUNT500

31
z80.cpp
View File

@@ -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;
}
}

5
z80.h
View File

@@ -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();
}

View File

@@ -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.mouseX<midx*CHR_W && e->wheel.mouseY>=mem_y*CHR_H && e->wheel.mouseY<con_y*CHR_H) {
if (e->wheel.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

View File

@@ -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();

View File

@@ -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;
if (opcode_size>4) {
opcode_size=4;
sprintf(buffer, base, (int8_t)*(memory+3));
//} else {
// sprintf(buffer, base, (int8_t)*(memory+1));
//}
} else {
sprintf(buffer, base, (int8_t)*(memory+2));
}
}
return buffer;