summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2007-01-30 23:46:49 +0000
committerIan C <ianc@noddybox.co.uk>2007-01-30 23:46:49 +0000
commit6fca8cfe0bcbe30767c30ac9b6d9a79e4fa19edc (patch)
tree303f46557317a8e43524ba7999715f547ab9783e
parentef641589bf763ea12e73abf4bf42e45ac1acd2ff (diff)
Added pseudo-hires support
-rw-r--r--CHANGES14
-rw-r--r--fat_patch.sh3
-rw-r--r--include/zx81.h7
-rw-r--r--mkrelease.sh4
-rw-r--r--source/framebuffer.c4
-rw-r--r--source/keyboard.c2
-rw-r--r--source/main.c29
-rw-r--r--source/tapes.c4
-rw-r--r--source/zx81.c218
9 files changed, 255 insertions, 30 deletions
diff --git a/CHANGES b/CHANGES
index 1a785eb..02e9a78 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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)