wip
[virtual-nascom.git] / xvirtualnascom.c
blob2d12cd2119c4d5716cb2200066c3dc06bbea707a
1 /* VirtualNascom, a Nascom II emulator.
3 Copyright (C) 2000 Tommy Thorn
4 Copyright (C) 1995,1998 Frank D. Cringle.
6 NasEmu is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2 of the License, or (at your
9 option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
26 #include <X11/Intrinsic.h>
27 #include <X11/StringDefs.h>
28 #include <X11/Xos.h>
29 #include <X11/cursorfont.h>
30 #include <X11/Xutil.h>
31 #include <X11/xpm.h>
34 #include "simz80.h"
35 #include "xvirtualnascom.h"
37 #define VERSION "1.0"
38 #define YAZEVERSION "1.10"
41 /* Z80 registers */
43 WORD af[2]; /* accumulator and flags (2 banks) */
44 int af_sel; /* bank select for af */
46 struct ddregs regs[2]; /* bc,de,hl */
47 int regs_sel; /* bank select for ddregs */
49 WORD ir; /* other Z80 registers */
50 WORD ix;
51 WORD iy;
52 WORD sp;
53 WORD pc;
54 WORD IFF;
56 BYTE ram[MEMSIZE*1024]; /* Z80 memory space */
57 #ifdef MMU
58 BYTE *pagetable[MEMSIZE/4]; /* MMU page table */
59 #endif
61 #ifndef LIBDIR
62 #define LIBDIR "/usr/local/lib/"
63 #endif
65 static char *monitor = "nassys3.nal";
66 static char *progname;
67 int vflag = 0;
69 static void
70 usage(void)
72 fprintf(stderr,
73 "Usage: %s {flags} {commands}\n"
74 " -m <file> use <file> as monitor (default is nasysy3.nal)\n"
75 " -v verbose\n"
76 ,progname);
77 exit (1);
80 void load_nascom(char *file)
82 FILE *f = fopen(file, "r");
83 int a, b1, b2, b3, b4, b5, b6, b7, b8;
84 int count = 0;
85 int ch;
87 if (!f) {
88 perror(file);
89 exit(1);
92 if (vflag) printf("Loading %s", file);
93 for (;!feof(f);) {
94 if (fscanf(f, "%x %x %x %x %x %x %x %x %x",
95 &a, &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8)
96 == 9) {
97 RAM(a) = b1;
98 RAM(a+1) = b2;
99 RAM(a+2) = b3;
100 RAM(a+3) = b4;
101 RAM(a+4) = b5;
102 RAM(a+5) = b6;
103 RAM(a+6) = b7;
104 RAM(a+7) = b8;
105 count += 8;
109 ch = fgetc(f);
110 while (ch != -1 && ch != '\n');
111 if (ch == -1)
112 break;
114 fclose(f);
115 if (vflag) printf(". Successfully loaded %d bytes\n", count);
118 extern char *optarg;
119 extern int optind, opterr, optopt;
120 int getopt(int argc, char * const *argv, const char *optstring);
122 int main(int argc, char **argv)
124 int c;
126 progname = argv[0];
128 xsetup(1, argv);
131 #ifdef MMU
132 for (c=0; c<MEMSIZE/4; ++c) pagetable[c]=ram+(c<<12);
133 #endif
135 while ((c = getopt(argc, argv, "m:v")) != EOF)
136 switch (c) {
137 case 'm':
138 monitor = optarg;
139 break;
140 case 'v':
141 vflag = 1;
142 break;
143 case '?':
144 usage();
147 if (vflag)
148 puts("VirtualNascom, a Nascom 2 emulator version " VERSION "\n"
149 "Copyright 2000 Tommy Thorn. Based on\n"
150 "Yet Another Z80 Emulator version " YAZEVERSION
151 ", Copyright 1995,1998 Frank D. Cringle.\n"
152 "NasEmu comes with ABSOLUTELY NO WARRANTY; for details\n"
153 "see the file \"COPYING\" in the distribution directory.\n");
155 load_nascom(monitor);
156 load_nascom("basic.nal");
158 for ( ; optind < argc; optind++)
159 load_nascom(argv[optind]);
161 simz80(pc, 20, xhandleevent);
163 fprintf(stderr,"HALT\n\r");
164 fprintf(stderr,"PC SP IR IX IY AF BC DE HL AF' BC' DE' HL'\n\r");
165 fprintf(stderr,"%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n\r",pc,sp,ir,ix,iy,af[af_sel],regs[regs_sel].bc,regs[regs_sel].de,regs[regs_sel].hl,af[1-af_sel],regs[1-regs_sel].bc,regs[1-regs_sel].de,regs[1-regs_sel].hl);
166 exit(0);
169 #ifndef USE_GNU_READLINE
170 void *
171 xmalloc(size_t size)
173 void *p = malloc(size);
175 if (p == NULL) {
176 fputs("insufficient memory\n", stderr);
177 exit(1);
179 return p;
181 #endif
188 #include "chars.xpm"
190 #define APP_NAME "xnasemu"
191 #define APP_CLASS "XNasemu"
193 # define RightButton Button3
194 # define MiddleButton Button2
195 # define LeftButton Button1
196 # define RightButtonMask Button3Mask
197 # define MiddleButtonMask Button2Mask
198 # define LeftButtonMask Button1Mask
201 * If MAXARGS isn't enough to hold all the arguments you pass any Xt
202 * procedure, the program aborts
204 #define MAXARGS 32
205 static int nargs;
206 static Arg wargs[MAXARGS];
207 #define startargs() nargs = 0
208 #define setarg(name, value) \
209 if (nargs < MAXARGS) \
210 XtSetArg(wargs[nargs], name, value), nargs++; \
211 else \
212 abort()
214 static Cursor WorkingCursor;
216 Display *dpy;
218 static Window win;
219 static GC gc;
220 static GC cleargc;
222 XImage *chars_bitmap, *chars_mask;
223 XpmAttributes chars_attrs;
225 #define CHARWIDTH 8
226 #define CHARHEIGHT 16
227 #define ROWS 16
228 #define COLS 48
230 /* Defaults */
231 static int defaultWidth = CHARWIDTH * COLS;
232 static int defaultHeight = CHARHEIGHT * ROWS;
234 static int Width, Height;
235 static Pixel fg, bg;
236 static char *progname;
238 /* Application Resources - no particular widget */
239 static XtResource application_resources[] = {
240 {"name", "Name", XtRString, sizeof(char *),
241 (Cardinal)&progname, XtRString, APP_NAME},
242 {"width", "Width", XtRInt, sizeof(int),
243 (Cardinal)&Width, XtRInt, (caddr_t) &defaultWidth},
244 {"height", "Height", XtRInt, sizeof(int),
245 (Cardinal)&Height, XtRInt, (caddr_t) &defaultHeight},
246 {"foreground", "Foreground", XtRPixel, sizeof(Pixel),
247 (Cardinal)&fg, XtRString, (caddr_t) "Black"},
248 {"background", "Background", XtRPixel, sizeof(Pixel),
249 (Cardinal)&bg, XtRString, (caddr_t) "White"},
253 * Command line options table. The command line is parsed for these,
254 * and it sets/overrides the appropriate values in the resource
255 * database
257 static XrmOptionDescRec optionDescList[] = {
258 {"-width", "*width", XrmoptionSepArg, (caddr_t) NULL},
259 {"-height", "*height", XrmoptionSepArg, (caddr_t) NULL},
260 {"-fg", "*foreground", XrmoptionSepArg, (caddr_t) NULL},
261 {"-bg", "*background", XrmoptionSepArg, (caddr_t) NULL},
265 void RepaintCanvas(Widget w, caddr_t data, XEvent *ev);
266 void RecordMapStatus(Widget w, caddr_t data, XEvent *ev);
267 void EventHandler(Widget w, caddr_t data, XEvent *ev);
269 void xsetup(int argc, char **argv)
271 Widget toplevel;
272 Widget w;
273 XGCValues gcv;
274 XEvent ev;
277 * Create the top level Widget that represents encloses the
278 * application.
280 toplevel = XtInitialize(argv[0],
281 APP_CLASS,
282 optionDescList,
283 XtNumber(optionDescList),
284 &argc,
285 argv);
287 XtGetApplicationResources(toplevel, (caddr_t) 0, application_resources,
288 XtNumber(application_resources), (ArgList) NULL, (Cardinal)0);
291 if (argc != 1) {
292 (void) fprintf(stderr, "Usage: %s [Xt options]\n", argv[0]);
293 exit(-1);
297 * Create a simple Core class widget which we'll use for the actual
298 * game. A Core class widget is basically just a window, with a
299 * simple Xt "wrapper" around it.
301 startargs();
302 setarg(XtNwidth, Width);
303 setarg(XtNheight, Height);
304 w = XtCreateManagedWidget(argv[0], widgetClass, toplevel,
305 wargs, XtNumber(wargs));
308 * Set the procedures for various X Windows actions - exposure events
309 * which arrive when a window needs to be redrawn. The map event lets
310 * you know that the window is now on the screen so you can actually
311 * do stuff. The ButtonPress event lets you know that a mouse button
312 * was pressed.
314 XtAddEventHandler(w, (EventMask) ExposureMask, False,
315 (XtEventHandler) RepaintCanvas, "redraw_data");
316 XtAddEventHandler(w, (EventMask) StructureNotifyMask, False,
317 (XtEventHandler) RecordMapStatus, "map_data");
318 /* One day, we'll use the translation manager here */
319 XtAddEventHandler(w, (EventMask) KeyPressMask | KeyReleaseMask, False,
320 (XtEventHandler) EventHandler, "input_data");
323 * Create the windows, and set their attributes according to the Widget
324 * data.
326 XtRealizeWidget(toplevel);
328 /* We need these for the raw Xlib calls */
329 win = XtWindow(w);
330 dpy = XtDisplay(w);
332 WorkingCursor = XCreateFontCursor(dpy, XC_top_left_arrow);
333 XDefineCursor(dpy, win, WorkingCursor);
336 * make the GC stuff here - one for copy, one for invert. Remember
337 * to change the both appropriately
339 gcv.foreground = fg;
340 gcv.background = bg;
341 gcv.function = GXcopy;
342 gc = XCreateGC(dpy, win, GCForeground | GCBackground
343 | GCFunction, &gcv);
344 gcv.foreground = bg;
345 cleargc = XCreateGC(dpy, win, GCForeground | GCBackground
346 | GCFunction, &gcv);
348 XpmCreateImageFromData(dpy, chars_xpm, &chars_bitmap, &chars_mask,
349 &chars_attrs);
352 * Now process the events.
355 /* Wait for first exposure event so we know window has been mapped */
356 XWindowEvent(dpy, win, (long) ExposureMask, &ev);
359 static int isMapped = 0;
362 /*ARGSUSED*/
363 void RepaintCanvas(Widget w, caddr_t data, XEvent *ev)
365 int x, y;
367 if (!isMapped)
368 return;
370 * Redraw the array
372 if (ev && ev->xexpose.count == 0) {
373 XEvent event;
374 /* Skip all excess redraws */
375 while (XCheckTypedEvent(dpy, Expose, &event))
379 /* The Nascom screen memory has the top line be line 15 with
380 line 0-14 just following it. Yes, stupid indeed */
382 for (x = 0; x < 48; ++x)
383 xputch(x, 0, RAM(0x80a+64*15+x));
385 for (y = 0; y < 15; ++y)
386 for (x = 0; x < 48; ++x)
387 xputch(x, y+1, RAM(0x80a+y*64+x));
389 XFlush(dpy);
393 void RecordMapStatus(Widget w, caddr_t data, XEvent *ev)
395 if (ev->type == MapNotify) {
396 #ifdef WINDOWDEBUG
397 (void) printf("window mapped\n");
398 #endif
399 isMapped = TRUE;
400 } else if (ev->type == ConfigureNotify) {
401 #ifdef WINDOWDEBUG
402 (void) printf("window resized\n");
403 #endif
408 void xputch(int x, int y, unsigned char v)
410 /* FIXME: Are Nascom characters really 16 pixels high? */
411 XPutImage(dpy, win, gc, chars_bitmap, 0, v*16, x*8, y*16, 8, 16);
412 /* XFlush(dpy); An unsuccessful attempt to improve some games */
415 void xhandleevent()
417 XEvent ev;
419 if (XtPending()) {
420 XtNextEvent(&ev);
421 XtDispatchEvent(&ev);