diff options
-rw-r--r-- | src/gfx.c | 15 | ||||
-rw-r--r-- | src/gfx.h | 13 | ||||
-rw-r--r-- | src/gui.c | 223 | ||||
-rw-r--r-- | src/gui.h | 20 | ||||
-rw-r--r-- | src/main.c | 13 | ||||
-rw-r--r-- | src/memmenu.c | 300 | ||||
-rw-r--r-- | src/memmenu.h | 11 | ||||
-rw-r--r-- | src/spec.c | 56 | ||||
-rw-r--r-- | src/spec.h | 4 | ||||
-rw-r--r-- | src/util.c | 17 | ||||
-rw-r--r-- | src/util.h | 5 |
11 files changed, 527 insertions, 150 deletions
@@ -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+sy<SCR_H && x<SCR_W) + if (y+sy<GFX_HEIGHT && x<GFX_WIDTH) { for(sx=0;sx<8;sx++) { - if (font[(int)*p][sx+sy*8] && x+sx<SCR_W) + if (font[(int)*p][sx+sy*8] && x+sx<GFX_WIDTH) putpixel(x+sx,y+sy,col); } } @@ -400,11 +397,11 @@ void GFXPrintPaper(int x, int y, Uint32 col, Uint32 paper, { for(sy=0;sy<8;sy++) { - if (y+sy<SCR_H && x<SCR_W) + if (y+sy<GFX_HEIGHT && x<GFX_WIDTH) { for(sx=0;sx<8;sx++) { - if (font[(int)*p][sx+sy*8] && x+sx<SCR_W) + if (font[(int)*p][sx+sy*8] && x+sx<GFX_WIDTH) putpixel(x+sx,y+sy,col); else putpixel(x+sx,y+sy,paper); @@ -41,6 +41,11 @@ #define FONT_CURSOR '\007' #define FONT_COPYRIGHT '\010' +/* The size of the display +*/ +#define GFX_WIDTH 320 +#define GFX_HEIGHT 300 + /* ---------------------------------------- INTERFACES */ @@ -50,6 +55,12 @@ void GFXInit(void); +/* Size of the screen +*/ +int GFXHeight(void); +int GFXWidth(void); + + /* Get the SDL_Surface for the screen */ SDL_Surface *GFXGetSurface(void); @@ -87,7 +98,7 @@ void GFXKeyRepeat(int repeat); SDL_Event *GFXGetKey(void); -/* Wait for a keypress (key up event) +/* Wait for a keypress. Note that key up events are returned. */ SDL_Event *GFXWaitKey(void); @@ -34,6 +34,7 @@ static const char ident[]="$Id$"; #include "gui.h" #include "gfx.h" #include "exit.h" +#include "util.h" static const char ident_h[]=ESPEC_GUI_H; @@ -48,10 +49,12 @@ static const char ident_h[]=ESPEC_GUI_H; #define FALSE 0 #endif -/* Must match gfx.c -*/ -#define SCR_W 320 -#define SCR_H 200 +#define WHITE GFXRGB(255,255,255) +#define BLACK GFXRGB(0,0,0) +#define RED GFXRGB(255,100,100) +#define GREY GFXRGB(160,160,160) +#define LOGREY GFXRGB(100,100,100) +#define GREEN GFXRGB(100,255,100) /* ---------------------------------------- STATICS */ @@ -59,26 +62,45 @@ static const char ident_h[]=ESPEC_GUI_H; /* ---------------------------------------- PRIVATE FUNCTIONS */ -static void *Malloc(size_t size) +static void Trim(char *p,size_t len) { - void *p=malloc(size); + if (strlen(p)>len) + { + 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;f<no;f++) { line[f]=strtok(NULL,"\n"); + Trim(line[f],38); if (strlen(line[f])>width) 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;f<no;f++) - Centre(line[f],y+5+10*(f+1),200,200,200); + Centre(line[f],y+5+10*(f+1),WHITE); - Centre("Press a key",y+height-10,255,0,0); + if (type==eMessageBox) + Centre("Press a key",y+height-12,RED); + else + Centre("Press Y/N",y+height-12,RED); GFXEndFrame(FALSE); - GFXWaitKey(); + if (type==eYesNoBox) + { + SDL_Event *e; + + while(TRUE) + { + e=GFXWaitKey(); + + if (e->key.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;f<max;f++) + { + if (f+top<no) + { + Uint32 pen,paper; + + if (f+top==cur) + { + pen=WHITE; + paper=RED; + } + else + { + pen=GREY; + paper=BLACK; + } + + GFXPrintPaper(16,20+f*8,pen,paper,"%-36.36s",list[f+top]); + } + } + + GFXEndFrame(FALSE); + + e=GFXWaitKey(); + + switch(e->key.keysym.sym) + { + case SDLK_RETURN: + done=TRUE; + break; + + case SDLK_ESCAPE: + cur=-1; + done=TRUE; + break; + + case SDLK_UP: + if (cur>0) + { + cur--; + + if (cur<top) + top=cur; + } + break; + + case SDLK_DOWN: + if (cur<no-1) + { + cur++; + + if (cur>top+max-2) + top=cur-max+2; + } + break; + + default: + break; + } + } + + return cur; +} + + int GUIFileSelect(const char *prompt, int load, const char *start_dir, char path[]) { @@ -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. @@ -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 <SDL.h> @@ -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<GFX_HEIGHT/8-8;f++) { char s[80]; char *p; @@ -250,14 +245,27 @@ static void DoDisassem(Z80 *z80, const Z80State *s) if (hexmode) { int n; + char asc[9]; for(n=0;n<8;n++) { - GFXPrint(40+n*24,y,WHITE,"%2.2x", - (int)SPECReadForDisassem(z80,curr)); + Z80Byte b; + + b=SPECReadForDisassem(z80,curr); + + GFXPrint(40+n*24,y,WHITE,"%2.2x",(int)b); curr++; + + if (isprint(b)) + asc[n]=b; + else + asc[n]='.'; } + + asc[8]=0; + + GFXPrint(40+8*24,y,RED,"%s",asc); } else { @@ -279,7 +287,7 @@ static void DoDisassem(Z80 *z80, const Z80State *s) { case SDLK_F1: GUIMessage - ("DISASSEMBLY HELP","%s", + (eMessageBox, "DISASSEMBLY HELP","%s", "ESC - Exit \n" "H - Disassembly/hex \n" "Enter - Enter address \n" @@ -362,7 +370,7 @@ static void DoDisassemFile(Z80 *z80, const Z80State *s) if (!(fp=fopen(fname,"w"))) { - GUIMessage("ERROR","Couldn't create file:\n%s",fname); + GUIMessage(eMessageBox,"ERROR","Couldn't create file:\n%s",fname); return; } @@ -383,10 +391,27 @@ static void DoDisassemFile(Z80 *z80, const Z80State *s) static int Instruction(Z80 *z80, Z80Val data) { - Z80State s; + int f; - Z80GetState(z80,&s); - fwrite(&s,sizeof s,1,trace); + if (trace) + { + Z80State s; + + Z80GetState(z80,&s); + + fwrite(&s,sizeof s,1,trace); + } + + for(f=0;f<bpoint.no;f++) + { + long l; + + if (Z80Expression(z80,bpoint.expr[f],&l,NULL)) + { + if (l) + brk=bpoint.expr[f]; + } + } return TRUE; } @@ -400,12 +425,12 @@ static void EnableTrace(Z80 *z80, Z80State *s) if (trace) { - GUIMessage("NOTICE","Created trace log"); - Z80LodgeCallback(z80,Z80_Instruction,Instruction); + GUIMessage(eMessageBox,"NOTICE","Created trace log"); + SetCallback(z80); } else { - GUIMessage("ERROR","Failed to create trace log"); + GUIMessage(eMessageBox,"ERROR","Failed to create trace log"); } } } @@ -415,10 +440,10 @@ static void DisableTrace(Z80 *z80) { if (trace) { - GUIMessage("NOTICE","Closing current trace log"); + GUIMessage(eMessageBox,"NOTICE","Closing current trace log"); fclose(trace); trace=NULL; - Z80LodgeCallback(z80,Z80_Instruction,NULL); + ClearCallback(z80); } } @@ -437,7 +462,7 @@ static void PlaybackTrace(Z80 *z80) if (!fp) { - GUIMessage("ERROR","Couldn't open trace file"); + GUIMessage(eMessageBox,"ERROR","Couldn't open trace file"); return; } @@ -447,7 +472,7 @@ static void PlaybackTrace(Z80 *z80) if (max_pos==0) { - GUIMessage("ERROR","Empty trace file"); + GUIMessage(eMessageBox,"ERROR","Empty trace file"); fclose(fp); return; } @@ -507,7 +532,7 @@ static void PlaybackTrace(Z80 *z80) { case SDLK_F1: GUIMessage - ("PLAYBACK HELP","%s", + (eMessageBox,"PLAYBACK HELP","%s", "ESC - Exit \n" "Enter - Step number \n" "P - Search for PC \n" @@ -542,7 +567,7 @@ static void PlaybackTrace(Z80 *z80) if (rd!=1) { - GUIMessage("NOTICE","Address not found"); + GUIMessage(eMessageBox,"NOTICE","Address not found"); pos=prev_pos; } } @@ -589,6 +614,110 @@ static void PlaybackTrace(Z80 *z80) } +static void DoAddBreakpoint(Z80 *z80) +{ + const char *expr; + char *error; + long l; + + expr=GUIInputString("Expression?",""); + + if (!*expr) + return; + + if (!Z80Expression(z80,expr,&l,&error)) + { + if (error) + { + GUIMessage(eMessageBox,"INVALID EXPRESSION","%s",error); + free(error); + } + else + { + GUIMessage(eMessageBox,"ERROR","Expression is invalid"); + free(error); + } + } + else + { + bpoint.no++; + bpoint.expr=Realloc(bpoint.expr,bpoint.no * sizeof(*bpoint.expr)); + + bpoint.expr[bpoint.no-1]=StrCopy(expr); + + SetCallback(z80); + } +} + + +static void DoRemoveBreakpoint(Z80 *z80, int delete) +{ + if (bpoint.no==0) + { + if (delete) + GUIMessage(eMessageBox,"NOTICE","No breakpoints to delete"); + else + GUIMessage(eMessageBox,"NOTICE","No breakpoints to display"); + + return; + } + + GFXClear(BLACK); + + if (delete) + { + int sel; + + sel=GUIListSelect("BREAKPOINT TO DELETE",bpoint.no,bpoint.expr); + + while (sel!=-1) + { + int f; + + free(bpoint.expr[sel]); + + for(f=sel;f<bpoint.no-1;f++) + bpoint.expr[f]=bpoint.expr[f+1]; + + bpoint.no--; + + if (bpoint.no==0) + { + free(bpoint.expr); + bpoint.expr=NULL; + } + else + bpoint.expr=Realloc(bpoint.expr, + bpoint.no * sizeof(*bpoint.expr)); + + ClearCallback(z80); + + sel=GUIListSelect("BREAKPOINT TO DELETE",bpoint.no,bpoint.expr); + } + } + else + GUIListSelect("CURRENT BREAKPOINTS",bpoint.no,bpoint.expr); +} + + +static void DoClearBreakpoint(Z80 *z80) +{ + if (GUIMessage(eYesNoBox,"BREAKPOINTS","Clear all breakpoints")) + { + int f; + + for(f=0;f<bpoint.no;f++) + free(bpoint.expr[f]); + + free(bpoint.expr); + bpoint.expr=NULL; + bpoint.no=0; + + ClearCallback(z80); + } +} + + /* ---------------------------------------- EXPORTED INTERFACES */ void MemoryMenu(Z80 *z80) @@ -631,8 +760,24 @@ void MemoryMenu(Z80 *z80) PlaybackTrace(z80); break; - case SDLK_ESCAPE: case SDLK_5: + DoAddBreakpoint(z80); + break; + + case SDLK_6: + DoRemoveBreakpoint(z80,TRUE); + break; + + case SDLK_7: + DoRemoveBreakpoint(z80,FALSE); + break; + + case SDLK_8: + DoClearBreakpoint(z80); + break; + + case SDLK_ESCAPE: + case SDLK_9: quit=TRUE; break; @@ -654,4 +799,15 @@ void DisplayState(Z80 *z80) } +const char *Break(void) +{ + const char *ret; + + ret=brk; + brk=NULL; + + return ret; +} + + /* END OF FILE */ diff --git a/src/memmenu.h b/src/memmenu.h index 660242f..f04b6b8 100644 --- a/src/memmenu.h +++ b/src/memmenu.h @@ -22,8 +22,6 @@ Provides a menu driven interface for analysing memory - Requires access to the INSTRUCTION Z80 callback. - */ #ifndef ESPEC_MEMMENU_H @@ -34,12 +32,17 @@ /* Memory menu */ -void MemoryMenu(Z80 *z80); +void MemoryMenu(Z80 *z80); /* Display the state of the SPEC at the bottom of the screen */ -void DisplayState(Z80 *z80); +void DisplayState(Z80 *z80); + + +/* Non-NULL (the breakpoint hit) if a breakpoint has been hit +*/ +const char *Break(void); #endif @@ -63,8 +63,6 @@ static FILE *tape_out; /* The SPEC screen */ -#define GFX_W 320 -#define GFX_H 300 #define SCR_W 256 #define SCR_H 192 #define TXT_W 32 @@ -75,8 +73,8 @@ static FILE *tape_out; #define ATTR_AT(x,y) \ mem[ATTR+(x)+((y)/8)*32] -static const int OFF_X=(GFX_W-SCR_W)/2; -static const int OFF_Y=(GFX_H-SCR_H)/2; +static const int OFF_X=(GFX_WIDTH-SCR_W)/2; +static const int OFF_Y=(GFX_HEIGHT-SCR_H)/2; static Z80Byte mem[0x10000]; @@ -256,7 +254,7 @@ void DrawScanline(int y) aline=scanline-TOPL; - GFXHLine(0,GFX_W-1,y,coltable[border].col); + GFXHLine(0,GFX_WIDTH-1,y,coltable[border].col); if (aline>=0 && aline<SCRL) { @@ -335,17 +333,17 @@ static int EDCallback(Z80 *z80, Z80Val data) case SAVE_PATCH: if (!tape_out) { - state.AF|=Z80_F_Carry; + state.AF|=eZ80_Carry; } else { if (TAPSave(tape_out,HIBYTE(state.AF),&state.IX,&state.DE,mem)) { - state.AF&=~Z80_F_Carry; + state.AF&=~eZ80_Carry; } else { - state.AF|=Z80_F_Carry; + state.AF|=eZ80_Carry; } } break; @@ -353,17 +351,17 @@ static int EDCallback(Z80 *z80, Z80Val data) case LOAD_PATCH: if (!tape_in) { - state.AF|=Z80_F_Carry; + state.AF|=eZ80_Carry; } else { if (TAPLoad(tape_in,HIBYTE(state.AF),&state.IX,&state.DE,mem)) { - state.AF&=~Z80_F_Carry; + state.AF&=~eZ80_Carry; } else { - state.AF|=Z80_F_Carry; + state.AF|=eZ80_Carry; } } break; @@ -412,7 +410,7 @@ static int CheckTimers(Z80 *z80, Z80Val val) */ y=scanline-TOPL+OFF_Y; - if (y>=0 && y<GFX_H) + if (y>=0 && y<GFX_HEIGHT) DrawScanline(y); /* TODO: Process sound emulation */ @@ -433,23 +431,28 @@ void SPECInit(Z80 *z80) if (!(fp=fopen(SConfig(CONF_ROMFILE),"rb"))) { - GUIMessage("ERROR","Failed to open Spectrum ROM\n%s", - SConfig(CONF_ROMFILE)); + GUIMessage(eMessageBox, + "ERROR", + "Failed to open Spectrum ROM\n%s", + SConfig(CONF_ROMFILE)); Exit(""); } if (fread(mem,1,ROMLEN,fp)!=ROMLEN) { fclose(fp); - GUIMessage("ERROR","ROM file must be %d bytes long\n",ROMLEN); + GUIMessage(eMessageBox, + "ERROR", + "ROM file must be %d bytes long\n", + ROMLEN); Exit(""); } /* Patch the ROM */ RomPatch(); - Z80LodgeCallback(z80,Z80_EDHook,EDCallback); - Z80LodgeCallback(z80,Z80_Fetch,CheckTimers); + Z80LodgeCallback(z80,eZ80_EDHook,EDCallback); + Z80LodgeCallback(z80,eZ80_Instruction,CheckTimers); /* Set up the keyboard */ @@ -533,6 +536,25 @@ void SPECWriteMem(Z80 *z80, Z80Word addr, Z80Byte val) } +Z80Word SPECReadWord(Z80 *z80, Z80Word addr) +{ + /* TODO: Emulation of contention */ + return (Z80Word)mem[addr]|(Z80Word)mem[addr+1]<<8; +} + + +void SPECWriteWord(Z80 *z80, Z80Word addr, Z80Word val) +{ + if (addr>=ROMLEN) + mem[addr]=val&0xff; + + addr++; + + if (addr>=ROMLEN) + mem[addr]=val>>8; +} + + Z80Byte SPECReadPort(Z80 *z80, Z80Word port) { Z80Byte lo=port&0xff; @@ -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); @@ -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; } @@ -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); |