breakpoints, mem, run, console...

This commit is contained in:
2024-04-12 14:30:53 +02:00
parent b06d880614
commit eb4f2be4a4
6 changed files with 253 additions and 53 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
z80 z80
.vscode/*

View File

@@ -39,17 +39,30 @@ int main(int argc, char *argv[])
while (SDL_PollEvent(&e)) while (SDL_PollEvent(&e))
{ {
if (e.type == SDL_QUIT) { should_exit=true; break; } if (e.type == SDL_QUIT) { should_exit=true; break; }
if (e.type == SDL_KEYDOWN) { if (z80debug::debugging()) {
if (e.key.keysym.scancode==SDL_SCANCODE_ESCAPE) { if (e.type == SDL_KEYDOWN) {
should_exit=true; break; if (e.key.keysym.scancode==SDL_SCANCODE_ESCAPE) {
} else if (e.key.keysym.scancode==SDL_SCANCODE_RETURN) { should_exit=true; break;
//uint16_t PC = z80::getPC(); } else if (e.key.keysym.scancode==SDL_SCANCODE_F10) {
//z80dis::getAsm(&memory[PC]); t += z80::step();
t += z80::step(); z80debug::refresh();
z80debug::refresh(); } else if (e.key.keysym.scancode==SDL_SCANCODE_RETURN) {
z80debug::executeConsole();
} else if (e.key.keysym.scancode==SDL_SCANCODE_BACKSPACE) {
z80debug::DeleteCharConsole();
}
}
if (e.type == SDL_TEXTINPUT) {
z80debug::sendToConsole(e.text.text);
} }
} }
} }
if (!z80debug::debugging()) {
if (z80debug::isbreak(z80::getPC()))
z80debug::stop();
else
t += z80::step();
}
} }
return 0; return 0;

View File

@@ -51,7 +51,12 @@ namespace z80debug
SDL_Renderer *ren = nullptr; SDL_Renderer *ren = nullptr;
SDL_Texture *tex = nullptr; SDL_Texture *tex = nullptr;
bool is_debugging=false;
uint16_t mem_viewer_pos = 0; uint16_t mem_viewer_pos = 0;
char console[256];
char console_error[256];
uint8_t breakpoints[65536];
char temp[256]; char temp[256];
const char *tohex(int value, int numdigits) const char *tohex(int value, int numdigits)
@@ -61,17 +66,26 @@ namespace z80debug
return temp; return temp;
} }
void processCommand();
void show() void show()
{ {
is_debugging = true;
if (win) return; if (win) return;
win = SDL_CreateWindow("Z80 Debugger", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 71*CHR_W, 28*CHR_H, SDL_WINDOW_SHOWN); win = SDL_CreateWindow("Z80 Debugger", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 71*CHR_W, 34*CHR_H, SDL_WINDOW_SHOWN);
ren = SDL_CreateRenderer(win, -1, 0); ren = SDL_CreateRenderer(win, -1, 0);
tex = SDL_CreateTextureFromSurface(ren, SDL_LoadBMP("font.bmp")); tex = SDL_CreateTextureFromSurface(ren, SDL_LoadBMP("font.bmp"));
SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
for (int i=0; i<65536; ++i) breakpoints[i]=0;
z80debug::refresh(); z80debug::refresh();
} }
void stop() { is_debugging = true; refresh(); }
void cont() { is_debugging = false; }
const bool debugging() { return is_debugging; }
void box(int x, int y, int w, int h, uint8_t color) void box(int x, int y, int w, int h, uint8_t color)
{ {
SDL_Rect rect {((offset_x+x)*CHR_W)+3, ((offset_y+y)*CHR_H)+6, w*CHR_W-6, h*CHR_H-13}; SDL_Rect rect {((offset_x+x)*CHR_W)+3, ((offset_y+y)*CHR_H)+6, w*CHR_W-6, h*CHR_H-13};
@@ -105,11 +119,11 @@ namespace z80debug
uint16_t find_previous_opcode(uint16_t pc) uint16_t find_previous_opcode(uint16_t pc)
{ {
pc-=4; pc-=4;
if (z80dis::getOpcodeSize(&z80::getMem()[pc]) != 4) { if (z80dis::getOpcodeSize(pc) != 4) {
pc++; pc++;
if (z80dis::getOpcodeSize(&z80::getMem()[pc]) != 3) { if (z80dis::getOpcodeSize(pc) != 3) {
pc++; pc++;
if (z80dis::getOpcodeSize(&z80::getMem()[pc]) != 2) { if (z80dis::getOpcodeSize(pc) != 2) {
pc++; pc++;
} }
} }
@@ -140,24 +154,27 @@ namespace z80debug
printrect(0,8, 44,1, COLOR_BLUE); printrect(0,8, 44,1, COLOR_BLUE);
uint16_t pc = z80::getPC(); uint16_t pc = z80::getPC();
uint8_t *memory = z80::getMem(); uint8_t *memory = z80::getMem();
if (breakpoints[pc]&1) printtxt(0,8,"*", COLOR_YELLOW);
printtxt(1,8,tohex(pc,4), COLOR_YELLOW); printtxt(1,8,tohex(pc,4), COLOR_YELLOW);
printtxt(7,8, z80dis::getOpcode(&memory[pc]), COLOR_YELLOW); printtxt(7,8, z80dis::getOpcode(pc), COLOR_YELLOW);
printtxt(19,8, z80dis::getAsm(&memory[pc]), COLOR_YELLOW); printtxt(19,8, z80dis::getAsm(pc), COLOR_YELLOW);
uint16_t pos = pc; uint16_t pos = pc;
for (int i=9;i<18;++i) { for (int i=9;i<18;++i) {
pos += z80dis::getOpcodeSize(&memory[pos]); pos += z80dis::getOpcodeSize(pos);
if (breakpoints[pos]&1) printtxt(0,i,"*", COLOR_RED);
printtxt(1,i,tohex(pos,4), COLOR_CYAN); printtxt(1,i,tohex(pos,4), COLOR_CYAN);
printtxt(7,i, z80dis::getOpcode(&memory[pos]), COLOR_GRAY); printtxt(7,i, z80dis::getOpcode(pos), COLOR_GRAY);
printtxt(19,i, z80dis::getAsm(&memory[pos]), COLOR_WHITE); printtxt(19,i, z80dis::getAsm(pos), COLOR_WHITE);
} }
pos = pc; pos = pc;
for (int i=7;i>=0;--i) { for (int i=7;i>=0;--i) {
pos = find_previous_opcode(pos); pos = find_previous_opcode(pos);
if (breakpoints[pos]&1) printtxt(0,i,"*", COLOR_RED);
printtxt(1,i,tohex(pos,4), COLOR_CYAN); printtxt(1,i,tohex(pos,4), COLOR_CYAN);
printtxt(7,i, z80dis::getOpcode(&memory[pos]), COLOR_GRAY); printtxt(7,i, z80dis::getOpcode(pos), COLOR_GRAY);
printtxt(19,i, z80dis::getAsm(&memory[pos]), COLOR_WHITE); printtxt(19,i, z80dis::getAsm(pos), COLOR_WHITE);
} }
//for (int i=0;i<20;++i) printtxt(1,i,tohex(pc,4), COLOR_CYAN); //for (int i=0;i<20;++i) printtxt(1,i,tohex(pc,4), COLOR_CYAN);
@@ -213,9 +230,18 @@ namespace z80debug
printrect(59,8, 9,1, COLOR_DARK); printrect(59,8, 9,1, COLOR_DARK);
printtxt(60,8, "BREAKS:", COLOR_WHITE); printtxt(60,8, "BREAKS:", COLOR_WHITE);
offset_x=58;offset_y=9; offset_x=58;offset_y=9;
printtxt(0,0, "#1", COLOR_CYAN);
printtxt(3,0, "FFFF", COLOR_WHITE); int line=0;
printtxt(8,0, "read", COLOR_GRAY); for (int i=0; i<65536; ++i) {
if (breakpoints[i]) {
printtxt(2,line, tohex(i,4), COLOR_WHITE);
printtxt(7,line, breakpoints[i]&1?"x":"-", COLOR_GRAY);
printtxt(8,line, breakpoints[i]&2?"r":"-", COLOR_GRAY);
printtxt(9,line, breakpoints[i]&4?"w":"-", COLOR_GRAY);
line++;
if (line>9) break;
}
}
offset_x=offset_y=0; offset_x=offset_y=0;
box(0,20,71,8,COLOR_WHITE); box(0,20,71,8,COLOR_WHITE);
@@ -229,12 +255,125 @@ namespace z80debug
printtxt(0,i, tohex(mem_viewer_cursor, 4), COLOR_CYAN); printtxt(0,i, tohex(mem_viewer_cursor, 4), COLOR_CYAN);
for (int j=0; j<16; ++j) { for (int j=0; j<16; ++j) {
printtxt(5+j*3, i, tohex(memory[mem_viewer_cursor++],2), COLOR_WHITE); printtxt(5+j*3, i, tohex(memory[mem_viewer_cursor++],2), COLOR_WHITE);
printchar(53+j, i, memory[mem_viewer_cursor++], COLOR_GRAY); printchar(53+j, i, memory[mem_viewer_cursor], COLOR_GRAY);
} }
//printtxt(5,0, "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", COLOR_WHITE); //printtxt(5,0, "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", COLOR_WHITE);
//printtxt(53,0, "0123456789AB\tDEF", COLOR_GRAY); //printtxt(53,0, "0123456789AB\tDEF", COLOR_GRAY);
} }
offset_x=offset_y=0;
box(0,28,71,6,COLOR_WHITE);
printrect(2,28, 10,1, COLOR_DARK);
printtxt(3,28, "CONSOLE:", COLOR_WHITE);
offset_x=1; offset_y=29;
printtxt(0,0, ">", COLOR_WHITE);
printtxt(1,0, console, COLOR_WHITE);
printtxt(strlen(console)+1,0, "\x7F", COLOR_WHITE);
printtxt(1,1, console_error, COLOR_RED);
SDL_RenderPresent(ren); SDL_RenderPresent(ren);
} }
void sendToConsole(const char* text)
{
if (strlen(console)+strlen(text)<256) strcat(console, text);
refresh();
}
void DeleteCharConsole()
{
const int len = strlen(console);
console[len-1] = 0;
refresh();
}
void executeConsole()
{
processCommand();
console[0]=0;
refresh();
}
const char integer_digits[] = "0123456789";
const char hex_digits[] = "0123456789ABCDEF";
const int getnum(const char *str)
{
int i=0;
int return_value = 0;
if (str[0]=='$') {
i++;
while(str[i]!=0) {
int num = str[i]-48;
if (num<0) return -1;
if (num>9) {
num-=7;
if (num>15) {
num-=32;
if (num<10 || num>15) return -1;
}
}
return_value = (return_value<<4)+num;
i++;
}
} else {
while(str[i]!=0) {
int num = str[i]-48;
if (num<0 || num>9) return -1;
return_value = (return_value*10)+num;
i++;
}
}
return return_value;
}
#define getcmd() {while (*console_ptr==32) console_ptr++;while (console_ptr[i]!=0 && console_ptr[i]!=32) { cmd[i]=console_ptr[i]; i++; } cmd[i]=0; console_ptr = &console_ptr[i]; i=0;}
void processCommand()
{
console_error[0]=0;
char cmd[256];
int i=0;
char *console_ptr = console;
getcmd();
if (strcmp(cmd, "s")==0 || strcmp(cmd, "step")==0) {
z80::step();
} else if (strcmp(cmd, "r")==0 || strcmp(cmd, "run")==0 || strcmp(cmd, "c")==0 || strcmp(cmd, "cont")==0) {
z80::step();
z80debug::cont();
} else if (strcmp(cmd, "b")==0 || strcmp(cmd, "break")==0) {
getcmd();
int address = getnum(cmd);
if (address<0 || address>65536) { strcpy(console_error, "Illegal break address"); return; }
getcmd();
uint8_t break_type = 0;
if (cmd[0]!=0) {
if (strcmp(cmd, "x")==0 || strcmp(cmd, "exec")==0) {
break_type = 1;
} else if (strcmp(cmd, "r")==0 || strcmp(cmd, "read")==0) {
break_type = 2;
} else if (strcmp(cmd, "w")==0 || strcmp(cmd, "write")==0) {
break_type = 4;
} else {
strcpy(console_error, "Illegal break type");
return;
}
breakpoints[address] |= break_type;
}
} else if (strcmp(cmd, "m")==0 || strcmp(cmd, "mem")==0) {
getcmd();
int address = getnum(cmd);
if (address<0 || address>65536) { strcpy(console_error, "Illegal memory address"); return; }
mem_viewer_pos = address;
}
}
const bool isbreak(const uint16_t address)
{
return (breakpoints[address]&1);
}
} }

View File

@@ -1,7 +1,18 @@
#pragma once #pragma once
#include <stdint.h>
namespace z80debug namespace z80debug
{ {
void show(); void show();
void stop();
void cont();
const bool debugging();
void refresh(); void refresh();
void sendToConsole(const char* text);
void DeleteCharConsole();
void executeConsole();
const bool isbreak(const uint16_t address);
} }

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
namespace z80dis namespace z80dis
{ {
const char *getAsm(const uint8_t *memory); const char *getAsm(const uint16_t pos);
const char *getOpcode(const uint8_t *memory); const char *getOpcode(const uint16_t pos);
const int getOpcodeSize(const uint8_t *memory); const int getOpcodeSize(const uint16_t pos);
} }