From 44ffbe36a8e7eaab7d7851bb79f229c4383c6545 Mon Sep 17 00:00:00 2001 From: Ian C Date: Tue, 13 Jan 2004 02:21:06 +0000 Subject: Added breakpoints to memory menu and added extra GUI items. Plus general fixes. --- src/gfx.c | 15 ++- src/gfx.h | 13 ++- src/gui.c | 223 +++++++++++++++++++++++++++++++++++-------- src/gui.h | 20 +++- src/main.c | 13 ++- src/memmenu.c | 300 ++++++++++++++++++++++++++++++++++++++++++++-------------- src/memmenu.h | 11 ++- src/spec.c | 56 +++++++---- src/spec.h | 4 +- src/util.c | 17 +++- src/util.h | 5 + 11 files changed, 527 insertions(+), 150 deletions(-) diff --git a/src/gfx.c b/src/gfx.c index a2d1623..7906e84 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -50,9 +50,6 @@ static const char ident_fh[]=ESPEC_FONT_H; #define FALSE 0 #endif -#define SCR_W 320 -#define SCR_H 300 - #define LOCK do \ { \ if (SDL_MUSTLOCK(surface)) \ @@ -179,8 +176,8 @@ void GFXInit(void) Exit("Failed to init SDL: %s\n",SDL_GetError()); } - if (!(surface=SDL_SetVideoMode(SCR_W*scale, - SCR_H*scale, + if (!(surface=SDL_SetVideoMode(GFX_WIDTH*scale, + GFX_HEIGHT*scale, 0, IConfig(CONF_FULLSCREEN) ? SDL_FULLSCREEN : 0))) @@ -362,11 +359,11 @@ void GFXPrint(int x, int y, Uint32 col, const char *format, ...) { for(sy=0;sy<8;sy++) { - if (y+sylen) + { + p[len]=0; + p[len-1]='.'; + p[len-2]='.'; + } +} - if (!p) - Exit("malloc failed for %lu bytes\n",(unsigned long)size); - return p; +static void Centre(const char *p, int y, Uint32 col) +{ + GFXPrint((GFX_WIDTH-strlen(p)*8)/2,y,col,"%s",p); } -static void Centre(const char *p, int y, int r, int g, int b) +static void Box(const char *title, int x, int y, int width, int height) { - GFXPrint((SCR_W-strlen(p)*8)/2,y,GFXRGB(r,g,b),"%s",p); + GFXRect(x+1,y+1, + width-2,height-2, + BLACK,TRUE); + + GFXRect(x+1,y+1, + width-2,11, + LOGREY,TRUE); + + GFXRect(x,y, + width,height, + GREY,FALSE); + + Centre(title,y+2,GREEN); + GFXHLine(x,x+width-1,y+11,GREY); } /* ---------------------------------------- EXPORTED INTERFACES */ -void GUIMessage(const char *title, const char *format,...) +int GUIMessage(GUIBoxType type, const char *title, const char *format,...) { char buff[1025]; va_list va; @@ -89,6 +111,9 @@ void GUIMessage(const char *title, const char *format,...) int width; int height; int x,y; + int ret; + + ret=FALSE; va_start(va,format); vsprintf(buff,format,va); @@ -107,69 +132,96 @@ void GUIMessage(const char *title, const char *format,...) line=Malloc(sizeof *line * no); + width=16; + line[0]=strtok(buff,"\n"); - width=strlen(line[0]); + Trim(line[0],38); + + if (strlen(line[0])>width) + width=strlen(line[0]); for(f=1;fwidth) width=strlen(line[f]); } - width=(width*8)+16; - height=(no+3)*10; - - if (width>(SCR_W-10)) - width=SCR_W-10; + width=(width*8)+18; + height=(no+3)*12; - if (height>(SCR_H-10)) - height=SCR_H-10; + if (width>(GFX_WIDTH-10)) + width=GFX_WIDTH-10; - y=(SCR_H-height)/2; - x=(SCR_W-width)/2; + if (height>(GFX_HEIGHT-10)) + height=GFX_HEIGHT-10; - GFXRect(x-1,y-1, - width+2,height+2, - GFXRGB(255,255,255),FALSE); - - GFXRect(x,y, - width,height, - GFXRGB(0,0,0),TRUE); + y=(GFX_HEIGHT-height)/2; + x=(GFX_WIDTH-width)/2; - Centre(title,y+2,255,255,255); - GFXHLine(x+2,x+width-4,y+10,GFXRGB(255,255,255)); + Box(title,x,y,width,height); for(f=0;fkey.keysym.sym==SDLK_y) + { + ret=TRUE; + break; + } + else if (e->key.keysym.sym==SDLK_n) + { + ret=FALSE; + break; + } + } + } + else + GFXWaitKey(); + free(line); + + return ret; } const char *GUIInputString(const char *prompt, const char *orig) { - static const int y_pos=SCR_H-8; + static const int y_pos=GFX_HEIGHT-8; static char buff[41]; size_t len; int done=FALSE; + unsigned char c; SDL_Event *e; buff[0]=0; strncat(buff,orig,40); len=strlen(buff); + SDL_EnableUNICODE(1); + while(!done) { - GFXRect(0,y_pos,SCR_W,8,GFXRGB(0,0,0),TRUE); - GFXPrint(0,y_pos,GFXRGB(255,255,255),"%s %s%c",prompt,buff,FONT_CURSOR); + GFXRect(0,y_pos,GFX_WIDTH,8,BLACK,TRUE); + GFXPrint(0,y_pos,WHITE,"%s %s%c",prompt,buff,FONT_CURSOR); GFXEndFrame(FALSE); e=GFXWaitKey(); @@ -194,19 +246,112 @@ const char *GUIInputString(const char *prompt, const char *orig) break; default: - if (len<40 && isprint(e->key.keysym.sym)) + c=(unsigned char)e->key.keysym.unicode; + + if (len<40 && isprint(c)) { - buff[len++]=(char)e->key.keysym.sym; + buff[len++]=c; buff[len]=0; } break; } } + SDL_EnableUNICODE(0); + return buff; } +int GUIListSelect(const char *title, int no, char * const list[]) +{ + static const int max=GFX_HEIGHT/8-8; + SDL_Event *e; + int top; + int cur; + int done; + int f; + + if (no==0) + return -1; + + top=0; + cur=0; + + done=FALSE; + + while(!done) + { + Box(title,7,7,GFX_WIDTH-14,GFX_HEIGHT-14); + + Centre("Cursors and RETURN to select",GFX_HEIGHT-40,WHITE); + Centre("ESCAPE to cancel",GFX_HEIGHT-32,WHITE); + + for(f=0;fkey.keysym.sym) + { + case SDLK_RETURN: + done=TRUE; + break; + + case SDLK_ESCAPE: + cur=-1; + done=TRUE; + break; + + case SDLK_UP: + if (cur>0) + { + cur--; + + if (curtop+max-2) + top=cur-max+2; + } + break; + + default: + break; + } + } + + return cur; +} + + int GUIFileSelect(const char *prompt, int load, const char *start_dir, char path[]) { diff --git a/src/gui.h b/src/gui.h index 953aac9..e1ad43a 100644 --- a/src/gui.h +++ b/src/gui.h @@ -31,10 +31,20 @@ /* ---------------------------------------- INTERFACES */ +/* Message types +*/ +typedef enum {eMessageBox, eYesNoBox} GUIBoxType; + /* Display a simple message box. A message of longer than 1024 bytes causes - undefined behaviour. Newlines cause a line break. + undefined behaviour. Newlines cause a line break. If a line is over 38 + characters then it will be truncated. + + If type is eYesNoBox then TRUE/FALSE is returned depending on whether + yes/no was selected. */ -void GUIMessage(const char *title, const char *format,...); +int GUIMessage(GUIBoxType type, + const char *title, + const char *format,...); /* Enter a string, max 40 characters @@ -42,6 +52,12 @@ void GUIMessage(const char *title, const char *format,...); const char *GUIInputString(const char *prompt, const char *orig); +/* Selects an entry from a list. Returns the index selected, or + -1 if cancelled. +*/ +int GUIListSelect(const char *title, int no, char * const list[]); + + /* Select a file from the given directory. If load is TRUE then a new name cannot be entered. diff --git a/src/main.c b/src/main.c index e25ce75..75352f5 100644 --- a/src/main.c +++ b/src/main.c @@ -80,6 +80,8 @@ int main(int argc, char *argv[]) z80=Z80Init(SPECWriteMem, SPECReadMem, + SPECWriteWord, + SPECReadWord, SPECWritePort, SPECReadPort, SPECReadForDisassem, @@ -103,6 +105,8 @@ int main(int argc, char *argv[]) while(!quit) { + const char *brk; + Z80State s1,s2; Z80GetState(z80,&s1); @@ -121,6 +125,12 @@ int main(int argc, char *argv[]) GFXEndFrame(FALSE); } + if ((brk=Break())) + { + GUIMessage(eMessageBox,"BREAKPOINT","%s",brk); + MemoryMenu(z80); + } + while((e=GFXGetKey())) { switch (e->key.keysym.sym) @@ -132,7 +142,8 @@ int main(int argc, char *argv[]) case SDLK_F1: if (e->key.state==SDL_PRESSED) - GUIMessage("HELP", + GUIMessage(eMessageBox, + "HELP", "ESC - Quit \n" "F1 - Help \n" "F8 - Select tape file for loading\n" diff --git a/src/memmenu.c b/src/memmenu.c index 50b9acb..60e2c03 100644 --- a/src/memmenu.c +++ b/src/memmenu.c @@ -34,6 +34,7 @@ static const char ident[]="$Id$"; #include "spec.h" #include "gfx.h" #include "gui.h" +#include "util.h" #include @@ -56,13 +57,43 @@ static const char ident_h[]=ESPEC_MEMMENU_H; #define TRACE "trace" +/* ---------------------------------------- TYPES +*/ +typedef struct +{ + int no; + char **expr; +} Breakpoint; + + /* ---------------------------------------- STATIC DATA */ -FILE *trace=NULL; +static FILE *trace=NULL; +static Breakpoint bpoint={NULL,0}; +static const char *brk=NULL; + + +/* ---------------------------------------- PROTOS +*/ +static int Instruction(Z80 *z80, Z80Val data); /* ---------------------------------------- PRIVATE FUNCTIONS */ +static void SetCallback(Z80 *z80) +{ + if (trace || bpoint.no) + Z80LodgeCallback(z80,eZ80_Instruction,Instruction); +} + + +static void ClearCallback(Z80 *z80) +{ + if (!trace && !bpoint.no) + Z80RemoveCallback(z80,eZ80_Instruction,Instruction); +} + + static void Centre(const char *p, int y, Uint32 col) { GFXPrint((320-strlen(p)*8)/2,y,col,"%s",p); @@ -73,11 +104,15 @@ static void DisplayMenu(void) { static const char *menu[]= { - "1. Disassemble/Hex dump", - "2. Disassemble to file ", - "3. Start/Stop trace log", - "4. Playback trace log ", - "5. Return ", + "1. Disassemble/Hex dump ", + "2. Disassemble to file ", + "3. Start/Stop trace log ", + "4. Playback trace log ", + "5. Add a new breakpoint ", + "6. Clear a breakpoint ", + "7. Display breakpoints ", + "8. Clear all breakpoints", + "9. Return ", NULL }; @@ -138,66 +173,26 @@ void DisplayZ80State(Z80State *s, int y, Uint32 col) } -static int StrEq(const char *a, const char *b) -{ - while(*a && *b && tolower(*a)==tolower(*b)) - { - a++; - b++; - } - - if (*a || *b) - return FALSE; - else - return TRUE; -} - - -static Z80Word Address(Z80 *z80, const char *p) -{ - Z80State s; - - Z80GetState(z80,&s); - - if (StrEq(p,"AF")) - return s.AF; - else if (StrEq(p,"BC")) - return s.BC; - else if (StrEq(p,"DE")) - return s.DE; - else if (StrEq(p,"HL")) - return s.HL; - else if (StrEq(p,"IX")) - return s.IX; - else if (StrEq(p,"IY")) - return s.IY; - else if (StrEq(p,"SP")) - return s.SP; - else if (StrEq(p,"PC")) - return s.PC; - - return (Z80Word)strtoul(p,NULL,0); -} - - static int EnterAddress(const char *prompt, Z80 *z80, Z80Word *w) { - unsigned long ul; const char *p; + char *error; + long l; p=GUIInputString(prompt ? prompt : "Address?",""); if (*p) { - ul=Address(z80,p); - - if (ul>0xffff) + if (!Z80Expression(z80,p,&l,&error)) { - GUIMessage("ERROR","Bad address"); + GUIMessage(eMessageBox, + "ERROR","%s",error ? error:"Invalid expression"); + + free(error); } else { - *w=(Z80Word)ul; + *w=(Z80Word)l; return TRUE; } } @@ -237,7 +232,7 @@ static void DoDisassem(Z80 *z80, const Z80State *s) curr=pc; - for(f=0;f<21;f++) + for(f=0;f=0 && aline=0 && y=0 && y=ROMLEN) + mem[addr]=val&0xff; + + addr++; + + if (addr>=ROMLEN) + mem[addr]=val>>8; +} + + Z80Byte SPECReadPort(Z80 *z80, Z80Word port) { Z80Byte lo=port&0xff; diff --git a/src/spec.h b/src/spec.h index bb62b91..f771480 100644 --- a/src/spec.h +++ b/src/spec.h @@ -21,8 +21,6 @@ ------------------------------------------------------------------------- Provides the emulation for the SPEC - - Requires access to the HOOK and FETCH Z80 callbacks */ #ifndef ESPEC_SPECH @@ -48,6 +46,8 @@ void SPECKeyEvent(SDL_Event *e); */ Z80Byte SPECReadMem(Z80 *z80, Z80Word addr); void SPECWriteMem(Z80 *z80, Z80Word addr, Z80Byte val); +Z80Word SPECReadWord(Z80 *z80, Z80Word addr); +void SPECWriteWord(Z80 *z80, Z80Word addr, Z80Word val); Z80Byte SPECReadPort(Z80 *z80, Z80Word port); void SPECWritePort(Z80 *z80, Z80Word port, Z80Byte val); Z80Byte SPECReadForDisassem(Z80 *z80, Z80Word addr); diff --git a/src/util.c b/src/util.c index c3396eb..a8a037d 100644 --- a/src/util.c +++ b/src/util.c @@ -42,12 +42,23 @@ static const char ident_h[]=ESPEC_UTIL_H; */ void *Malloc(size_t size) { - void *p=malloc(size); + void *new=malloc(size); - if (!p) + if (!new) Exit("malloc failed for %lu bytes\n",(unsigned long)size); - return p; + return new; +} + + +void *Realloc(void *p, size_t size) +{ + void *new=realloc(p,size); + + if (!new) + Exit("realloc failed for %lu bytes\n",(unsigned long)size); + + return new; } diff --git a/src/util.h b/src/util.h index f391170..6930b8a 100644 --- a/src/util.h +++ b/src/util.h @@ -37,6 +37,11 @@ void *Malloc(size_t size); +/* Returns result from realloc(p,size), calling Exit() if it fails. +*/ +void *Realloc(void *p, size_t size); + + /* Copies a string. The result must be freed. */ char *StrCopy(const char *source); -- cgit v1.2.3