diff options
| -rw-r--r-- | CHANGES | 14 | ||||
| -rw-r--r-- | fat_patch.sh | 3 | ||||
| -rw-r--r-- | include/zx81.h | 7 | ||||
| -rw-r--r-- | mkrelease.sh | 4 | ||||
| -rw-r--r-- | source/framebuffer.c | 4 | ||||
| -rw-r--r-- | source/keyboard.c | 2 | ||||
| -rw-r--r-- | source/main.c | 29 | ||||
| -rw-r--r-- | source/tapes.c | 4 | ||||
| -rw-r--r-- | source/zx81.c | 218 | 
9 files changed, 255 insertions, 30 deletions
| @@ -1,4 +1,4 @@ -+ Completed, * In progress, - Not done. ++ Completed, * In progress, - Not done/abandoned.  Changes from V1.0 to V1.1 @@ -16,4 +16,14 @@ Changes from V1.1 to V1.1a (uncontrolled release).  Changes from V1.1a to V1.2      +	Controlled version of keyboard fix. -    *	Adding Wifi code so that a web server can act as a file store. +    -	Added seperate ARM7/ARM9 code so I could use Wifi to use a web server +        as a file store.  Wifi lib doesn't work with my access point, so +	reverted to a simpler ARM9 build. +    +	Compiled with newer version of libfat so that the DLDI interfaces can +    	be used (thanks Chism!)  At last I can load ZX81 programs into my own +	damned emulator! +    +	Added support for text mode overlayed with a rotation screen for bitmap +    	purposes. +    +	Added code to ZX81 emulation to notice changes to I register and search +    	for hires display files.  Works for a lot of hires games, though needs +	proper display emulation for Manic Miner, so that won't work :-( diff --git a/fat_patch.sh b/fat_patch.sh new file mode 100644 index 0000000..65af06f --- /dev/null +++ b/fat_patch.sh @@ -0,0 +1,3 @@ +#!/bin/sh +dlditool.exe ../DLDI/mmcf.dldi ds81.nds +dlditool.exe ../DLDI/mmcf.dldi ds81.ds.gba diff --git a/include/zx81.h b/include/zx81.h index 992cba7..4050918 100644 --- a/include/zx81.h +++ b/include/zx81.h @@ -33,7 +33,7 @@  /* Initialise the ZX81  */ -void	ZX81Init(uint16 *vram, Z80 *z80); +void	ZX81Init(uint16 *text_vram, uint16 *bitmap_vram, Z80 *z80);  /* Handle keypresses  */ @@ -58,8 +58,13 @@ void	ZX81Reset(Z80 *z80);     lost on the next emulation update cycle.     The character '%' toggles inverse video. + +   ZX81SuspendDisplay() and ZX81ResumeDisplay() should be called so that the +   ZX81 can set up its internals.  */  void	ZX81DisplayString(const char *p); +void	ZX81SuspendDisplay(void); +void	ZX81ResumeDisplay(void);  /* Interfaces for the Z80  */ diff --git a/mkrelease.sh b/mkrelease.sh index 0ad5661..2210ca2 100644 --- a/mkrelease.sh +++ b/mkrelease.sh @@ -8,5 +8,7 @@ make ADDITIONAL_CFLAGS="-DDS81_DISABLE_FAT"  mv ds81.nds ds81-nofat.nds  mv ds81.ds.gba ds81-nofat.ds.gba -rm -f arm9/build/main.* +rm -f build/main.*  make + +./fat_patch.sh diff --git a/source/framebuffer.c b/source/framebuffer.c index 4a4b03d..ef66235 100644 --- a/source/framebuffer.c +++ b/source/framebuffer.c @@ -259,7 +259,7 @@ void FB_Blit(sImage *img, int x, int y)  {      if (img->width==WIDTH && img->height==HEIGHT)      { -	dmaCopy(img->data8,buff,SCREEN_WIDTH*SCREEN_HEIGHT*2); +	dmaCopy(img->image.data8,buff,SCREEN_WIDTH*SCREEN_HEIGHT*2);      }      else      { @@ -267,7 +267,7 @@ void FB_Blit(sImage *img, int x, int y)  	for(f=0;f<img->height;f++)  	{ -	    dmaCopy(img->data16+(f*img->width), +	    dmaCopy(img->image.data16+(f*img->width),  		    buff+x+(y+f)*WIDTH,img->width*2);  	}      } diff --git a/source/keyboard.c b/source/keyboard.c index eb50310..cb6a932 100644 --- a/source/keyboard.c +++ b/source/keyboard.c @@ -270,7 +270,7 @@ void SK_DisplayKeyboard(uint16 *vram)      loadPCX(keyb_bin,&img);      image8to16(&img); -    dmaCopy(img.data8,vram,SCREEN_WIDTH*SCREEN_HEIGHT*2); +    dmaCopy(img.image.data8,vram,SCREEN_WIDTH*SCREEN_HEIGHT*2);  } diff --git a/source/main.c b/source/main.c index 29f4448..aed05f5 100644 --- a/source/main.c +++ b/source/main.c @@ -93,6 +93,7 @@ static void Splash(void)      int y;      int res=FALSE; +    ZX81SuspendDisplay();      ZX81DisplayString("10 print '%the zx81 is ace%'\n20 goto 10");      FB_Clear(); @@ -159,6 +160,8 @@ static void Splash(void)      {  	swiWaitForVBlank();      } + +    ZX81ResumeDisplay();  } @@ -173,6 +176,8 @@ static void MapJoypad(void)      SK_DisplayKeyboard(BG_GFX_SUB); +    ZX81SuspendDisplay(); +      ZX81DisplayString("press the joypad button you want\n"  		      "to define and then the ZX81 key\n"  		      "you want to use.\n\n" @@ -217,6 +222,8 @@ static void MapJoypad(void)  	swiWaitForVBlank();      } + +    ZX81ResumeDisplay();  } @@ -228,26 +235,34 @@ int main(int argc, char *argv[])      powerON(POWER_ALL_2D); -    /* Set up main text screen and load the ROM character data +    /* Set up main screen for ZX81 and load the ROM character data      */ -    videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE); +    videoSetMode(MODE_3_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG3_ACTIVE); -    vramSetBankA(VRAM_A_MAIN_BG_0x6000000); -    vramSetBankB(VRAM_B_MAIN_BG_0x6020000); +    vramSetBankA(VRAM_A_MAIN_BG_0x06000000); +    vramSetBankB(VRAM_B_MAIN_BG_0x06020000); -    BG0_CR = BG_COLOR_256|BG_MAP_BASE(0)|BG_TILE_BASE(1); +    BG0_CR = BG_COLOR_256 | BG_MAP_BASE(0) | BG_TILE_BASE(1) | BG_PRIORITY(0);      BG0_X0 = 0;      BG0_Y0 = 0;      BG_PALETTE[0] = RGB15(31,31,31);      BG_PALETTE[1] = RGB15(0,0,0); +    BG3_CR = BG_BMP16_256x256 | BG_BMP_BASE(2) | BG_PRIORITY(1); +    BG3_XDX = 0x100; +    BG3_XDY = 0; +    BG3_YDX = 0; +    BG3_YDY = 0x100; +    BG3_CX = 0; +    BG3_CY = 0; +      dmaCopy(rom_font_bin,(void *)BG_TILE_RAM(1),rom_font_bin_size);      /* Set up the sub-screen for rotation (basically for use as a framebuffer)      */      videoSetModeSub(MODE_5_2D | DISPLAY_BG2_ACTIVE); -    vramSetBankC(VRAM_C_SUB_BG_0x6200000); +    vramSetBankC(VRAM_C_SUB_BG_0x06200000);      SUB_BG2_CR = BG_BMP16_256x256;      SUB_BG2_XDX = 0x100; @@ -282,7 +297,7 @@ int main(int argc, char *argv[])  	GUI_Alert(TRUE,"Failed to initialise\nthe Z80 CPU emulation!");      } -    ZX81Init((uint16*)SCREEN_BASE_BLOCK(0), z80); +    ZX81Init((uint16*)BG_MAP_RAM(0), (uint16*)BG_BMP_RAM(2), z80);      Splash(); diff --git a/source/tapes.c b/source/tapes.c index bc5ac8b..8f141f9 100644 --- a/source/tapes.c +++ b/source/tapes.c @@ -232,6 +232,8 @@ void SelectTape(void)      InitTapes(); +    ZX81SuspendDisplay(); +      while(!done)      {  	uint32 key=0; @@ -272,5 +274,7 @@ void SelectTape(void)  	    done=TRUE;  	}      } + +    ZX81ResumeDisplay();  } diff --git a/source/zx81.c b/source/zx81.c index d6edaa0..9a053b5 100644 --- a/source/zx81.c +++ b/source/zx81.c @@ -69,9 +69,15 @@ static Z80Val		FRAME_TSTATES=FAST_TSTATES;  /* The ZX81 screen and memory  */ +static void		(*DrawScreen)(Z80 *z80); +  static int		waitkey=FALSE;  static int		started=FALSE; +static int		hires=FALSE; +static int		hires_dfile; +static int		last_I; +  #define	SCR_W		256  #define	SCR_H		192  #define	TXT_W		32 @@ -95,7 +101,8 @@ static int		tape_len;  /* GFX vars  */ -static uint16		*screen; +static uint16		*txt_screen; +static uint16		*bmp_screen;  /* The keyboard  */ @@ -330,7 +337,89 @@ static void LoadExternalTape(FILE *tape, Z80 *z80)  } -static void DrawScreen(Z80 *z80) +static void ClearBitmap(void) +{ +    uint16 *s; +    uint16 p; +    int f; + +    s = bmp_screen; +    p = 0x8000|RGB15(31,31,31); + +    for(f=0;f<SCREEN_WIDTH*SCREEN_HEIGHT;f++) +    { +    	*s++=p; +    } +} + + +static void ClearText(void) +{ +    uint16 *s; +    int f; + +    s = txt_screen; + +    for(f=0;f<TXT_W*TXT_H;f++) +    { +    	*s++=0; +    } +} + + +static void DrawScreen_HIRES(Z80 *z80) +{ +    uint16 *bmp; +    Z80Byte *scr; +    int x,y; +    int table; + +    scr = mem + hires_dfile; +    bmp = bmp_screen; +    table = z80->I << 8; + +    /* scr is increment in both loops so that it can skip of the end-of-line +       character +    */ +    for(y=0; y<192; y++) +    { +    	for(x=0; x<32; x++) +	{ +	    int c; +	    int v; +	    int b; + +	    c = *scr; + +	    v = mem[table + (c&0x3f)*8]; + +	    if (c & 0x80) +	    { +	    	v ^= 0xff; +	    } + +	    for(b=0;b<8;b++) +	    { +	    	if (v & 0x80) +		{ +		    *bmp++ = 0x8000; +		} +		else +		{ +		    *bmp++ = 0xffff; +		} + +		v=v<<1; +	    } + +	    scr++; +	} + +	scr++; +    } +} + +static void DrawScreen_TEXT(Z80 *z80)  {      Z80Byte *scr=mem+WORD(DFILE);      int x,y; @@ -349,11 +438,11 @@ static void DrawScreen(Z80 *z80)  	    if (ch&0x80)  	    { -	    	screen[x+y*32]=(ch&0x3f)|0x40; +	    	txt_screen[x+y*32]=(ch&0x3f)|0x40;  	    }  	    else  	    { -	    	screen[x+y*32]=(ch&0x3f); +	    	txt_screen[x+y*32]=(ch&0x3f);  	    }  	    x++; @@ -369,7 +458,7 @@ static void DrawSnow(Z80 *z80)      uint16 *s;      int f; -    s = screen; +    s = txt_screen;      for(f=0;f<TXT_W*TXT_H;f++)      { @@ -378,6 +467,56 @@ static void DrawSnow(Z80 *z80)  } +static void FindHiresDFILE(void) +{ +    /* Somewhat based on the code from xz81, an X-based ZX81 emulator, +       (C) 1994 Ian Collier.  Search the ZX81's RAM until we find what looks +       like a hi-res display file. + +       Bizarrely the original code used 'f' for a loop counter too...  Another +       poor soul forever damaged by the ZX81's keyword entry system... +    */ +    int f; + +    for(f=0x8000-(33*192); f>0x4000 ; f--) +    { +	int v; + +	v = mem[f+32]; + +	if (v&0x40) +	{ +	    int ok = TRUE; +	    int n; + +	    for(n=0;n<192 && ok;n++) +	    { +	    	if (mem[f+33*n]&0x40) +		{ +		    ok = FALSE; +		} + +		if (mem[f+32+33*n] != v) +		{ +		    ok = FALSE; +		} +	    } + +	    if (ok) +	    { +	    	hires_dfile = f; +		return; +	    } +	} +    } + +    /* All else fails, put the hires dfile at 0x4000 -- at least it should be +       obvious that the hires won't work for whatever is being run. +    */ +    hires_dfile = 0x4000; +} + +  /* Perform ZX81 housekeeping functions like updating FRAMES and updating LASTK  */  static void ZX81HouseKeeping(Z80 *z80) @@ -464,9 +603,33 @@ static int CheckTimers(Z80 *z80, Z80Val val)  {      if (val>=FRAME_TSTATES)      { +    	/* Check for hi-res modes +	*/ +	if (z80->I && z80->I != last_I) +	{ +	    last_I = z80->I; + +	    if (z80->I == 0x1e) +	    { +	    	hires = FALSE; +		DrawScreen = DrawScreen_TEXT; +		ClearBitmap(); +	    } +	    else +	    { +	    	hires = TRUE; +		DrawScreen = DrawScreen_HIRES; +		ClearText(); +		FindHiresDFILE(); +	    } +	} +  	Z80ResetCycles(z80,val-FRAME_TSTATES); -	if (started && ((mem[CDFLAG] & 0x80) || waitkey)) +	/* Kludge warning - We assume that a hires display will not be in +	   FAST mode!  +	*/ +	if (started && ((mem[CDFLAG] & 0x80) || waitkey || hires))  	{  	    DrawScreen(z80);  	    FRAME_TSTATES=SLOW_TSTATES; @@ -582,11 +745,19 @@ static int EDCallback(Z80 *z80, Z80Val data)  /* ---------------------------------------- EXPORTED INTERFACES  */ -void ZX81Init(uint16 *vram, Z80 *z80) +void ZX81Init(uint16 *text_vram, uint16* bitmap_vram, Z80 *z80)  {      Z80Word f; -    screen = vram; +    txt_screen = text_vram; +    bmp_screen = bitmap_vram; + +    hires = FALSE; +    hires_dfile = 0; +    last_I = 0x1e; +    DrawScreen = DrawScreen_TEXT; + +    ClearBitmap();      /* Load the ROM      */ @@ -602,7 +773,6 @@ void ZX81Init(uint16 *vram, Z80 *z80)      */      memcpy(mem+ROMLEN,mem,ROMLEN); -      /* Memory size (16K)      */      RAMBOT=0x4000; @@ -701,6 +871,7 @@ Z80Byte ZX81ReadPort(Z80 *z80, Z80Word port)  	    break;  	default: +	    b = 0xff;	/* Idle bus */  	    break;      } @@ -732,6 +903,13 @@ void ZX81Reset(Z80 *z80)      Z80ResetCycles(z80,0);      started=FALSE; + +    hires = FALSE; +    hires_dfile = 0; +    last_I = 0x1e; +    DrawScreen = DrawScreen_TEXT; + +    ClearBitmap();  } @@ -748,20 +926,28 @@ void ZX81SetTape(const Z80Byte *image, int len)  } +void ZX81SuspendDisplay(void) +{ +    ClearBitmap(); +    ClearText(); +} + + +void ZX81ResumeDisplay(void) +{ +    ClearText(); +} + +  void ZX81DisplayString(const char *p)  {      uint16 *s;      uint16 inv=0;      int f; -    s = screen; - -    for(f=0;f<TXT_W*TXT_H;f++) -    { -    	*s++=0; -    } +    ClearText(); -    s = screen; +    s = txt_screen;      f = 0;      while(*p) | 
