1 /* VirtualNascom, a Nascom II emulator.
3 Copyright (C) 2000,2009 Tommy Thorn
5 Z80 emulator portition Copyright (C) 1995,1998 Frank D. Cringle.
7 NasEmu is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 - a bitmapped keyboard,
29 0000 - 07ff 2 KB ROM monitor,
30 0800 - 0bff 1 KB screen memory,
31 0c00 - 0fff 1 KB workspace
33 e000 - ffff 8 KB of MS Basic
35 With the Z80 emulator in place the first thing to get working is the
36 screen memory. The "correct" way to simulate screen memory is to
37 trap upon writes, but that would be slow. We do it any just to get
52 static SDL_Surface
*screen
;
58 static unsigned framebuffer_generation
;
60 static void RenderItem(struct font
*font
, int index
, int x
, int y
)
62 SDL_Rect dest
= { x
, y
, font
->w
, font
->h
};
63 SDL_Rect clip
= { 0, index
* font
->h
, font
->w
, font
->h
};
64 SDL_BlitSurface(font
->surf
, &clip
, screen
, &dest
);
67 void RenderLetters(struct font
*font
, char *s
, int x
, int y
)
69 for (; *s
; ++s
, x
+= font
->w
)
70 RenderItem(font
, *s
, x
, y
);
73 int mysetup(int argc
, char **argv
)
75 if (SDL_Init(SDL_INIT_VIDEO
) < 0) {
76 fprintf(stderr
, "Unable to init SDL: %s\n", SDL_GetError());
84 screen
= SDL_SetVideoMode(48 * FONT_W
, 16 * FONT_H
, 8, SDL_SWSURFACE
);
86 fprintf(stderr
, "Unable to set video: %s\n", SDL_GetError());
90 /* Set the window caption */
91 SDL_WM_SetCaption("Nascom II", "Nascom II");
94 /* Populate the palette */
95 SDL_Color colors
[256];
97 colors
[0].r
= colors
[0].g
= colors
[0].b
= 0;
98 colors
[255].r
= colors
[255].b
= 0;
102 if (!SDL_SetColors(screen
, colors
, 0, 256)) {
103 fprintf(stderr
, "Unable to create framebuffer palette: %s\n",
105 screen
= 0; //XXX should free it
111 extern uint8_t nascom_font_raw
[];
115 SDL_CreateRGBSurfaceFrom(
125 nascom_font
.w
= FONT_W
;
126 nascom_font
.h
= FONT_H
;
128 if (!nascom_font
.surf
) {
129 fprintf(stderr
, "no font :-( \n");
133 nascom_font
.surf
= SDL_DisplayFormat(nascom_font
.surf
);
142 unsigned char keym
[9] = {
143 0, /* ? ? ? Shift ? ? ? ? */
144 0, /* ?!TXF5BH ! = Up*/
145 0, /* ?!YZD6NJ ! = Left*/
146 0, /* ?!USE7MK ! = Down */
147 0, /* ?!IAW8,L ! = Right */
151 0 /* ? ? CR - Newline BS */
154 unsigned char keyp
= 0;
161 "Usage: %s {flags} {commands}\n"
162 " -m <file> use <file> as monitor (default is nassys3.nal)\n"
168 void load_nascom(const char *file
)
170 FILE *f
= fopen(file
, "r");
171 int a
, b1
, b2
, b3
, b4
, b5
, b6
, b7
, b8
;
181 printf("Loading %s", file
);
184 if (fscanf(f
, "%x %x %x %x %x %x %x %x %x",
185 &a
, &b1
, &b2
, &b3
, &b4
, &b5
, &b6
, &b7
, &b8
) == 9) {
199 while (ch
!= -1 && ch
!= '\n');
207 printf(". Successfully loaded %d bytes\n", count
);
211 f
= fopen("blob", "w");
212 fwrite((const void *) ram
, 1, 2048, f
);
217 static char * kbd_translation
[] = {
226 /* 8 */ "xzxxx-\r\010"
234 unsigned last_generation
= 0;
239 while (SDL_PollEvent(&event
)) {
240 switch (event
.type
) {
241 case SDL_MOUSEMOTION
:
242 /*printf("Mouse moved by %d,%d to (%d,%d)\n",
243 event.motion.xrel, event.motion.yrel,
244 event.motion.x, event.motion.y);*/
246 case SDL_MOUSEBUTTONDOWN
:
247 /*printf("Mouse button %d pressed at (%d,%d)\n",
248 event.button.button, event.button.x, event.button.y);*/
252 if (event
.key
.keysym
.sym
== 27 && event
.type
== SDL_KEYDOWN
) {
257 if (event
.key
.keysym
.sym
< 128) {
258 int ch
= toupper(event
.key
.keysym
.sym
);
259 for (i
= 0; i
< 9; ++i
)
260 for (bit
= 0; bit
< 8; ++bit
)
261 if (kbd_translation
[i
][7-bit
] == ch
) {
262 //printf(" -> %d/%d", i, bit);
266 printf("%d?\n", event
.key
.keysym
.sym
);
270 switch (event
.key
.keysym
.sym
) {
271 case SDLK_LCTRL
: i
= 0, bit
= 3; break;
273 case SDLK_RSHIFT
: i
= 0, bit
= 4; break;
274 case SDLK_RCTRL
: i
= 0, bit
= 5; break;
275 case SDLK_UP
: i
= 1, bit
= 6; break;
276 case SDLK_LEFT
: i
= 2, bit
= 6; break;
277 case SDLK_DOWN
: i
= 3, bit
= 6; break;
278 case SDLK_RIGHT
: i
= 4, bit
= 6; break;
282 case SDLK_LALT
: i
= 5, bit
= 6; break;
283 case SDLK_KP_ENTER
:i
= 8, bit
= 6; break;
285 /* Undocumented hack */
287 f
= fopen("screendump", "w");
288 fwrite((const void *) (ram
+0x800), 1, 1024, f
);
290 if (vflag
) printf("Screen dumped\n");
294 printf("%d? ", event
.key
.keysym
.sym
);
295 printf(" keysym %s\n", SDL_GetKeyName(event
.key
.keysym
.sym
));
300 if (event
.type
== SDL_KEYDOWN
)
303 keym
[i
] &= ~(1 << bit
);
310 printf("Unknown event: %d\n", event
.type
);
315 /* Only update the screen if the framebuffer has been written
317 if (last_generation
!= framebuffer_generation
) {
319 unsigned p
= 0x800 + 10;
320 last_generation
= framebuffer_generation
;
322 for (y
= 1; y
< 16; ++y
, p
+= 64) {
323 for (x
= 0; x
< 48; ++x
)
324 RenderItem(&nascom_font
, RAM(p
+ x
), x
* FONT_W
, y
* FONT_H
);
327 // Nascom is strange in that the last line is the first line!
328 for (x
= 0; x
< 48; ++x
)
329 RenderItem(&nascom_font
, RAM(p
+ x
), x
* FONT_W
, 0);
331 SDL_UpdateRect(screen
, 0, 0, screen
->w
, screen
->h
);
332 // SDL_Flip(screen); either seem to work
335 SDL_Delay(1000 / 30); // 30 fps
351 void simulate(void *dummy
)
353 simz80(pc
, 1000, sim_delay
);
356 int main(int argc
, char **argv
)
360 if (mysetup(argc
, argv
))
363 monitor
= "nassys3.nal";
368 for (c
=0; c
<MEMSIZE
/4; ++c
) pagetable
[c
]=ram
+(c
<<12);
371 while ((c
= getopt(argc
, argv
, "m:v")) != EOF
)
384 puts("VirtualNascom, a Nascom 2 emulator version " VERSION
"\n"
385 "Copyright 2000 Tommy Thorn. Based on\n"
386 "Yet Another Z80 Emulator version " YAZEVERSION
387 ", Copyright 1995,1998 Frank D. Cringle.\n"
388 "NasEmu comes with ABSOLUTELY NO WARRANTY; for details\n"
389 "see the file \"COPYING\" in the distribution directory.\n");
391 load_nascom(monitor
);
392 load_nascom("basic.nal");
394 for (; optind
< argc
; optind
++)
395 load_nascom(argv
[optind
]);
397 SDL_CreateThread((int (*)(void *))simulate
, NULL
);
401 fprintf(stderr
,"HALT\n");
402 fprintf(stderr
,"PC SP IR IX IY AF BC DE HL AF' BC' DE' HL'\n");
403 fprintf(stderr
,"%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
404 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
);
407 void out(unsigned int port
, unsigned char value
)
409 unsigned int down_trans
;
411 if (0) fprintf(stdout
, "[%02x] <- %02x\n", port
, value
);
416 down_trans
= port0
& ~value
;
419 if ((1 & down_trans
) && keyp
< 9) keyp
++;
420 if (2 & down_trans
) keyp
= 0;
427 int in(unsigned int port
)
429 if (0) fprintf(stdout
, "<- [%02x]\n", port
);
434 /* printf("[%d]", keyp); */
437 /* Status port on the UART */
444 void slow_write(unsigned int a
, unsigned char v
)
447 unsigned int y
= (a
-0x800) / 64;
448 unsigned int x
= (a
-0x800) % 64;
449 /* fprintf(stdout, "putbyte %04x %02x '%c'\n", a, v, v); */
450 if (10 <= x
&& x
< 58 && ' ' <= v
) {
456 //xputch(x-10, y, v);
457 //fprintf(stderr, "\033[%d;%dH%c", 1+y, 1+x-10, v);
458 framebuffer_generation
++;
462 if (0x800 <= a
&& a
<= 0xE000)