diff options
author | Ian C <ianc@noddybox.co.uk> | 2007-01-30 23:46:49 +0000 |
---|---|---|
committer | Ian C <ianc@noddybox.co.uk> | 2007-01-30 23:46:49 +0000 |
commit | 6fca8cfe0bcbe30767c30ac9b6d9a79e4fa19edc (patch) | |
tree | 303f46557317a8e43524ba7999715f547ab9783e | |
parent | ef641589bf763ea12e73abf4bf42e45ac1acd2ff (diff) |
Added pseudo-hires support
-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) |