summaryrefslogtreecommitdiff
path: root/arm9/source/zx81.c
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2007-01-12 00:40:03 +0000
committerIan C <ianc@noddybox.co.uk>2007-01-12 00:40:03 +0000
commitef641589bf763ea12e73abf4bf42e45ac1acd2ff (patch)
tree0afa591a9c5294a07508f6c5c56a0857adfd2285 /arm9/source/zx81.c
parent50d960d99f0783799f81236d9225a6940606fe38 (diff)
Gone back to a simpler ARM9 only build as the new dynamic libfat library means I can use that, and dswifi wouldn't work with my AP.
Diffstat (limited to 'arm9/source/zx81.c')
-rw-r--r--arm9/source/zx81.c792
1 files changed, 0 insertions, 792 deletions
diff --git a/arm9/source/zx81.c b/arm9/source/zx81.c
deleted file mode 100644
index 41ff686..0000000
--- a/arm9/source/zx81.c
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- ds81 - Nintendo DS ZX81 emulator
-
- Copyright (C) 2006 Ian Cowburn <ianc@noddybox.co.uk>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- -------------------------------------------------------------------------
-
- Provides the emulation for the zX81
-
-*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <nds.h>
-
-#include "ds81_global.h"
-
-#include "zx81.h"
-#include "gui.h"
-
-#include "zx81_bin.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#define MAX_FNAME_LEN 30
-
-
-/* ---------------------------------------- STATICS
-*/
-#define ROMLEN 0x2000
-#define ROM_SAVE 0x2fc
-#define ROM_LOAD 0x347
-
-#define ED_SAVE 0xf0
-#define ED_LOAD 0xf1
-#define ED_WAITKEY 0xf2
-#define ED_ENDWAITKEY 0xf3
-#define ED_PAUSE 0xf4
-
-#define SLOW_TSTATES 16000
-#define FAST_TSTATES 64000
-
-#define LASTK1 16421
-#define LASTK2 16422
-#define MARGIN 16424
-#define FRAMES 16436
-#define CDFLAG 16443
-
-static Z80Val FRAME_TSTATES=FAST_TSTATES;
-
-/* The ZX81 screen and memory
-*/
-static int waitkey=FALSE;
-static int started=FALSE;
-
-#define SCR_W 256
-#define SCR_H 192
-#define TXT_W 32
-#define TXT_H 24
-
-static Z80Byte mem[0x10000];
-
-static Z80Word RAMBOT=0;
-static Z80Word RAMTOP=0;
-static Z80Word RAMLEN=0;
-
-#define DFILE 0x400c
-
-#define WORD(a) (mem[a] | (Z80Word)mem[a+1]<<8)
-
-/* Tape
-*/
-static int enable_filesystem;
-static const Z80Byte *tape_image;
-static int tape_len;
-
-/* GFX vars
-*/
-static uint16 *screen;
-
-/* The keyboard
-*/
-static Z80Byte matrix[8];
-
-static struct
-{
- int row;
- int bit;
-} key_matrix[]=
- {
- {3,0x01}, {3,0x02}, {3,0x04}, {3,0x08}, {3,0x10}, /* 1 - 5 */
- {4,0x10}, {4,0x08}, {4,0x04}, {4,0x02}, {4,0x01}, /* 6 - 0 */
- {2,0x01}, {2,0x02}, {2,0x04}, {2,0x08}, {2,0x10}, /* Q - T */
- {5,0x10}, {5,0x08}, {5,0x04}, {5,0x02}, {5,0x01}, /* Y - P */
- {1,0x01}, {1,0x02}, {1,0x04}, {1,0x08}, {1,0x10}, /* A - G */
- {6,0x10}, {6,0x08}, {6,0x04}, {6,0x02}, {6,0x01}, /* H - NL */
- {0,0x01}, {0,0x02}, {0,0x04}, {0,0x08}, {0,0x10}, /* CAPS - V */
- {7,0x10}, {7,0x08}, {7,0x04}, {7,0x02}, {7,0x01} /* B - SPACE */
- };
-
-
-/* ---------------------------------------- PRIVATE FUNCTIONS
-*/
-#define PEEKW(addr) (mem[addr] | (Z80Word)mem[addr+1]<<8)
-
-#define POKEW(addr,val) do \
- { \
- Z80Word wa=addr; \
- Z80Word wv=val; \
- mem[wa]=wv; \
- mem[wa+1]=wv>>8; \
- } while(0)
-
-static void RomPatch(void)
-{
- static const Z80Byte save[]=
- {
- 0xed, ED_SAVE, /* (SAVE) */
- 0xc3, 0x07, 0x02, /* JP $0207 */
- 0xff /* End of patch */
- };
-
- static const Z80Byte load[]=
- {
- 0xed, ED_LOAD, /* (LOAD) */
- 0xc3, 0x07, 0x02, /* JP $0207 */
- 0xff /* End of patch */
- };
-
- static const Z80Byte fast_hack[]=
- {
- 0xed, ED_WAITKEY, /* (START KEY WAIT) */
- 0xcb,0x46, /* L: bit 0,(hl) */
- 0x28,0xfc, /* jr z,L */
- 0xed, ED_ENDWAITKEY, /* (END KEY WAIT) */
- 0x00, /* nop */
- 0xff /* End of patch */
- };
-
- static const Z80Byte kbd_hack[]=
- {
- 0x2a,0x25,0x40, /* ld hl,(LASTK) */
- 0xc9, /* ret */
- 0xff /* End of patch */
- };
-
- static const Z80Byte pause_hack[]=
- {
- 0xed, ED_PAUSE, /* (PAUSE) */
- 0x00, /* nop */
- 0xff /* End of patch */
- };
-
- int f;
-
- for(f=0;save[f]!=0xff;f++)
- {
- mem[ROM_SAVE+f]=save[f];
- }
-
- for(f=0;load[f]!=0xff;f++)
- {
- mem[ROM_LOAD+f]=load[f];
- }
-
- for(f=0;fast_hack[f]!=0xff;f++)
- {
- mem[0x4ca+f]=fast_hack[f];
- }
-
- for(f=0;kbd_hack[f]!=0xff;f++)
- {
- mem[0x2bb+f]=kbd_hack[f];
- }
-
- for(f=0;pause_hack[f]!=0xff;f++)
- {
- mem[0xf3a+f]=pause_hack[f];
- }
-
- /* Trust me, we have a ZX81... Honestly.
- */
- mem[0x21c]=0x00;
- mem[0x21d]=0x00;
-
- /* Remove HALTs as we don't do interrupts
- */
- mem[0x0079]=0;
- mem[0x02ec]=0;
-}
-
-static Z80Byte FromASCII(char c)
-{
- switch(c)
- {
- case '\'':
- case '"':
- return 11;
-
- case '(':
- return 16;
-
- case ')':
- return 17;
-
- case '-':
- return 22;
-
- case '*':
- return 23;
-
- case ',':
- return 26;
-
- case '.':
- return 27;
- }
-
- if (c>='0' && c<='9')
- return (c-'0')+28;
-
- if (c>='a' && c<='z')
- return (c-'a')+38;
-
- if (c>='A' && c<='Z')
- return (c-'A')+38;
-
- return 0;
-}
-
-
-/* Open a tape file the passed address
-*/
-static FILE *OpenTapeFile(Z80Word addr)
-{
- FILE *fp;
- char fn[MAX_FNAME_LEN];
- int f;
- int done;
-
- f=0;
- done=FALSE;
-
- while(f<(MAX_FNAME_LEN-3) && !done)
- {
- int ch;
-
- ch=mem[addr++];
-
- if (ch&0x80)
- {
- done=TRUE;
- ch&=0x7f;
- }
-
- switch(ch)
- {
- case 22:
- fn[f++]='-';
- break;
-
- case 27:
- fn[f++]='.';
-
- default:
- if (ch>=28 && ch<=37)
- {
- fn[f++]='0'+(ch-28);
- }
- else if (ch>=38 && ch<=63)
- {
- fn[f++]='A'+(ch-38);
- }
- break;
- }
- }
-
- fn[f++]='.';
- fn[f++]='P';
- fn[f]=0;
-
- if (!(fp=fopen(fn,"rb")))
- {
- char full_fn[MAX_FNAME_LEN+11]="\\ZX81SNAP\\";
-
- strcat(full_fn,fn);
- fp=fopen(full_fn,"rb");
- }
-
- return fp;
-}
-
-
-static void LoadInternalTape(Z80 *z80)
-{
- memcpy(mem+0x4009,tape_image,tape_len);
-}
-
-
-static void LoadExternalTape(FILE *tape, Z80 *z80)
-{
- int c;
- Z80Byte *a;
-
- a=mem+0x4009;
-
- while((c=getc(tape))!=EOF)
- {
- *a++=c;
- }
-}
-
-
-static void DrawScreen(Z80 *z80)
-{
- Z80Byte *scr=mem+WORD(DFILE);
- int x,y;
-
- x=0;
- y=0;
-
- while(y<TXT_H)
- {
- scr++;
- x=0;
-
- while((*scr!=118)&&(x<TXT_W))
- {
- Z80Byte ch = *scr++;
-
- if (ch&0x80)
- {
- screen[x+y*32]=(ch&0x3f)|0x40;
- }
- else
- {
- screen[x+y*32]=(ch&0x3f);
- }
-
- x++;
- }
-
- y++;
- }
-}
-
-
-static void DrawSnow(Z80 *z80)
-{
- uint16 *s;
- int f;
-
- s = screen;
-
- for(f=0;f<TXT_W*TXT_H;f++)
- {
- *s++=8;
- }
-}
-
-
-/* Perform ZX81 housekeeping functions like updating FRAMES and updating LASTK
-*/
-static void ZX81HouseKeeping(Z80 *z80)
-{
- static unsigned prev_lk1,prev_lk2;
- unsigned row;
- unsigned lastk1;
- unsigned lastk2;
-
- /* British ZX81
- */
- mem[MARGIN]=55;
-
- /* Update FRAMES
- */
- if (FRAME_TSTATES==SLOW_TSTATES)
- {
- Z80Word frame=PEEKW(FRAMES)&0x7fff;
-
- if (frame)
- {
- frame--;
- }
-
- POKEW(FRAMES,frame|0x8000);
- }
-
- if (!started)
- {
- prev_lk1=0;
- prev_lk2=0;
- return;
- }
-
- /* Update LASTK
- */
- lastk1=0;
- lastk2=0;
-
- for(row=0;row<8;row++)
- {
- unsigned b;
-
- b=(~matrix[row]&0x1f)<<1;
-
- if (row==0)
- {
- unsigned shift;
-
- shift=b&2;
- b&=~2;
- b|=(shift>>1);
- }
-
- if (b)
- {
- if (b>1)
- {
- lastk1|=(1<<row);
- }
-
- lastk2|=b;
- }
- }
-
- if (lastk1 && (lastk1!=prev_lk1 || lastk2!=prev_lk2))
- {
- mem[CDFLAG]|=1;
- }
- else
- {
- mem[CDFLAG]&=~1;
- }
-
- mem[LASTK1]=lastk1^0xff;
- mem[LASTK2]=lastk2^0xff;
-
- prev_lk1=lastk1;
- prev_lk2=lastk2;
-}
-
-
-static int CheckTimers(Z80 *z80, Z80Val val)
-{
- if (val>=FRAME_TSTATES)
- {
- Z80ResetCycles(z80,val-FRAME_TSTATES);
-
- if (started && ((mem[CDFLAG] & 0x80) || waitkey))
- {
- DrawScreen(z80);
- FRAME_TSTATES=SLOW_TSTATES;
- }
- else
- {
- DrawSnow(z80);
- FRAME_TSTATES=FAST_TSTATES;
- }
-
- /* Update FRAMES (if in SLOW) and scan the keyboard. This only happens
- once we've got to a decent point in the boot cycle (detected with
- a valid stack pointer).
- */
- if (z80->SP<0x8000)
- {
- ZX81HouseKeeping(z80);
- }
-
- swiWaitForVBlank();
-
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
-
-
-static int EDCallback(Z80 *z80, Z80Val data)
-{
- Z80Word pause;
-
- switch((Z80Byte)data)
- {
- case ED_SAVE:
- break;
-
- case ED_LOAD:
- /* Try and load the external file if a name given. Otherwise, we
- try the internal one. Some of this is slightly dodgy -- it was
- never intended for the emulator to be doing any GUI related
- nonsense (like the alerts) but simply emulating.
- */
- if (enable_filesystem && z80->DE.w<0x8000)
- {
- FILE *fp;
-
- if ((fp=OpenTapeFile(z80->DE.w)))
- {
- LoadExternalTape(fp,z80);
- fclose(fp);
- }
- else
- {
- GUI_Alert(FALSE,"Couldn't open tape");
- SK_DisplayKeyboard(BG_GFX_SUB);
- }
- }
- else
- {
- if (tape_image)
- {
- LoadInternalTape(z80);
- }
- else
- {
- GUI_Alert(FALSE,"No tape image selected");
- SK_DisplayKeyboard(BG_GFX_SUB);
- }
- }
-
- mem[CDFLAG]=0xc0;
- break;
-
- case ED_WAITKEY:
- waitkey=TRUE;
- started=TRUE;
- break;
-
- case ED_ENDWAITKEY:
- waitkey=FALSE;
- break;
-
- case ED_PAUSE:
- waitkey=TRUE;
-
- pause=z80->BC.w;
-
- while(pause-- && !(mem[CDFLAG]&1))
- {
- SoftKeyEvent ev;
-
- while (SK_GetEvent(&ev))
- {
- ZX81HandleKey(ev.key,ev.pressed);
- }
-
- CheckTimers(z80,FRAME_TSTATES);
- }
-
- waitkey=FALSE;
- break;
-
- default:
- break;
- }
-
- return TRUE;
-}
-
-
-/* ---------------------------------------- EXPORTED INTERFACES
-*/
-void ZX81Init(uint16 *vram, Z80 *z80)
-{
- Z80Word f;
-
- screen = vram;
-
- /* Load the ROM
- */
- memcpy(mem,zx81_bin,ROMLEN);
-
- /* Patch the ROM
- */
- RomPatch();
- Z80LodgeCallback(z80,eZ80_EDHook,EDCallback);
- Z80LodgeCallback(z80,eZ80_Instruction,CheckTimers);
-
- /* Mirror the ROM
- */
- memcpy(mem+ROMLEN,mem,ROMLEN);
-
-
- /* Memory size (16K)
- */
- RAMBOT=0x4000;
- RAMLEN=0x4000;
- RAMTOP=RAMBOT+RAMLEN;
-
- for(f=RAMBOT;f<=RAMTOP;f++)
- mem[f]=0;
-
- for(f=0;f<8;f++)
- matrix[f]=0x1f;
-}
-
-
-void ZX81HandleKey(SoftKey key, int is_pressed)
-{
- if (key<SK_CONFIG)
- {
- if (is_pressed)
- {
- matrix[key_matrix[key].row]&=~key_matrix[key].bit;
- }
- else
- {
- matrix[key_matrix[key].row]|=key_matrix[key].bit;
- }
- }
- else
- {
- /* TODO: Joysticks? */
- }
-}
-
-
-Z80Byte ZX81ReadMem(Z80 *z80, Z80Word addr)
-{
- /* Hopefully by simply returning RET for ULA reads we save a lot of
- ROM patching shenanigans.
- */
- if (addr>0x7fff)
- {
- return 0xc9;
- }
- else
- {
- return mem[addr];
- }
-}
-
-
-void ZX81WriteMem(Z80 *z80, Z80Word addr, Z80Byte val)
-{
- if (addr>=RAMBOT && addr<=RAMTOP)
- {
- mem[addr]=val;
- }
-}
-
-
-Z80Byte ZX81ReadPort(Z80 *z80, Z80Word port)
-{
- Z80Byte b=0;
-
- switch(port&0xff)
- {
- case 0xfe: /* 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;
- }
- break;
-
- default:
- break;
- }
-
- return b;
-}
-
-
-void ZX81WritePort(Z80 *z80, Z80Word port, Z80Byte val)
-{
- switch(port&0xff)
- {
- case 0xfd:
- break;
-
- case 0xfe:
- break;
- }
-}
-
-
-void ZX81Reset(Z80 *z80)
-{
- int f;
-
- for(f=0;f<8;f++)
- matrix[f]=0x1f;
-
- Z80Reset(z80);
- Z80ResetCycles(z80,0);
-
- started=FALSE;
-}
-
-
-void ZX81EnableFileSystem(int enable)
-{
- enable_filesystem=enable;
-}
-
-
-void ZX81SetTape(const Z80Byte *image, int len)
-{
- tape_image=image;
- tape_len=len;
-}
-
-
-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;
- }
-
- s = screen;
- f = 0;
-
- while(*p)
- {
- switch(*p)
- {
- case '\n':
- s+=32;
- f=0;
- break;
-
- case '%':
- inv^=0x40;
- break;
-
- default:
- s[f++]=FromASCII(*p)|inv;
- break;
- }
-
- p++;
- }
-}
-
-
-/* END OF FILE */