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. */
23 #include <sys/types.h>
26 #include <X11/Intrinsic.h>
27 #include <X11/StringDefs.h>
29 #include <X11/cursorfont.h>
30 #include <X11/Xutil.h>
35 #include "xvirtualnascom.h"
38 #define YAZEVERSION "1.10"
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 */
56 BYTE ram
[MEMSIZE
*1024]; /* Z80 memory space */
58 BYTE
*pagetable
[MEMSIZE
/4]; /* MMU page table */
62 #define LIBDIR "/usr/local/lib/"
65 static char *monitor
= "nassys3.nal";
66 static char *progname
;
73 "Usage: %s {flags} {commands}\n"
74 " -m <file> use <file> as monitor (default is nasysy3.nal)\n"
80 void load_nascom(char *file
)
82 FILE *f
= fopen(file
, "r");
83 int a
, b1
, b2
, b3
, b4
, b5
, b6
, b7
, b8
;
92 if (vflag
) printf("Loading %s", file
);
94 if (fscanf(f
, "%x %x %x %x %x %x %x %x %x",
95 &a
, &b1
, &b2
, &b3
, &b4
, &b5
, &b6
, &b7
, &b8
)
110 while (ch
!= -1 && ch
!= '\n');
115 if (vflag
) printf(". Successfully loaded %d bytes\n", count
);
119 extern int optind
, opterr
, optopt
;
120 int getopt(int argc
, char * const *argv
, const char *optstring
);
122 int main(int argc
, char **argv
)
132 for (c
=0; c
<MEMSIZE
/4; ++c
) pagetable
[c
]=ram
+(c
<<12);
135 while ((c
= getopt(argc
, argv
, "m:v")) != EOF
)
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
);
169 #ifndef USE_GNU_READLINE
173 void *p
= malloc(size
);
176 fputs("insufficient memory\n", stderr
);
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
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++; \
214 static Cursor WorkingCursor
;
222 XImage
*chars_bitmap
, *chars_mask
;
223 XpmAttributes chars_attrs
;
226 #define CHARHEIGHT 16
231 static int defaultWidth
= CHARWIDTH
* COLS
;
232 static int defaultHeight
= CHARHEIGHT
* ROWS
;
234 static int Width
, Height
;
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
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
)
277 * Create the top level Widget that represents encloses the
280 toplevel
= XtInitialize(argv
[0],
283 XtNumber(optionDescList
),
287 XtGetApplicationResources(toplevel
, (caddr_t
) 0, application_resources
,
288 XtNumber(application_resources
), (ArgList
) NULL
, (Cardinal
)0);
292 (void) fprintf(stderr
, "Usage: %s [Xt options]\n", argv
[0]);
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.
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
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
326 XtRealizeWidget(toplevel
);
328 /* We need these for the raw Xlib calls */
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
341 gcv
.function
= GXcopy
;
342 gc
= XCreateGC(dpy
, win
, GCForeground
| GCBackground
345 cleargc
= XCreateGC(dpy
, win
, GCForeground
| GCBackground
348 XpmCreateImageFromData(dpy
, chars_xpm
, &chars_bitmap
, &chars_mask
,
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;
363 void RepaintCanvas(Widget w
, caddr_t data
, XEvent
*ev
)
372 if (ev
&& ev
->xexpose
.count
== 0) {
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
));
393 void RecordMapStatus(Widget w
, caddr_t data
, XEvent
*ev
)
395 if (ev
->type
== MapNotify
) {
397 (void) printf("window mapped\n");
400 } else if (ev
->type
== ConfigureNotify
) {
402 (void) printf("window resized\n");
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 */
421 XtDispatchEvent(&ev
);