summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2003-12-23 23:33:02 +0000
committerIan C <ianc@noddybox.co.uk>2003-12-23 23:33:02 +0000
commit33dfea1c74749124379ef8052f0689577ebe68ff (patch)
tree6db163a5b8a17fe06da01ac13c707d25a3a342bc /src
parent15261bfe7390fb0d0ac40c9d4e20c3a86b5e3e33 (diff)
This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile200
-rw-r--r--src/config.c176
-rw-r--r--src/config.h70
-rw-r--r--src/exit.c56
-rw-r--r--src/exit.h39
-rw-r--r--src/font.h1101
-rw-r--r--src/gfx.c395
-rw-r--r--src/gfx.h143
-rw-r--r--src/gui.c210
-rw-r--r--src/gui.h50
-rw-r--r--src/main.c138
-rw-r--r--src/memmenu.c329
-rw-r--r--src/memmenu.h46
-rw-r--r--src/spec.c673
-rw-r--r--src/spec.h58
15 files changed, 3684 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..ed3c38e
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,200 @@
+# espec - ZX Spectrum emulator
+#
+# Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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
+#
+# -------------------------------------------------------------------------
+#
+# $Id: Makefile,v 1.1.1.1 2003-12-23 23:33:02 ianc Exp $
+#
+
+
+# This CFLAGS assumes that gcc is being used.
+# Simply comment out if not, and replace as needed.
+# Other CFLAGS lines *are* required.
+#
+CFLAGS = -g -Wall -Werror -pedantic -ansi
+
+TARGET = espec
+
+Z80LIB = z80/z80.a
+
+SOURCE = main.c \
+ spec.c \
+ config.c \
+ gfx.c \
+ gui.c \
+ memmenu.c \
+ exit.c
+
+OBJECTS = main.o \
+ spec.o \
+ config.o \
+ gfx.o \
+ gui.o \
+ memmenu.o \
+ exit.o
+
+CFLAGS += -Iz80 `sdl-config --cflags`
+
+LIBS = $(Z80LIB) `sdl-config --libs`
+
+
+$(TARGET): $(OBJECTS) $(Z80LIB)
+ $(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
+
+$(Z80LIB): z80/*.[ch]
+ cd z80; make ; cd ..
+
+clean:
+ rm -f $(TARGET) $(OBJECTS) core
+ cd z80; make clean; cd ..
+
+depend:
+ makedepend -- $(CFLAGS) -- $(SOURCE)
+ if test -e Makefile ; then rm -f Makefile.bak ; fi
+ cd z80; make depend ; cd ..
+
+# DO NOT DELETE THIS LINE -- make depend depends on it
+
+main.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h
+main.o: /usr/include/sys/_types.h /usr/include/machine/_types.h
+main.o: /usr/include/stdio.h /usr/local/include/SDL/SDL.h
+main.o: /usr/local/include/SDL/SDL_main.h /usr/local/include/SDL/SDL_types.h
+main.o: /usr/local/include/SDL/SDL_getenv.h
+main.o: /usr/local/include/SDL/SDL_error.h
+main.o: /usr/local/include/SDL/begin_code.h
+main.o: /usr/local/include/SDL/close_code.h
+main.o: /usr/local/include/SDL/SDL_rwops.h /usr/local/include/SDL/SDL_timer.h
+main.o: /usr/local/include/SDL/SDL_audio.h
+main.o: /usr/local/include/SDL/SDL_byteorder.h
+main.o: /usr/local/include/SDL/SDL_cdrom.h
+main.o: /usr/local/include/SDL/SDL_joystick.h
+main.o: /usr/local/include/SDL/SDL_events.h
+main.o: /usr/local/include/SDL/SDL_active.h
+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
+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: /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
+spec.o: /usr/local/include/SDL/close_code.h
+spec.o: /usr/local/include/SDL/SDL_rwops.h /usr/local/include/SDL/SDL_timer.h
+spec.o: /usr/local/include/SDL/SDL_audio.h
+spec.o: /usr/local/include/SDL/SDL_byteorder.h
+spec.o: /usr/local/include/SDL/SDL_cdrom.h
+spec.o: /usr/local/include/SDL/SDL_joystick.h
+spec.o: /usr/local/include/SDL/SDL_events.h
+spec.o: /usr/local/include/SDL/SDL_active.h
+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
+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
+config.o: exit.h config.h
+gfx.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h
+gfx.o: /usr/include/sys/_types.h /usr/include/machine/_types.h
+gfx.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h
+gfx.o: /usr/include/stdarg.h gfx.h /usr/local/include/SDL/SDL.h
+gfx.o: /usr/local/include/SDL/SDL_main.h /usr/local/include/SDL/SDL_types.h
+gfx.o: /usr/local/include/SDL/SDL_getenv.h /usr/local/include/SDL/SDL_error.h
+gfx.o: /usr/local/include/SDL/begin_code.h
+gfx.o: /usr/local/include/SDL/close_code.h /usr/local/include/SDL/SDL_rwops.h
+gfx.o: /usr/local/include/SDL/SDL_timer.h /usr/local/include/SDL/SDL_audio.h
+gfx.o: /usr/local/include/SDL/SDL_byteorder.h
+gfx.o: /usr/local/include/SDL/SDL_cdrom.h
+gfx.o: /usr/local/include/SDL/SDL_joystick.h
+gfx.o: /usr/local/include/SDL/SDL_events.h
+gfx.o: /usr/local/include/SDL/SDL_active.h
+gfx.o: /usr/local/include/SDL/SDL_keyboard.h
+gfx.o: /usr/local/include/SDL/SDL_keysym.h /usr/local/include/SDL/SDL_mouse.h
+gfx.o: /usr/local/include/SDL/SDL_video.h /usr/local/include/SDL/SDL_mutex.h
+gfx.o: /usr/local/include/SDL/SDL_quit.h /usr/local/include/SDL/SDL_version.h
+gfx.o: exit.h config.h font.h
+gui.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h
+gui.o: /usr/include/sys/_types.h /usr/include/machine/_types.h
+gui.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h
+gui.o: /usr/include/stdarg.h /usr/include/ctype.h /usr/include/runetype.h
+gui.o: gui.h /usr/local/include/SDL/SDL.h /usr/local/include/SDL/SDL_main.h
+gui.o: /usr/local/include/SDL/SDL_types.h /usr/local/include/SDL/SDL_getenv.h
+gui.o: /usr/local/include/SDL/SDL_error.h /usr/local/include/SDL/begin_code.h
+gui.o: /usr/local/include/SDL/close_code.h /usr/local/include/SDL/SDL_rwops.h
+gui.o: /usr/local/include/SDL/SDL_timer.h /usr/local/include/SDL/SDL_audio.h
+gui.o: /usr/local/include/SDL/SDL_byteorder.h
+gui.o: /usr/local/include/SDL/SDL_cdrom.h
+gui.o: /usr/local/include/SDL/SDL_joystick.h
+gui.o: /usr/local/include/SDL/SDL_events.h
+gui.o: /usr/local/include/SDL/SDL_active.h
+gui.o: /usr/local/include/SDL/SDL_keyboard.h
+gui.o: /usr/local/include/SDL/SDL_keysym.h /usr/local/include/SDL/SDL_mouse.h
+gui.o: /usr/local/include/SDL/SDL_video.h /usr/local/include/SDL/SDL_mutex.h
+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/local/include/SDL/SDL_types.h
+memmenu.o: /usr/local/include/SDL/SDL_getenv.h
+memmenu.o: /usr/local/include/SDL/SDL_error.h
+memmenu.o: /usr/local/include/SDL/begin_code.h
+memmenu.o: /usr/local/include/SDL/close_code.h
+memmenu.o: /usr/local/include/SDL/SDL_rwops.h /usr/include/stdio.h
+memmenu.o: /usr/local/include/SDL/SDL_timer.h
+memmenu.o: /usr/local/include/SDL/SDL_audio.h
+memmenu.o: /usr/local/include/SDL/SDL_byteorder.h
+memmenu.o: /usr/local/include/SDL/SDL_cdrom.h
+memmenu.o: /usr/local/include/SDL/SDL_joystick.h
+memmenu.o: /usr/local/include/SDL/SDL_events.h
+memmenu.o: /usr/local/include/SDL/SDL_active.h
+memmenu.o: /usr/local/include/SDL/SDL_keyboard.h
+memmenu.o: /usr/local/include/SDL/SDL_keysym.h
+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
+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
+exit.o: /usr/local/include/SDL/SDL_main.h /usr/local/include/SDL/SDL_types.h
+exit.o: /usr/local/include/SDL/SDL_getenv.h
+exit.o: /usr/local/include/SDL/SDL_error.h
+exit.o: /usr/local/include/SDL/begin_code.h
+exit.o: /usr/local/include/SDL/close_code.h
+exit.o: /usr/local/include/SDL/SDL_rwops.h /usr/include/stdio.h
+exit.o: /usr/local/include/SDL/SDL_timer.h /usr/local/include/SDL/SDL_audio.h
+exit.o: /usr/local/include/SDL/SDL_byteorder.h
+exit.o: /usr/local/include/SDL/SDL_cdrom.h
+exit.o: /usr/local/include/SDL/SDL_joystick.h
+exit.o: /usr/local/include/SDL/SDL_events.h
+exit.o: /usr/local/include/SDL/SDL_active.h
+exit.o: /usr/local/include/SDL/SDL_keyboard.h
+exit.o: /usr/local/include/SDL/SDL_keysym.h
+exit.o: /usr/local/include/SDL/SDL_mouse.h /usr/local/include/SDL/SDL_video.h
+exit.o: /usr/local/include/SDL/SDL_mutex.h /usr/local/include/SDL/SDL_quit.h
+exit.o: /usr/local/include/SDL/SDL_version.h
diff --git a/src/config.c b/src/config.c
new file mode 100644
index 0000000..4035d22
--- /dev/null
+++ b/src/config.c
@@ -0,0 +1,176 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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
+
+ -------------------------------------------------------------------------
+
+ Config file
+
+*/
+static const char ident[]="$Id$";
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "exit.h"
+#include "config.h"
+
+static const char ident_h[]=ESPEC_CONFIG_H;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+/* ---------------------------------------- CONFIG
+*/
+static char rompath[FILENAME_MAX]="./zx81.rom";
+static char tapedir[FILENAME_MAX]=".";
+static int fullscreen=FALSE;
+static int memsize=16;
+static int frames=50;
+static int scale=1;
+static int trace=0;
+
+static const struct
+{
+ const char *name;
+ void *var;
+ int is_int;
+} config[]= {
+ {"rompath", rompath, FALSE},
+ {"tapedir", tapedir, FALSE},
+ {"fullscreen", &fullscreen, TRUE},
+ {"memsize", &memsize, TRUE},
+ {"frames", &frames, TRUE},
+ {"scale", &scale, TRUE},
+ {"trace", &trace, TRUE},
+ {NULL, NULL, FALSE}
+ };
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static void Parse(FILE *fp)
+{
+ char buff[1024];
+
+ while(fgets(buff,sizeof buff,fp))
+ {
+ size_t l;
+
+ l=strlen(buff);
+
+ if (buff[l-1]=='\n')
+ buff[--l]=0;
+
+ if (l>0 && buff[0]!='#')
+ {
+ char *t1=NULL;
+ char *t2=NULL;
+
+ t1=strtok(buff,"\t");
+ t2=strtok(NULL,"\t");
+
+ if (t2)
+ {
+ int f;
+
+ for(f=0;config[f].name;f++)
+ {
+ if (strcmp(config[f].name,t1)==0)
+ {
+ if (config[f].is_int)
+ {
+ int *i;
+
+ i=config[f].var;
+ *i=atoi(t2);
+ }
+ else
+ {
+ char *p;
+
+ p=config[f].var;
+ strcpy(p,t2);
+ }
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr,"Ignored bad config: %s %s\n",t1,t2 ? t2:"");
+ }
+ }
+ }
+}
+
+
+/* ---------------------------------------- EXPORTED INTERFACES
+*/
+void ConfigRead(void)
+{
+ FILE *fp;
+ char path[FILENAME_MAX]={0};
+
+ if (getenv("HOME"))
+ strcpy(path,getenv("HOME"));
+
+ strcat(path,"/.ezx81");
+
+ if ((fp=fopen(path,"r")))
+ {
+ Parse(fp);
+ fclose(fp);
+ }
+}
+
+
+int IConfig(IConfigVar v)
+{
+ static const int *vars[]=
+ {
+ &fullscreen,
+ &memsize,
+ &frames,
+ &scale,
+ &trace
+ };
+
+ return *vars[v];
+}
+
+
+const char *SConfig(SConfigVar v)
+{
+ static const char *vars[]=
+ {
+ rompath,
+ tapedir
+ };
+
+ return vars[v];
+}
+
+
+/* END OF FILE */
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..94dad15
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,70 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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
+
+ -------------------------------------------------------------------------
+
+ Config file
+
+*/
+
+#ifndef ESPEC_CONFIG_H
+#define ESPEC_CONFIG_H "$Id$"
+
+
+/* Integer settings
+*/
+typedef enum
+{
+ CONF_FULLSCREEN,
+ CONF_MEMSIZE,
+ CONF_FRAMES_PER_SEC,
+ CONF_SCALE,
+ CONF_TRACE
+} IConfigVar;
+
+
+/* String settings
+*/
+typedef enum
+{
+ CONF_ROMFILE,
+ CONF_TAPEDIR
+} SConfigVar;
+
+
+/* Read config file
+*/
+void ConfigRead(void);
+
+
+/* Get integer setting
+*/
+int IConfig(IConfigVar v);
+
+
+/* Get string setting
+*/
+const char *SConfig(SConfigVar v);
+
+
+#endif
+
+
+/* END OF FILE */
diff --git a/src/exit.c b/src/exit.c
new file mode 100644
index 0000000..254acc3
--- /dev/null
+++ b/src/exit.c
@@ -0,0 +1,56 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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 a common error exit point
+
+*/
+static const char ident[]="$Id$";
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include "exit.h"
+
+#include <SDL.h>
+
+static const char ident_h[]=ESPEC_EXIT_H;
+
+
+/* ---------------------------------------- EXPORTED INTERFACES
+*/
+void Exit(const char *format,...)
+{
+ va_list va;
+
+ if (SDL_WasInit(SDL_INIT_EVERYTHING))
+ {
+ SDL_Quit();
+ }
+
+ va_start(va,format);
+ vfprintf(stderr,format,va);
+ va_end(va);
+
+ exit(EXIT_FAILURE);
+}
+
+
+/* END OF FILE */
diff --git a/src/exit.h b/src/exit.h
new file mode 100644
index 0000000..084fc78
--- /dev/null
+++ b/src/exit.h
@@ -0,0 +1,39 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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 a common error exit point
+
+*/
+
+#ifndef ESPEC_EXIT_H
+#define ESPEC_EXIT_H "$Id$"
+
+
+/* Exit
+*/
+void Exit(const char *format,...);
+
+
+#endif
+
+
+/* END OF FILE */
diff --git a/src/font.h b/src/font.h
new file mode 100644
index 0000000..f4a6925
--- /dev/null
+++ b/src/font.h
@@ -0,0 +1,1101 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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
+
+ -------------------------------------------------------------------------
+
+ Internal font for gfx routines
+
+*/
+
+#ifndef ESPEC_FONT_H
+#define ESPEC_FONT_H "$Id$"
+
+typedef unsigned char FontChar[64];
+
+#define NULLCHARDEF {0}
+
+
+static const FontChar font[128]=
+{
+ NULLCHARDEF, /* 00 */
+
+ { /* 01 FONT_UP_ARROW */
+ 0,0,0,1,1,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,1,1,1,1,1,0,
+ 1,1,0,1,1,0,1,1,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ },
+ { /* 02 FONT_DOWN_ARROW */
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 1,1,0,1,1,0,1,1,
+ 0,1,1,1,1,1,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,1,1,0,0,0,
+ },
+ { /* 03 FONT_LEFT_ARROW */
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,1,0,0,0,0,
+ 0,1,1,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,
+ 0,1,1,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ },
+ { /* 04 FONT_RIGHT_ARROW */
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,1,0,0,
+ 0,0,0,0,0,1,1,0,
+ 1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,1,1,0,
+ 0,0,0,0,1,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ },
+ { /* 05 FONT_TICK */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,
+ 0,0,0,0,0,0,1,1,
+ 0,0,0,0,0,1,1,0,
+ 1,1,0,0,1,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,0,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 06 FONT_CROSS */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,0,0,0,1,1,
+ 0,0,1,1,0,1,1,0,
+ 0,0,0,1,1,1,0,0,
+ 0,0,0,1,1,1,0,0,
+ 0,0,1,1,0,1,1,0,
+ 0,1,1,0,0,0,1,1,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 07 FONT_CURSOR */
+ 1,1,1,1,1,1,1,1,
+ 1,0,1,1,1,1,1,1,
+ 1,0,1,1,1,1,1,1,
+ 1,0,1,1,1,1,1,1,
+ 1,0,1,1,1,1,1,1,
+ 1,0,1,1,1,1,1,1,
+ 1,0,0,0,0,0,0,1,
+ 1,1,1,1,1,1,1,1,
+ },
+ { /* 08 FONT_COPYRIGHT */
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 1,0,0,1,1,0,0,1,
+ 1,0,1,0,0,0,0,1,
+ 1,0,1,0,0,0,0,1,
+ 1,0,0,1,1,0,0,1,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ },
+
+ NULLCHARDEF, /* 09 */
+ NULLCHARDEF, /* 0a */
+ NULLCHARDEF, /* 0b */
+ NULLCHARDEF, /* 0c */
+ NULLCHARDEF, /* 0d */
+ NULLCHARDEF, /* 0e */
+ NULLCHARDEF, /* 0f */
+ NULLCHARDEF, /* 10 */
+ NULLCHARDEF, /* 11 */
+ NULLCHARDEF, /* 12 */
+ NULLCHARDEF, /* 13 */
+ NULLCHARDEF, /* 14 */
+ NULLCHARDEF, /* 15 */
+ NULLCHARDEF, /* 16 */
+ NULLCHARDEF, /* 17 */
+ NULLCHARDEF, /* 18 */
+ NULLCHARDEF, /* 19 */
+ NULLCHARDEF, /* 1a */
+ NULLCHARDEF, /* 1b */
+ NULLCHARDEF, /* 1c */
+ NULLCHARDEF, /* 1d */
+ NULLCHARDEF, /* 1e */
+ NULLCHARDEF, /* 1f */
+
+ { /* 20 ' ' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 21 '!' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 22 '"' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 23 '#' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 24 '$' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,1,0,1,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,1,0,0,0,
+ },
+ { /* 25 '%' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,0,0,0,1,0,
+ 0,1,1,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,1,1,0,
+ 0,1,0,0,0,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 26 '&' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,1,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 27 ''' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 28 '(' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 29 ')' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 2a '*' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 2b '+' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 2c ',' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ },
+ { /* 2d '-' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 2e '.' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 2f '/' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 30 '0' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,1,1,0,
+ 0,1,0,0,1,0,1,0,
+ 0,1,0,1,0,0,1,0,
+ 0,1,1,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 31 '1' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 32 '2' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 33 '3' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,1,1,0,0,
+ 0,0,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 34 '4' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 35 '5' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 36 '6' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 37 '7' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 38 '8' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 39 '9' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 3a ':' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 3b ';' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ },
+ { /* 3c '<' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 3d '=' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 3e '>' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 3f '?' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 40 '@' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,1,0,1,0,
+ 0,1,0,1,0,1,1,0,
+ 0,1,0,1,1,1,1,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 41 'A' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,1,1,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 42 'B' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 43 'C' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 44 'D' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 45 'E' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 46 'F' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 47 'G' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,1,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 48 'H' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,1,1,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 49 'I' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 4a 'J' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 4b 'K' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,1,1,0,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 4c 'L' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 4d 'M' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,0,0,1,1,0,
+ 0,1,0,1,1,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 4e 'N' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,0,0,0,1,0,
+ 0,1,0,1,0,0,1,0,
+ 0,1,0,0,1,0,1,0,
+ 0,1,0,0,0,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 4f 'O' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 50 'P' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,1,1,1,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 51 'Q' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,1,0,0,1,0,
+ 0,1,0,0,1,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 52 'R' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,1,1,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 53 'S' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 54 'T' */
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 55 'U' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 56 'V' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 57 'W' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,1,1,0,1,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 58 'X' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 59 'Y' */
+ 0,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 5a 'Z' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 5b '[' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 5c '\' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 5d ']' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 5e '^' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,1,0,1,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 5f '_' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,
+ },
+ { /* 60 '`' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,1,0,0,
+ 0,0,1,0,0,0,1,0,
+ 0,1,1,1,1,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 61 'a' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 62 'b' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,1,0,0,0,1,0,
+ 0,0,1,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 63 'c' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,1,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 64 'd' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 65 'e' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 66 'f' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 67 'g' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ },
+ { /* 68 'h' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 69 'i' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 6a 'j' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,0,1,1,0,0,0,
+ },
+ { /* 6b 'k' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,1,0,0,0,0,
+ 0,0,1,1,0,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 6c 'l' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 6d 'm' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,0,1,0,0,0,
+ 0,1,0,1,0,1,0,0,
+ 0,1,0,1,0,1,0,0,
+ 0,1,0,1,0,1,0,0,
+ 0,1,0,1,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 6e 'n' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 6f 'o' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 70 'p' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ },
+ { /* 71 'q' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,1,0,
+ },
+ { /* 72 'r' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,1,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 73 's' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 74 't' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 75 'u' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 76 'v' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 77 'w' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,1,0,1,0,0,
+ 0,1,0,1,0,1,0,0,
+ 0,1,0,1,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 78 'x' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 79 'y' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ },
+ { /* 7a 'z' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 7b '{' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,1,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 7c '|' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 7d '}' */
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,1,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ { /* 7e '~' */
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ },
+ NULLCHARDEF, /* 7f */
+};
+
+
+#endif
+
+
+/* END OF FILE */
diff --git a/src/gfx.c b/src/gfx.c
new file mode 100644
index 0000000..a77c496
--- /dev/null
+++ b/src/gfx.c
@@ -0,0 +1,395 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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
+
+ -------------------------------------------------------------------------
+
+ Wrapper to SDL
+
+*/
+static const char ident[]="$Id$";
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "gfx.h"
+#include "exit.h"
+#include "config.h"
+
+#include "font.h"
+
+static const char ident_h[]=ESPEC_GFX_H;
+static const char ident_fh[]=ESPEC_FONT_H;
+
+
+/* ---------------------------------------- MACROS
+*/
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define SCR_W 320
+#define SCR_H 200
+
+#define LOCK do \
+ { \
+ if (SDL_MUSTLOCK(surface)) \
+ if (SDL_LockSurface(surface)<0) \
+ Exit("Failed to lock surface: %s\n", \
+ SDL_GetError()); \
+ } while(0)
+
+#define UNLOCK do \
+ { \
+ if (SDL_MUSTLOCK(surface)) \
+ SDL_UnlockSurface(surface); \
+ } while(0)
+
+
+/* ---------------------------------------- STATICS
+*/
+static SDL_Surface *surface;
+static Uint32 ticks;
+static Uint32 frame;
+static int scale;
+
+static void (*putpixel)(int x, int y, Uint32 col);
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+
+/* Taken from SDL documentation
+*/
+static void normal_putpixel(int x, int y, Uint32 pixel)
+{
+ int bpp;
+ Uint8 *p;
+
+ bpp=surface->format->BytesPerPixel;
+ p=(Uint8 *)surface->pixels+y*surface->pitch+x*bpp;
+
+ switch(bpp)
+ {
+ case 1:
+ *p=pixel;
+ break;
+
+ case 2:
+ *(Uint16 *)p=pixel;
+ break;
+
+ case 3:
+ if(SDL_BYTEORDER==SDL_BIG_ENDIAN)
+ {
+ p[0]=(pixel>>16)&0xff;
+ p[1]=(pixel>>8)&0xff;
+ p[2]=pixel&0xff;
+ } else
+ {
+ p[0]=pixel&0xff;
+ p[1]=(pixel>>8)&0xff;
+ p[2]=(pixel>>16)&0xff;
+ }
+ break;
+
+ case 4:
+ *(Uint32 *)p=pixel;
+ break;
+ }
+}
+
+
+static void scale_putpixel(int x, int y, Uint32 pixel)
+{
+ int sx,sy;
+
+ x*=scale;
+ y*=scale;
+
+ for(sx=0;sx<scale;sx++)
+ for(sy=0;sy<scale;sy++)
+ normal_putpixel(x+sx,y+sy,pixel);
+}
+
+
+static void DoHLine(int x1, int x2, int y, Uint32 col)
+{
+ for(;x1<=x2;x1++)
+ putpixel(x1,y,col);
+}
+
+
+static void DoVLine(int x, int y1, int y2, Uint32 col)
+{
+ for(;y1<=y2;y1++)
+ putpixel(x,y1,col);
+}
+
+
+/* ---------------------------------------- EXPORTED INTERFACES
+*/
+void GFXInit(void)
+{
+ if (IConfig(CONF_FULLSCREEN))
+ scale=1;
+ else
+ scale=IConfig(CONF_SCALE);
+
+ if (scale<0)
+ scale=1;
+
+ if (scale>1)
+ putpixel=scale_putpixel;
+ else
+ putpixel=normal_putpixel;
+
+ 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 (!(surface=SDL_SetVideoMode(SCR_W*scale,
+ SCR_H*scale,
+ 0,
+ IConfig(CONF_FULLSCREEN) ?
+ SDL_FULLSCREEN : 0)))
+ {
+ Exit("Failed to open video: %s\n",SDL_GetError());
+ }
+
+ SDL_ShowCursor(SDL_DISABLE);
+ SDL_WM_SetCaption("eSPEC","eSPEC");
+}
+
+
+SDL_Surface *GFXGetSurface(void)
+{
+ return surface;
+}
+
+
+Uint32 GFXRGB(Uint8 r, Uint8 g, Uint8 b)
+{
+ return SDL_MapRGB(surface->format,r,g,b);
+}
+
+
+void GFXClear(Uint32 col)
+{
+ SDL_FillRect(surface,NULL,col);
+}
+
+
+void GFXStartFrame(void)
+{
+ ticks=SDL_GetTicks();
+}
+
+
+void GFXEndFrame(int delay)
+{
+ SDL_UpdateRect(surface,0,0,0,0);
+
+ if (delay)
+ {
+ Uint32 diff;
+
+ diff=SDL_GetTicks()-ticks;
+
+ if (diff<frame)
+ SDL_Delay(frame-diff);
+ }
+}
+
+
+void GFXKeyRepeat(int repeat)
+{
+ if (repeat)
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
+ SDL_DEFAULT_REPEAT_INTERVAL);
+ else
+ SDL_EnableKeyRepeat(0,0);
+}
+
+
+SDL_Event *GFXGetKey(void)
+{
+ static SDL_Event e;
+
+ while(SDL_PollEvent(&e))
+ {
+ if (e.type==SDL_KEYUP || e.type==SDL_KEYDOWN)
+ return &e;
+ }
+
+ return NULL;
+}
+
+
+SDL_Event *GFXWaitKey(void)
+{
+ static SDL_Event e;
+
+ do
+ {
+ SDL_WaitEvent(&e);
+ } while (e.type!=SDL_KEYDOWN);
+
+ return &e;
+}
+
+
+void GFXPlot(int x, int y, Uint32 col)
+{
+ LOCK;
+
+ putpixel(x,y,col);
+
+ UNLOCK;
+}
+
+
+void GFXRect(int x, int y, int w, int h, Uint32 col, int solid)
+{
+ LOCK;
+
+ if (solid)
+ {
+ SDL_Rect r;
+
+ r.x=x*scale;
+ r.y=y*scale;
+ r.w=w*scale;
+ r.h=h*scale;
+
+ SDL_FillRect(surface,&r,col);
+ }
+ else
+ {
+ DoHLine(x,x+w-1,y,col);
+ DoHLine(x,x+w-1,y+h-1,col);
+ DoVLine(x,y,y+h-1,col);
+ DoVLine(x+w-1,y,y+h-1,col);
+ }
+
+ UNLOCK;
+}
+
+
+void GFXHLine(int x1, int x2, int y, Uint32 col)
+{
+ LOCK;
+ DoHLine(x1,x2,y,col);
+ UNLOCK;
+}
+
+
+void GFXVLine(int x, int y1, int y2, Uint32 col)
+{
+ LOCK;
+ DoVLine(x,y1,y2,col);
+ UNLOCK;
+}
+
+
+void GFXPrint(int x, int y, Uint32 col, const char *format, ...)
+{
+ char buff[257];
+ va_list va;
+ char *p;
+ int sx,sy;
+
+ va_start(va,format);
+ vsprintf(buff,format,va);
+ va_end(va);
+
+ p=buff;
+
+ LOCK;
+
+ while(*p)
+ {
+ for(sy=0;sy<8;sy++)
+ {
+ if (y+sy<SCR_H && x<SCR_W)
+ {
+ for(sx=0;sx<8;sx++)
+ {
+ if (font[(int)*p][sx+sy*8] && x+sx<SCR_W)
+ putpixel(x+sx,y+sy,col);
+ }
+ }
+ }
+
+ p++;
+ x+=8;
+ }
+
+ UNLOCK;
+}
+
+
+void GFXPrintPaper(int x, int y, Uint32 col, Uint32 paper,
+ const char *format, ...)
+{
+ char buff[257];
+ va_list va;
+ char *p;
+ int sx,sy;
+
+ va_start(va,format);
+ vsprintf(buff,format,va);
+ va_end(va);
+
+ p=buff;
+
+ LOCK;
+
+ while(*p)
+ {
+ for(sy=0;sy<8;sy++)
+ {
+ if (y+sy<SCR_H && x<SCR_W)
+ {
+ for(sx=0;sx<8;sx++)
+ {
+ if (font[(int)*p][sx+sy*8] && x+sx<SCR_W)
+ putpixel(x+sx,y+sy,col);
+ else
+ putpixel(x+sx,y+sy,paper);
+ }
+ }
+ }
+
+ p++;
+ x+=8;
+ }
+
+ UNLOCK;
+}
+
+
+/* END OF FILE */
diff --git a/src/gfx.h b/src/gfx.h
new file mode 100644
index 0000000..baa19d2
--- /dev/null
+++ b/src/gfx.h
@@ -0,0 +1,143 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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
+
+ -------------------------------------------------------------------------
+
+ Wrapper to SDL
+
+*/
+
+#ifndef ESPEC_GFX_H
+#define ESPEC_GFX_H "$Id$"
+
+#include "SDL.h"
+
+
+/* ---------------------------------------- CONSTANTS
+*/
+#define FONT_UP_ARROW '\001'
+#define FONT_DOWN_ARROW '\002'
+#define FONT_LEFT_ARROW '\003'
+#define FONT_RIGHT_ARROW '\004'
+#define FONT_TICK '\005'
+#define FONT_CROSS '\006'
+#define FONT_CURSOR '\007'
+#define FONT_COPYRIGHT '\010'
+
+
+/* ---------------------------------------- INTERFACES
+*/
+
+/* Initialise
+*/
+void GFXInit(void);
+
+
+/* Get the SDL_Surface for the screen
+*/
+SDL_Surface *GFXGetSurface(void);
+
+
+/* Get the pixel value for a colour
+*/
+Uint32 GFXRGB(Uint8 r, Uint8 g, Uint8 b);
+
+
+/* Clear the screen
+*/
+void GFXClear(Uint32 col);
+
+
+/* Indicate a frame is starting
+*/
+void GFXStartFrame(void);
+
+
+/* Indicate a frame is done and refreshes the screen
+ If delay is TRUE, sleeps to implement the frames_per_sec config.
+ It's safe to call this multiple times without a matching GFXStartFrame().
+*/
+void GFXEndFrame(int delay);
+
+
+/* Set key repeat
+*/
+void GFXKeyRepeat(int repeat);
+
+
+/* Suck out keyboard events. Returns NULL if no more keyboard events
+*/
+SDL_Event *GFXGetKey(void);
+
+
+/* Wait for a keypress (key up event)
+*/
+SDL_Event *GFXWaitKey(void);
+
+
+/*
+ Note that no bound checking (except for GFXPrint()) is done - it is the
+ callers responsibility to plot onscreen.
+*/
+
+/* Plot a point
+*/
+void GFXPlot(int x, int y, Uint32 col);
+
+
+/* Draw a rectangle
+*/
+void GFXRect(int x, int y, int w, int h, Uint32 col, int solid);
+
+
+/* Draw an horizontal line
+*/
+void GFXHLine(int x1, int x2, int y, Uint32 col);
+
+
+/* Draw a vertical line
+*/
+void GFXVLine(int x, int y1, int y2, Uint32 col);
+
+
+/* Draws text using an internal 8x8 monspaced font. The only supported
+ characters are 32-126 and the special FONT_xxx characters defined
+ above. The routine assumes the environment operates with ASCII.
+
+ The co-ord given is the top left of the first character, and characters
+ are drawn transparently.
+
+ Causes undefined behaviour if the generated string from the printf
+ format is longer than 256 characters.
+*/
+void GFXPrint(int x, int y, Uint32 col, const char *format, ...);
+
+
+/* As above, but draws text using the supplied background colour, rather
+ than transparently.
+*/
+void GFXPrintPaper(int x, int y, Uint32 col, Uint32 paper,
+ const char *format, ...);
+
+
+#endif
+
+
+/* END OF FILE */
diff --git a/src/gui.c b/src/gui.c
new file mode 100644
index 0000000..3a4b031
--- /dev/null
+++ b/src/gui.c
@@ -0,0 +1,210 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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
+
+ -------------------------------------------------------------------------
+
+ Basic GUI routines
+
+*/
+static const char ident[]="$Id$";
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include "gui.h"
+#include "gfx.h"
+#include "exit.h"
+
+static const char ident_h[]=ESPEC_GUI_H;
+
+
+/* ---------------------------------------- MACROS
+*/
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* Must match gfx.c
+*/
+#define SCR_W 320
+#define SCR_H 200
+
+/* ---------------------------------------- STATICS
+*/
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static void *Malloc(size_t size)
+{
+ void *p=malloc(size);
+
+ if (!p)
+ Exit("malloc failed for %lu bytes\n",(unsigned long)size);
+
+ return p;
+}
+
+
+static void Centre(const char *p, int y, int r, int g, int b)
+{
+ GFXPrint((SCR_W-strlen(p)*8)/2,y,GFXRGB(r,g,b),"%s",p);
+}
+
+
+/* ---------------------------------------- EXPORTED INTERFACES
+*/
+void GUIMessage(const char *title, const char *format,...)
+{
+ char buff[1025];
+ va_list va;
+ char *p;
+ int no;
+ int f;
+ char **line;
+ int width;
+ int height;
+ int x,y;
+
+ va_start(va,format);
+ vsprintf(buff,format,va);
+ va_end(va);
+
+ p=buff;
+ no=1;
+
+ while(*p)
+ {
+ if (*p=='\n')
+ no++;
+
+ p++;
+ }
+
+ line=Malloc(sizeof *line * no);
+
+ line[0]=strtok(buff,"\n");
+ width=strlen(line[0]);
+
+ for(f=1;f<no;f++)
+ {
+ line[f]=strtok(NULL,"\n");
+
+ if (strlen(line[f])>width)
+ width=strlen(line[f]);
+ }
+
+ width=(width*8)+16;
+ height=(no+3)*10;
+
+ if (width>(SCR_W-10))
+ width=SCR_W-10;
+
+ if (height>(SCR_H-10))
+ height=SCR_H-10;
+
+ y=(SCR_H-height)/2;
+ x=(SCR_W-width)/2;
+
+ GFXRect(x-1,y-1,
+ width+2,height+2,
+ GFXRGB(255,255,255),FALSE);
+
+ GFXRect(x,y,
+ width,height,
+ GFXRGB(0,0,0),TRUE);
+
+ Centre(title,y+2,255,255,255);
+ GFXHLine(x+2,x+width-4,y+10,GFXRGB(255,255,255));
+
+ for(f=0;f<no;f++)
+ Centre(line[f],y+5+10*(f+1),200,200,200);
+
+ Centre("Press a key",y+height-10,255,0,0);
+
+ GFXEndFrame(FALSE);
+
+ GFXWaitKey();
+
+ free(line);
+}
+
+
+const char *GUIInputString(const char *prompt, const char *orig)
+{
+ static const int y_pos=SCR_H-8;
+ static char buff[41];
+ size_t len;
+ int done=FALSE;
+ SDL_Event *e;
+
+ buff[0]=0;
+ strncat(buff,orig,40);
+ len=strlen(buff);
+
+ while(!done)
+ {
+ GFXRect(0,y_pos,SCR_W,8,GFXRGB(0,0,0),TRUE);
+ GFXPrint(0,y_pos,GFXRGB(255,255,255),"%s %s%c",prompt,buff,FONT_CURSOR);
+ GFXEndFrame(FALSE);
+
+ e=GFXWaitKey();
+
+ switch(e->key.keysym.sym)
+ {
+ case SDLK_RETURN:
+ case SDLK_KP_ENTER:
+ done=TRUE;
+ break;
+
+ case SDLK_ESCAPE:
+ buff[0]=0;
+ len=0;
+ break;
+
+ case SDLK_BACKSPACE:
+ case SDLK_DELETE:
+ if (len)
+ buff[--len]=0;
+
+ break;
+
+ default:
+ if (len<40 && isprint(e->key.keysym.sym))
+ {
+ buff[len++]=(char)e->key.keysym.sym;
+ buff[len]=0;
+ }
+ break;
+ }
+ }
+
+ return buff;
+}
+
+
+/* END OF FILE */
diff --git a/src/gui.h b/src/gui.h
new file mode 100644
index 0000000..6d2fcb9
--- /dev/null
+++ b/src/gui.h
@@ -0,0 +1,50 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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
+
+ -------------------------------------------------------------------------
+
+ Basic GUI routines
+
+*/
+
+#ifndef ESPEC_GUI_H
+#define ESPEC_GUI_H "$Id$"
+
+#include "SDL.h"
+
+
+/* ---------------------------------------- INTERFACES
+*/
+
+/* Display a simple message box. A message of longer than 1024 bytes causes
+ undefined behaviour. Newlines cause a line break.
+*/
+void GUIMessage(const char *title, const char *format,...);
+
+
+/* Enter a string, max 40 characters
+*/
+const char *GUIInputString(const char *prompt, const char *orig);
+
+
+#endif
+
+
+/* END OF FILE */
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..e69eb77
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,138 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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
+
+ -------------------------------------------------------------------------
+
+*/
+static const char id[]="$Id$";
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "SDL.h"
+
+#include "z80.h"
+#include "spec.h"
+#include "gfx.h"
+#include "gui.h"
+#include "memmenu.h"
+#include "config.h"
+#include "exit.h"
+
+
+/* ---------------------------------------- MACROS
+*/
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+/* ---------------------------------------- STATICS
+*/
+static Uint32 white;
+static Uint32 black;
+static Uint32 grey;
+
+
+/* ---------------------------------------- PROTOS
+*/
+
+
+/* ---------------------------------------- MAIN
+*/
+int main(int argc, char *argv[])
+{
+ Z80 *z80;
+ SDL_Event *e;
+ int quit;
+ int trace;
+
+ ConfigRead();
+
+ trace=IConfig(CONF_TRACE);
+
+ z80=Z80Init(SPECWriteMem,
+ SPECReadMem,
+ SPECWritePort,
+ SPECReadPort,
+ SPECReadForDisassem,
+ NULL);
+
+ GFXInit();
+
+ SPECInit(z80);
+
+ white=GFXRGB(255,255,255);
+ grey=GFXRGB(128,128,128);
+ black=GFXRGB(0,0,0);
+
+ quit=FALSE;
+
+ while(!quit)
+ {
+ Z80SingleStep(z80);
+
+ if (trace)
+ {
+ DisplayState(z80);
+ GFXEndFrame(FALSE);
+ }
+
+ while((e=GFXGetKey()))
+ {
+ switch (e->key.keysym.sym)
+ {
+ case SDLK_ESCAPE:
+ if (e->key.state==SDL_RELEASED)
+ quit=TRUE;
+ break;
+
+ case SDLK_F11:
+ if (e->key.state==SDL_RELEASED)
+ MemoryMenu(z80);
+ break;
+
+ case SDLK_F12:
+ if (e->key.state==SDL_RELEASED)
+ trace=!trace;
+ break;
+
+ default:
+ SPECKeyEvent(e);
+ break;
+ }
+ }
+ }
+
+ SDL_Quit();
+
+ return EXIT_SUCCESS;
+}
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+
+
+/* END OF FILE */
diff --git a/src/memmenu.c b/src/memmenu.c
new file mode 100644
index 0000000..2badf65
--- /dev/null
+++ b/src/memmenu.c
@@ -0,0 +1,329 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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 a common error exit point
+
+*/
+static const char ident[]="$Id$";
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "memmenu.h"
+#include "spec.h"
+#include "gfx.h"
+#include "gui.h"
+
+#include <SDL.h>
+
+static const char ident_h[]=ESPEC_MEMMENU_H;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define WHITE GFXRGB(255,255,255)
+#define BLACK GFXRGB(0,0,0)
+#define RED GFXRGB(255,100,100)
+#define GREEN GFXRGB(100,255,100)
+#define BLUE GFXRGB(100,100,255)
+
+#define MENU
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static void Centre(const char *p, int y, Uint32 col)
+{
+ GFXPrint((320-strlen(p)*8)/2,y,col,"%s",p);
+}
+
+
+static void DisplayMenu(void)
+{
+ static const char *menu[]=
+ {
+ "1. Disassemble/Hex dump",
+ "2. Return ",
+ NULL
+ };
+
+ int f;
+
+ GFXClear(BLACK);
+
+ Centre("MEMORY MENU",0,WHITE);
+ Centre("Select an option",8,WHITE);
+
+ f=0;
+
+ while(menu[f])
+ {
+ Centre(menu[f],20+f*10,WHITE);
+ f++;
+ }
+}
+
+
+static const char *FlagString(Z80Byte flag)
+{
+ static char s[]="76543210";
+ static char c[]="SZ5H3PNC";
+ int f;
+
+ for(f=0;f<8;f++)
+ if (flag&(1<<(7-f)))
+ s[f]=c[f];
+ else
+ s[f]='-';
+
+ return s;
+}
+
+
+static int EnterAddress(Z80Word *w)
+{
+ unsigned long ul;
+ const char *p;
+
+ p=GUIInputString("Address?","");
+
+ if (*p)
+ {
+ ul=strtoul(p,NULL,0);
+
+ if (ul>0xffff)
+ {
+ GUIMessage("ERROR","Bad address");
+ }
+ else
+ {
+ *w=(Z80Word)ul;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+static void DoDisassem(Z80 *z80, const Z80State *s)
+{
+ static int hexmode=FALSE;
+ Z80Word pc=s->PC;
+ int quit=FALSE;
+
+ while(!quit)
+ {
+ SDL_Event *e;
+ Z80Word curr;
+ Z80Word next;
+ int f;
+
+ GFXClear(BLACK);
+
+ Centre("Press F1 for help",0,RED);
+
+ curr=pc;
+
+ for(f=0;f<21;f++)
+ {
+ char s[80];
+ char *p;
+ int y;
+
+ y=16+f*8;
+
+ GFXPrint(0,y,GREEN,"%4.4x",curr);
+
+ if (hexmode)
+ {
+ int n;
+
+ for(n=0;n<8;n++)
+ {
+ GFXPrint(40+n*24,y,WHITE,"%2.2x",
+ (int)SPECReadForDisassem(z80,curr));
+
+ curr++;
+ }
+ }
+ else
+ {
+ strcpy(s,Z80Disassemble(z80,&curr));
+
+ p=strtok(s,";");
+ GFXPrint(40,y,WHITE,"%s",p);
+ }
+
+ if (f==0)
+ next=curr;
+ }
+
+ GFXEndFrame(FALSE);
+
+ e=GFXWaitKey();
+
+ switch(e->key.keysym.sym)
+ {
+ case SDLK_F1:
+ GUIMessage
+ ("DISASSEMBLY HELP","%s",
+ "ESC - Exit\n"
+ "H - Switch between disassembly/hex\n"
+ "Enter - Enter address to display\n"
+ "Cursor Up - Prev op\n"
+ "Cursor Down - Next op\n"
+ "Page Up - Move back a page\n"
+ "Page Down - Move forward a page\n"
+ "Cursor Left - Move PC by -1024\n"
+ "Cursor Right - Move PC by 1024");
+ break;
+
+ case SDLK_ESCAPE:
+ quit=TRUE;
+ break;
+
+ case SDLK_h:
+ hexmode=!hexmode;
+ break;
+
+ case SDLK_RETURN:
+ case SDLK_KP_ENTER:
+ EnterAddress(&pc);
+ break;
+
+ case SDLK_UP:
+ if (hexmode)
+ pc-=8;
+ else
+ pc--;
+ break;
+
+ case SDLK_DOWN:
+ pc=next;
+ break;
+
+ case SDLK_PAGEUP:
+ if (hexmode)
+ pc-=21*8;
+ else
+ pc-=21;
+ break;
+
+ case SDLK_PAGEDOWN:
+ pc=curr;
+ break;
+
+ case SDLK_LEFT:
+ pc-=1024;
+ break;
+
+ case SDLK_RIGHT:
+ pc+=1024;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+
+/* ---------------------------------------- EXPORTED INTERFACES
+*/
+void MemoryMenu(Z80 *z80)
+{
+ SDL_Event *e;
+ int quit=FALSE;
+ Z80State s;
+
+ Z80GetState(z80,&s);
+
+ GFXKeyRepeat(TRUE);
+
+ while(!quit)
+ {
+ DisplayMenu();
+ DisplayState(z80);
+ GFXEndFrame(FALSE);
+
+ e=GFXWaitKey();
+
+ switch(e->key.keysym.sym)
+ {
+ case SDLK_1:
+ DoDisassem(z80,&s);
+ break;
+
+ case SDLK_ESCAPE:
+ case SDLK_2:
+ quit=TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ GFXKeyRepeat(FALSE);
+}
+
+
+void DisplayState(Z80 *z80)
+{
+ Z80State s;
+ int y;
+
+ Z80GetState(z80,&s);
+
+ y=136;
+
+ GFXPrintPaper(0,y,RED,BLACK,"PC=%4.4x A=%2.2x F=%s",
+ s.PC,s.AF>>8,FlagString(s.AF&0xff));
+ y+=8;
+
+ GFXPrintPaper(0,y,RED,BLACK,"BC=%4.4x DE=%4.4x HL=%4.4x",s.BC,s.DE,s.HL);
+ y+=8;
+
+ GFXPrintPaper(0,y,RED,BLACK,"IX=%4.4x IY=%4.4x SP=%4.4x",s.IX,s.IY,s.SP);
+ y+=8;
+
+ GFXPrintPaper(0,y,RED,BLACK,"I=%2.2x IM=%2.2x R=%2.2x",s.I,s.IM,s.R);
+ y+=8;
+
+ GFXPrintPaper(0,y,RED,BLACK,"IFF1=%2.2x IFF2=%2.2x",s.IFF1,s.IFF2);
+ y+=8;
+
+ y+=8;
+ GFXPrintPaper(0,y,RED,BLACK,"%s\n",SPECInfo(z80));
+ y+=8;
+}
+
+
+
+
+/* END OF FILE */
diff --git a/src/memmenu.h b/src/memmenu.h
new file mode 100644
index 0000000..524069f
--- /dev/null
+++ b/src/memmenu.h
@@ -0,0 +1,46 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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 a menu driven interface for analysing memory
+
+*/
+
+#ifndef ESPEC_MEMMENU_H
+#define ESPEC_MEMMENU_H "$Id$"
+
+#include "z80.h"
+
+
+/* Memory menu
+*/
+void MemoryMenu(Z80 *z80);
+
+
+/* Display the state of the SPEC at the bottom of the screen
+*/
+void DisplayState(Z80 *z80);
+
+
+#endif
+
+
+/* END OF FILE */
diff --git a/src/spec.c b/src/spec.c
new file mode 100644
index 0000000..51006df
--- /dev/null
+++ b/src/spec.c
@@ -0,0 +1,673 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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 SPEC
+
+*/
+static const char ident[]="$Id$";
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "spec.h"
+#include "gfx.h"
+#include "gui.h"
+#include "config.h"
+#include "exit.h"
+
+static const char ident_h[]=ESPEC_SPECH;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+/* ---------------------------------------- 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;
+
+/* 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;
+
+/* These assume a 320x200 screen
+*/
+static const int OFF_X=(320-256)/2;
+static const int OFF_Y=(200-192)/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
+*/
+static int nmigen=FALSE;
+static int hsync=FALSE;
+
+/* The ULA
+*/
+static struct
+{
+ int x;
+ int y;
+ int c;
+ int release;
+} ULA;
+
+/* GFX vars
+*/
+static Uint32 white;
+static Uint32 black;
+
+
+/* The keyboard
+*/
+static Z80Byte matrix[8];
+
+typedef struct
+{
+ SDLKey key;
+ int m1,b1,m2,b2;
+} MatrixMap;
+
+#define KY1(m,b) m,1<<b,-1,-1
+#define KY2(m1,b1,m2,b2) m1,1<<b1,m2,1<<b2
+
+static const MatrixMap keymap[]=
+{
+ {SDLK_1, KY1(3,0)},
+ {SDLK_2, KY1(3,1)},
+ {SDLK_3, KY1(3,2)},
+ {SDLK_4, KY1(3,3)},
+ {SDLK_5, KY1(3,4)},
+ {SDLK_6, KY1(4,4)},
+ {SDLK_7, KY1(4,3)},
+ {SDLK_8, KY1(4,2)},
+ {SDLK_9, KY1(4,1)},
+ {SDLK_0, KY1(4,0)},
+
+ {SDLK_a, KY1(1,0)},
+ {SDLK_b, KY1(7,4)},
+ {SDLK_c, KY1(0,3)},
+ {SDLK_d, KY1(1,2)},
+ {SDLK_e, KY1(2,2)},
+ {SDLK_f, KY1(1,3)},
+ {SDLK_g, KY1(1,4)},
+ {SDLK_h, KY1(6,4)},
+ {SDLK_i, KY1(5,2)},
+ {SDLK_j, KY1(6,3)},
+ {SDLK_k, KY1(6,2)},
+ {SDLK_l, KY1(6,1)},
+ {SDLK_m, KY1(7,2)},
+ {SDLK_n, KY1(7,3)},
+ {SDLK_o, KY1(5,1)},
+ {SDLK_p, KY1(5,0)},
+ {SDLK_q, KY1(2,0)},
+ {SDLK_r, KY1(2,3)},
+ {SDLK_s, KY1(1,1)},
+ {SDLK_t, KY1(2,4)},
+ {SDLK_u, KY1(5,3)},
+ {SDLK_v, KY1(0,4)},
+ {SDLK_w, KY1(2,1)},
+ {SDLK_x, KY1(0,2)},
+ {SDLK_y, KY1(5,4)},
+ {SDLK_z, KY1(0,1)},
+
+ {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)},
+ {SDLK_DOWN, KY2(0,0,4,4)},
+ {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_UNKNOWN, 0,0,0,0},
+};
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static void RomPatch(void)
+{
+ static const Z80Byte save[]=
+ {
+ 0xed, 0xf0, /* ED F0 illegal op */
+ 0xc3, 0x08, 0x02, /* JP $0207 */
+ 0xff /* End of patch */
+ };
+
+ static const Z80Byte load[]=
+ {
+ 0xed, 0xf1, /* ED F0 illegal op */
+ 0xc3, 0x08, 0x02, /* JP $0207 */
+ 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];
+}
+
+
+static char ToASCII(Z80Byte b)
+{
+ if (b==0) /* SPACE */
+ return ' ';
+
+ if (b==22) /* Dash (-) */
+ return '-';
+
+ if (b>=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);
+}
+
+
+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);
+}
+
+
+static int EDCallback(Z80 *z80, Z80Val data)
+{
+ Z80State state;
+
+ Z80GetState(z80,&state);
+
+ switch((Z80Byte)data)
+ {
+ case 0xf0:
+ SaveTape(&state);
+ break;
+
+ case 0xf1:
+ LoadTape(&state);
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+static void ULA_Video_Shifter(Z80 *z80, Z80Byte 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.y<SCR_H)
+ {
+ Uint32 fg,bg;
+
+ /* Position on screen corresponding to ULA
+ */
+ x=OFF_X+ULA.x*8;
+ y=OFF_Y+ULA.y;
+
+ /* Get ULA invert state and clear to ULA 6-but code
+ */
+ inv=val&0x80;
+ val&=0x3f;
+
+ base=((Z80Word)state.I<<8)|(val<<3)|ULA.c;
+
+ if (inv)
+ {
+ fg=white;
+ bg=black;
+ }
+ else
+ {
+ fg=black;
+ bg=white;
+ }
+
+ for(b=0;b<8;b++)
+ {
+ if (mem[base]&(1<<(7-b)))
+ GFXPlot(x+b,y,fg);
+ else
+ GFXPlot(x+b,y,bg);
+ }
+ }
+
+ ULA.x=(ULA.x+1)&0x1f;
+
+ if (ULA.x==0)
+ Z80Interrupt(z80,0xff);
+}
+
+
+static int CheckTimers(Z80 *z80, Z80Val val)
+{
+ if (val>HSYNC_PERIOD)
+ {
+ Z80ResetCycles(z80,0);
+
+ 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;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+/* ---------------------------------------- EXPORTED INTERFACES
+*/
+void SPECInit(Z80 *z80)
+{
+ FILE *fp;
+ Z80Word f;
+
+ if (!(fp=fopen(SConfig(CONF_ROMFILE),"rb")))
+ {
+ GUIMessage("ERROR","Failed to open SPEC ROM\n%s",SConfig(CONF_ROMFILE));
+ Exit("");
+ }
+
+ if (fread(mem,1,ROMLEN,fp)!=ROMLEN)
+ {
+ fclose(fp);
+ GUIMessage("ERROR","ROM file must be %d bytes long\n",ROMLEN);
+ Exit("");
+ }
+
+ /* Patch the ROM
+ */
+ RomPatch();
+ Z80LodgeCallback(z80,Z80_EDHook,EDCallback);
+ Z80LodgeCallback(z80,Z80_Fetch,CheckTimers);
+
+ /* Mirror the ROM
+ */
+ memcpy(mem+ROMLEN,mem,ROMLEN);
+
+ RAMBOT=0x4000;
+
+ /* Memory size (1 or 16K)
+ */
+ if (IConfig(CONF_MEMSIZE)==16)
+ RAMLEN=0x2000;
+ else
+ RAMLEN=0x400;
+
+ RAMTOP=RAMBOT+RAMLEN;
+
+ for(f=RAMBOT;f<=RAMTOP;f++)
+ mem[f]=0;
+
+ for(f=0;f<8;f++)
+ matrix[f]=0x1f;
+
+ white=GFXRGB(230,230,230);
+ black=GFXRGB(0,0,0);
+
+ nmigen=FALSE;
+ hsync=FALSE;
+
+ GFXStartFrame();
+}
+
+
+void SPECKeyEvent(SDL_Event *e)
+{
+ const MatrixMap *m;
+
+ m=keymap;
+
+ while(m->key!=SDLK_UNKNOWN)
+ {
+ if (e->key.keysym.sym==m->key)
+ {
+ if (e->key.state==SDL_PRESSED)
+ {
+ matrix[m->m1]&=~m->b1;
+
+ if (m->m2!=-1)
+ matrix[m->m2]&=~m->b2;
+ }
+ else
+ {
+ matrix[m->m1]|=m->b1;
+
+ if (m->m2!=-1)
+ matrix[m->m2]|=m->b2;
+ }
+ }
+
+ m++;
+ }
+}
+
+
+Z80Byte SPECReadMem(Z80 *z80, Z80Word addr)
+{
+ /* Memory reads above 32K invoke the ULA
+ */
+ if (addr>0x7fff)
+ {
+ 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];
+
+}
+
+
+void SPECWriteMem(Z80 *z80, Z80Word addr, Z80Byte val)
+{
+ addr=addr&0x7fff;
+
+ if (addr>=RAMBOT && addr<=RAMTOP)
+ mem[addr]=val;
+}
+
+
+Z80Byte SPECReadPort(Z80 *z80, Z80Word port)
+{
+ Z80Byte b=0;
+
+ printf("IN %4.4x\n",port);
+
+ 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;
+ }
+
+ /* Turn off HSYNC if NMI generator is OFF and redraw screen to
+ match output ULA has since sent out.
+ */
+ if (!nmigen && hsync)
+ {
+ hsync=FALSE;
+
+ GFXEndFrame(TRUE);
+ GFXClear(white);
+
+ ULA.x=0;
+ ULA.y=-1;
+ ULA.c=7;
+ ULA.release=FALSE;
+
+ GFXStartFrame();
+ }
+ else
+ {
+ /* Reset and hold ULA counter
+ */
+ ULA.c=0;
+ ULA.release=FALSE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return b;
+}
+
+
+void SPECWritePort(Z80 *z80, Z80Word port, Z80Byte val)
+{
+ printf("OUT %4.4x\n",port);
+
+ /* Any port write releases the ULA line counter
+ */
+ ULA.release=TRUE;
+
+ switch(port&0xff)
+ {
+ case 0xfd: /* NMI generator OFF */
+ nmigen=FALSE;
+ break;
+
+ case 0xfe: /* NMI generator ON */
+ nmigen=TRUE;
+ break;
+
+ case 0xff: /* HSYNC generator ON */
+ hsync=TRUE;
+ Z80ResetCycles(z80,0);
+ break;
+ }
+}
+
+
+Z80Byte SPECReadForDisassem(Z80 *z80, Z80Word addr)
+{
+ return mem[addr&0x7fff];
+}
+
+
+const char *SPECInfo(Z80 *z80)
+{
+ static char buff[80];
+
+ sprintf(buff,"NMIGEN: %s HSYNC: %s",
+ nmigen ? "ON":"OFF",
+ hsync ? "ON":"OFF");
+
+ return buff;
+}
+
+
+/* END OF FILE */
diff --git a/src/spec.h b/src/spec.h
new file mode 100644
index 0000000..611b5a4
--- /dev/null
+++ b/src/spec.h
@@ -0,0 +1,58 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.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 SPEC
+
+*/
+
+#ifndef ESPEC_SPECH
+#define ESPEC_SPECH "$Id$"
+
+#include "z80.h"
+#include "SDL.h"
+
+
+/* Initialise the SPEC
+*/
+void SPECInit(Z80 *z80);
+
+/* Handle keypresses
+*/
+void SPECKeyEvent(SDL_Event *e);
+
+/* Interfaces for the Z80
+*/
+Z80Byte SPECReadMem(Z80 *z80, Z80Word addr);
+void SPECWriteMem(Z80 *z80, Z80Word addr, Z80Byte val);
+Z80Byte SPECReadPort(Z80 *z80, Z80Word port);
+void SPECWritePort(Z80 *z80, Z80Word port, Z80Byte val);
+Z80Byte SPECReadForDisassem(Z80 *z80, Z80Word addr);
+
+/* Interfaces for memory menu
+*/
+const char *SPECInfo(Z80 *z80);
+
+
+#endif
+
+
+/* END OF FILE */