From 6a86fc4668ce7e213330bb78aff45c578e159f54 Mon Sep 17 00:00:00 2001 From: Ian C Date: Wed, 24 Dec 2003 18:19:00 +0000 Subject: devel snapshot --- src/Makefile | 19 ++- src/config.c | 8 +- src/config.h | 3 +- src/gfx.c | 32 +++- src/gfx.h | 16 ++ src/main.c | 11 ++ src/memmenu.c | 55 +++++- src/spec.c | 531 +++++++++++++++++++++------------------------------------- 8 files changed, 312 insertions(+), 363 deletions(-) diff --git a/src/Makefile b/src/Makefile index ed3c38e..347c5d0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,7 +18,7 @@ # # ------------------------------------------------------------------------- # -# $Id: Makefile,v 1.1.1.1 2003-12-23 23:33:02 ianc Exp $ +# $Id: Makefile,v 1.2 2003-12-24 18:19:00 ianc Exp $ # @@ -89,13 +89,13 @@ main.o: /usr/local/include/SDL/SDL_keyboard.h main.o: /usr/local/include/SDL/SDL_keysym.h main.o: /usr/local/include/SDL/SDL_mouse.h /usr/local/include/SDL/SDL_video.h main.o: /usr/local/include/SDL/SDL_mutex.h /usr/local/include/SDL/SDL_quit.h -main.o: /usr/local/include/SDL/SDL_version.h gfx.h gui.h memmenu.h config.h -main.o: exit.h +main.o: /usr/local/include/SDL/SDL_version.h z80/z80.h spec.h gfx.h gui.h +main.o: memmenu.h config.h exit.h spec.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h spec.o: /usr/include/sys/_types.h /usr/include/machine/_types.h spec.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h -spec.o: gfx.h /usr/local/include/SDL/SDL.h /usr/local/include/SDL/SDL_main.h -spec.o: /usr/local/include/SDL/SDL_types.h +spec.o: spec.h z80/z80.h /usr/local/include/SDL/SDL.h +spec.o: /usr/local/include/SDL/SDL_main.h /usr/local/include/SDL/SDL_types.h spec.o: /usr/local/include/SDL/SDL_getenv.h spec.o: /usr/local/include/SDL/SDL_error.h spec.o: /usr/local/include/SDL/begin_code.h @@ -111,7 +111,7 @@ spec.o: /usr/local/include/SDL/SDL_keyboard.h spec.o: /usr/local/include/SDL/SDL_keysym.h spec.o: /usr/local/include/SDL/SDL_mouse.h /usr/local/include/SDL/SDL_video.h spec.o: /usr/local/include/SDL/SDL_mutex.h /usr/local/include/SDL/SDL_quit.h -spec.o: /usr/local/include/SDL/SDL_version.h gui.h config.h exit.h +spec.o: /usr/local/include/SDL/SDL_version.h gfx.h gui.h config.h exit.h config.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h config.o: /usr/include/sys/_types.h /usr/include/machine/_types.h config.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h @@ -156,8 +156,9 @@ gui.o: /usr/local/include/SDL/SDL_quit.h /usr/local/include/SDL/SDL_version.h gui.o: gfx.h exit.h memmenu.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h memmenu.o: /usr/include/sys/_types.h /usr/include/machine/_types.h -memmenu.o: /usr/include/string.h /usr/include/strings.h memmenu.h gfx.h -memmenu.o: /usr/local/include/SDL/SDL.h /usr/local/include/SDL/SDL_main.h +memmenu.o: /usr/include/string.h /usr/include/strings.h memmenu.h z80/z80.h +memmenu.o: spec.h /usr/local/include/SDL/SDL.h +memmenu.o: /usr/local/include/SDL/SDL_main.h memmenu.o: /usr/local/include/SDL/SDL_types.h memmenu.o: /usr/local/include/SDL/SDL_getenv.h memmenu.o: /usr/local/include/SDL/SDL_error.h @@ -177,7 +178,7 @@ memmenu.o: /usr/local/include/SDL/SDL_mouse.h memmenu.o: /usr/local/include/SDL/SDL_video.h memmenu.o: /usr/local/include/SDL/SDL_mutex.h memmenu.o: /usr/local/include/SDL/SDL_quit.h -memmenu.o: /usr/local/include/SDL/SDL_version.h gui.h +memmenu.o: /usr/local/include/SDL/SDL_version.h gfx.h gui.h exit.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h exit.o: /usr/include/sys/_types.h /usr/include/machine/_types.h exit.o: /usr/include/stdarg.h exit.h /usr/local/include/SDL/SDL.h diff --git a/src/config.c b/src/config.c index 4035d22..c1c6e09 100644 --- a/src/config.c +++ b/src/config.c @@ -51,6 +51,7 @@ static int memsize=16; static int frames=50; static int scale=1; static int trace=0; +static int sound=1; static const struct { @@ -61,10 +62,10 @@ static const struct {"rompath", rompath, FALSE}, {"tapedir", tapedir, FALSE}, {"fullscreen", &fullscreen, TRUE}, - {"memsize", &memsize, TRUE}, {"frames", &frames, TRUE}, {"scale", &scale, TRUE}, {"trace", &trace, TRUE}, + {"sound", &sound, TRUE}, {NULL, NULL, FALSE} }; @@ -136,7 +137,7 @@ void ConfigRead(void) if (getenv("HOME")) strcpy(path,getenv("HOME")); - strcat(path,"/.ezx81"); + strcat(path,"/.espec"); if ((fp=fopen(path,"r"))) { @@ -154,7 +155,8 @@ int IConfig(IConfigVar v) &memsize, &frames, &scale, - &trace + &trace, + &sound }; return *vars[v]; diff --git a/src/config.h b/src/config.h index 94dad15..4115460 100644 --- a/src/config.h +++ b/src/config.h @@ -36,7 +36,8 @@ typedef enum CONF_MEMSIZE, CONF_FRAMES_PER_SEC, CONF_SCALE, - CONF_TRACE + CONF_TRACE, + CONF_SOUND } IConfigVar; diff --git a/src/gfx.c b/src/gfx.c index a77c496..739b876 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -51,7 +51,7 @@ static const char ident_fh[]=ESPEC_FONT_H; #endif #define SCR_W 320 -#define SCR_H 200 +#define SCR_H 300 #define LOCK do \ { \ @@ -168,8 +168,16 @@ void GFXInit(void) frame=1000/IConfig(CONF_FRAMES_PER_SEC); - if (SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO)) - Exit("Failed to init SDL: %s\n",SDL_GetError()); + if (IConfig(CONF_SOUND)) + { + if (SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_AUDIO)) + Exit("Failed to init SDL: %s\n",SDL_GetError()); + } + else + { + if (SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO)) + Exit("Failed to init SDL: %s\n",SDL_GetError()); + } if (!(surface=SDL_SetVideoMode(SCR_W*scale, SCR_H*scale, @@ -262,6 +270,18 @@ SDL_Event *GFXWaitKey(void) } +void GFXLock(void) +{ + LOCK; +} + + +void GFXUnlock(void) +{ + UNLOCK; +} + + void GFXPlot(int x, int y, Uint32 col) { LOCK; @@ -272,6 +292,12 @@ void GFXPlot(int x, int y, Uint32 col) } +void GFXFastPlot(int x, int y, Uint32 col) +{ + putpixel(x,y,col); +} + + void GFXRect(int x, int y, int w, int h, Uint32 col, int solid) { LOCK; diff --git a/src/gfx.h b/src/gfx.h index baa19d2..d3f1ec3 100644 --- a/src/gfx.h +++ b/src/gfx.h @@ -92,11 +92,27 @@ SDL_Event *GFXGetKey(void); SDL_Event *GFXWaitKey(void); +/* Lock the screen for updates +*/ +void GFXLock(void); + + +/* Unlock the screen following updates +*/ +void GFXUnlock(void); + + /* Note that no bound checking (except for GFXPrint()) is done - it is the callers responsibility to plot onscreen. */ +/* Plot a point without locking. GFXLock() and GFXUnlock() MUST surround + calls to this +*/ +void GFXFastPlot(int x, int y, Uint32 col); + + /* Plot a point */ void GFXPlot(int x, int y, Uint32 col); diff --git a/src/main.c b/src/main.c index e69eb77..c97aab3 100644 --- a/src/main.c +++ b/src/main.c @@ -91,8 +91,19 @@ int main(int argc, char *argv[]) while(!quit) { + Z80State s1,s2; + + Z80GetState(z80,&s1); Z80SingleStep(z80); + Z80GetState(z80,&s2); + + if (s2.PC>0x3fff) + { + printf("PC > 0x3fff - from 0x%4.4x\n",s1.PC); + return 0; + } + if (trace) { DisplayState(z80); diff --git a/src/memmenu.c b/src/memmenu.c index 2badf65..516bd36 100644 --- a/src/memmenu.c +++ b/src/memmenu.c @@ -20,13 +20,14 @@ ------------------------------------------------------------------------- - Provides a common error exit point + Provides the memory menu */ static const char ident[]="$Id$"; #include #include +#include #include "memmenu.h" #include "spec.h" @@ -51,8 +52,6 @@ static const char ident_h[]=ESPEC_MEMMENU_H; #define GREEN GFXRGB(100,255,100) #define BLUE GFXRGB(100,100,255) -#define MENU - /* ---------------------------------------- PRIVATE FUNCTIONS */ @@ -104,7 +103,49 @@ static const char *FlagString(Z80Byte flag) } -static int EnterAddress(Z80Word *w) +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(Z80 *z80, Z80Word *w) { unsigned long ul; const char *p; @@ -113,7 +154,7 @@ static int EnterAddress(Z80Word *w) if (*p) { - ul=strtoul(p,NULL,0); + ul=Address(z80,p); if (ul>0xffff) { @@ -213,7 +254,7 @@ static void DoDisassem(Z80 *z80, const Z80State *s) case SDLK_RETURN: case SDLK_KP_ENTER: - EnterAddress(&pc); + EnterAddress(z80,&pc); break; case SDLK_UP: @@ -324,6 +365,4 @@ void DisplayState(Z80 *z80) } - - /* END OF FILE */ diff --git a/src/spec.c b/src/spec.c index 51006df..a8cb9eb 100644 --- a/src/spec.c +++ b/src/spec.c @@ -47,51 +47,79 @@ static const char ident_h[]=ESPEC_SPECH; /* ---------------------------------------- STATICS */ -static const int ROMLEN=0x2000; -static const int ROM_SAVE=0x2fc; -static const int ROM_LOAD=0x347; - -/* No of cycles in each 64us HSYNC (hopefully) -*/ -static const int HSYNC_PERIOD=321; +static const int ROMLEN=0x4000; +static const int ROM_SAVE=0x4c6; +static const int ROM_LOAD=0x562; /* The SPEC screen */ -static const int SCR_W=256; -static const int SCR_H=192; -static const int TXT_W=32; -static const int TXT_H=24; +#define GFX_W 320 +#define GFX_H 300 +#define SCR_W 256 +#define SCR_H 192 +#define TXT_W 32 +#define TXT_H 24 +#define SCRDATA 0x4000 +#define ATTR 0x5800 -/* These assume a 320x200 screen -*/ -static const int OFF_X=(320-256)/2; -static const int OFF_Y=(200-192)/2; +#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 Z80Byte mem[0x10000]; -static Z80Word RAMBOT=0; -static Z80Word RAMTOP=0; -static Z80Word RAMLEN=0; -/* Counter used when triggering the interrupts for the display +/* Number of cycles per scan lines and scan line control */ -static int nmigen=FALSE; -static int hsync=FALSE; +static Z80Val SCAN_CYCLES=224; +static int scanline=0; + -/* The ULA +/* GFX vars */ +#define FLASH 16 /* Frames per flash */ + +static int flash=0; +static int flashctr=0; + +static int border=0; + +#define TOPL 64 /* Scanlines before 'first' line */ +#define SCRL SCR_H /* Scanlines making up screen data */ +#define BOTL 56 /* Scanlines after 'last' line */ + +#define TOTL (TOPL+SCRL+BOTL) + +#define NVAL 235 /* Normal RGB intensity */ +#define BVAL 255 /* Bright RGB intensity */ + static struct { - int x; - int y; - int c; - int release; -} ULA; + Uint32 col; + int r,g,b; +} coltable[16]= +{ + {0, 0x00,0x00,0x00}, /* BLACK */ + {0, 0x00,0x00,NVAL}, /* BLUE */ + {0, NVAL,0x00,0x00}, /* RED */ + {0, NVAL,0x00,NVAL}, /* MAGENTA */ + {0, 0x00,NVAL,0x00}, /* GREEN */ + {0, 0x00,NVAL,NVAL}, /* CYAN */ + {0, NVAL,NVAL,0x00}, /* YELLOW */ + {0, NVAL,NVAL,NVAL}, /* WHITE */ + + {0, 0x00,0x00,0x00}, /* BLACK */ + {0, 0x00,0x00,BVAL}, /* BLUE */ + {0, BVAL,0x00,0x00}, /* RED */ + {0, BVAL,0x00,BVAL}, /* MAGENTA */ + {0, 0x00,BVAL,0x00}, /* GREEN */ + {0, 0x00,BVAL,BVAL}, /* CYAN */ + {0, BVAL,BVAL,0x00}, /* YELLOW */ + {0, BVAL,BVAL,BVAL}, /* WHITE */ -/* GFX vars -*/ -static Uint32 white; -static Uint32 black; +}; /* The keyboard @@ -150,9 +178,6 @@ static const MatrixMap keymap[]= {SDLK_RETURN, KY1(6,0)}, {SDLK_SPACE, KY1(7,0)}, - {SDLK_COMMA, KY1(7,1)}, /* In the right place... */ - {SDLK_PERIOD, KY1(7,1)}, /* ...or the right key... */ - {SDLK_BACKSPACE, KY2(0,0,4,0)}, {SDLK_DELETE, KY2(0,0,4,0)}, {SDLK_UP, KY2(0,0,4,3)}, @@ -160,8 +185,13 @@ static const MatrixMap keymap[]= {SDLK_LEFT, KY2(0,0,3,4)}, {SDLK_RIGHT, KY2(0,0,4,2)}, - {SDLK_RSHIFT, KY1(0,0)}, {SDLK_LSHIFT, KY1(0,0)}, + {SDLK_RSHIFT, KY1(7,1)}, + {SDLK_LCTRL, KY1(0,0)}, + {SDLK_RCTRL, KY1(7,1)}, + {SDLK_LALT, KY1(0,0)}, + {SDLK_RALT, KY1(7,1)}, + {SDLK_CAPSLOCK, KY2(0,0,3,1)}, {SDLK_UNKNOWN, 0,0,0,0}, }; @@ -169,19 +199,71 @@ static const MatrixMap keymap[]= /* ---------------------------------------- PRIVATE FUNCTIONS */ +void DrawScanline(int y) +{ + int aline; + int f,r; + int ink,paper,t; + Z80Byte *scr; + Z80Byte b; + Z80Byte att; + + aline=scanline-TOPL; + + GFXHLine(0,GFX_W-1,y,coltable[border].col); + + if (aline>=0 && aline>3; + + if (att&0x40) + { + ink+=8; + paper+=8; + } + + if ((att&0x80)&&(flash)) + { + t=ink; + ink=paper; + paper=t; + } + + for(r=7,b=*scr++;r>=0;r--) + if (b&(1<=28 && b<=37) /* 0-9 */ - return '0'+b-28; - - if (b>=38 && b<=63) /* A-Z */ - return 'a'+b-38; - - return 0; -} - - -static const char *ConvertFilename(Z80Word addr) -{ - static char buff[FILENAME_MAX]; - char *p; - - p=buff; - *p=0; - - if (addr>0x8000) - return buff; - - do - { - char c=ToASCII(mem[addr]&0x7f); - - if (c) - *p++=c; - - } while(mem[addr++]<0x80); - - *p=0; - - return buff; -} - static void LoadTape(Z80State *state) { - const char *p=ConvertFilename(state->DE); - char path[FILENAME_MAX]; - FILE *fp; - Z80Word addr; - int c; - - if (strlen(p)==0) - { - GUIMessage("ERROR","Can't load empty filename"); - return; - } - - strcpy(path,SConfig(CONF_TAPEDIR)); - strcat(path,"/"); - strcat(path,p); - strcat(path,".p"); - - if (!(fp=fopen(path,"rb"))) - { - GUIMessage("ERROR","Can't load file:\n%s",path); - return; - } - - addr=0x4009; - - while((c=getc(fp))!=EOF) - { - if (addr>=0x4000) - mem[addr]=(Z80Byte)c; - - addr++; - } - - fclose(fp); + state->AF|=Z80_F_Carry; } static void SaveTape(Z80State *state) { - const char *p=ConvertFilename(state->DE); - char path[FILENAME_MAX]; - FILE *fp; - Z80Word start; - Z80Word end; - - if (strlen(p)==0) - { - GUIMessage("ERROR","Can't save empty filename"); - return; - } - - strcpy(path,SConfig(CONF_TAPEDIR)); - strcat(path,"/"); - strcat(path,p); - strcat(path,".p"); - - if (!(fp=fopen(path,"wb"))) - { - GUIMessage("ERROR","Can't write file:\n%s",path); - return; - } - - start=0x4009; - end=(Z80Word)mem[0x4014]|(Z80Word)mem[0x4015]<<8; - - while(start<=end) - putc(mem[start++],fp); - - fclose(fp); + state->AF|=Z80_F_Carry; } @@ -333,87 +310,51 @@ static int EDCallback(Z80 *z80, Z80Val data) break; } + Z80SetState(z80,&state); + return TRUE; } -static void ULA_Video_Shifter(Z80 *z80, Z80Byte val) +static int CheckTimers(Z80 *z80, Z80Val val) { - Z80State state; - Z80Word base; - int x,y; - int inv; - int b; - - Z80GetState(z80,&state); - - /* Extra check due to out dodgy ULA emulation - */ - if (ULA.y>=0 && ULA.ySCAN_CYCLES) { - Uint32 fg,bg; + int y; - /* Position on screen corresponding to ULA - */ - x=OFF_X+ULA.x*8; - y=OFF_Y+ULA.y; + Z80ResetCycles(z80,val-SCAN_CYCLES); - /* Get ULA invert state and clear to ULA 6-but code + /* Increment scan line and check for frame flyback */ - inv=val&0x80; - val&=0x3f; + scanline++; - base=((Z80Word)state.I<<8)|(val<<3)|ULA.c; - - if (inv) - { - fg=white; - bg=black; - } - else + if (scanline==TOTL) { - fg=black; - bg=white; - } + scanline=0; - for(b=0;b<8;b++) - { - if (mem[base]&(1<<(7-b))) - GFXPlot(x+b,y,fg); - else - GFXPlot(x+b,y,bg); - } - } + flashctr++; - ULA.x=(ULA.x+1)&0x1f; + if (flashctr==FLASH) + { + flash^=1; + flashctr=0; + } - if (ULA.x==0) - Z80Interrupt(z80,0xff); -} + Z80Interrupt(z80,0xff); + GFXEndFrame(TRUE); + GFXStartFrame(); + } -static int CheckTimers(Z80 *z80, Z80Val val) -{ - if (val>HSYNC_PERIOD) - { - Z80ResetCycles(z80,0); + /* Draw scanline + y=OFF_X-TOPL+scanline; + */ + y=scanline-TOPL+OFF_Y; - if (nmigen) - { - Z80NMI(z80,0xff); - printf("NMIGEN\n"); - } - else if (hsync) - { - printf("HSYNC\n"); - if (ULA.release) - { - /* ULA.release=FALSE; */ - ULA.c=(ULA.c+1)&7; - ULA.y++; - ULA.x=0; - } - } + if (y>=0 && y0x7fff) - { - Z80Byte b; - - /* B6 of R is tied to the IRQ line (only when HSYNC active?) - if ((HSYNC)&&(!(z80->R&0x40))) - z80->IRQ=TRUE; - */ - - b=mem[addr&0x7fff]; - - /* If bit 6 of the opcode is set the opcode is sent as is to the - Z80. If it's not, the byte is interretted by the ULA. - */ - if (b&0x40) - { - ULA_Video_Shifter(z80,0); - } - else - { - ULA_Video_Shifter(z80,b); - b=0; - } - - return b; - } - else - return mem[addr&0x7fff]; - + /* TODO: Emulation of contention */ + return mem[addr]; } void SPECWriteMem(Z80 *z80, Z80Word addr, Z80Byte val) { - addr=addr&0x7fff; - - if (addr>=RAMBOT && addr<=RAMTOP) + if (addr>=ROMLEN) mem[addr]=val; } Z80Byte SPECReadPort(Z80 *z80, Z80Word port) { - Z80Byte b=0; - - printf("IN %4.4x\n",port); + Z80Byte lo=port&0xff; + Z80Byte hi=port>>8; + Z80Byte b=0xff; + int f; - switch(port&0xff) + switch(lo) { - case 0xfe: /* ULA */ + case 0x1f: /* TODO: Kempston joystick */ + break; + + case 0x7f: /* TODO: Fuller joystick */ + break; + + case 0xfb: /* TODO: ZX Printer */ + break; + + case 0x01: /* ULA */ /* Key matrix */ - switch(port&0xff00) - { - case 0xfe00: - b=matrix[0]; - break; - case 0xfd00: - b=matrix[1]; - break; - case 0xfb00: - b=matrix[2]; - break; - case 0xf700: - b=matrix[3]; - break; - case 0xef00: - b=matrix[4]; - break; - case 0xdf00: - b=matrix[5]; - break; - case 0xbf00: - b=matrix[6]; - break; - case 0x7f00: - b=matrix[7]; - break; - } + b=0; - /* Turn off HSYNC if NMI generator is OFF and redraw screen to - match output ULA has since sent out. - */ - if (!nmigen && hsync) - { - hsync=FALSE; + for(f=0;f<8;f++) + if (!(hi&(1<