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
49 #define FONT_H_PITCH 16
53 static SDL_Surface
*screen
;
59 static unsigned framebuffer_generation
;
61 static void RenderItem(struct font
*font
, int index
, int x
, int y
)
63 SDL_Rect dest
= { x
, y
, font
->w
, font
->h
};
64 SDL_Rect clip
= { 0, index
* font
->h_pitch
, font
->w
, font
->h
};
65 SDL_BlitSurface(font
->surf
, &clip
, screen
, &dest
);
68 void RenderLetters(struct font
*font
, char *s
, int x
, int y
)
70 for (; *s
; ++s
, x
+= font
->w
)
71 RenderItem(font
, *s
, x
, y
);
74 int mysetup(int argc
, char **argv
)
76 if (SDL_Init(SDL_INIT_VIDEO
) < 0) {
77 fprintf(stderr
, "Unable to init SDL: %s\n", SDL_GetError());
85 screen
= SDL_SetVideoMode(48 * FONT_W
, 16 * FONT_H
, 8, SDL_SWSURFACE
);
87 fprintf(stderr
, "Unable to set video: %s\n", SDL_GetError());
91 /* Set the window caption */
92 SDL_WM_SetCaption("Nascom II", "Nascom II");
95 /* Populate the palette */
96 SDL_Color colors
[256];
98 colors
[0].r
= colors
[0].g
= colors
[0].b
= 0;
99 colors
[255].r
= colors
[255].b
= 0;
103 if (!SDL_SetColors(screen
, colors
, 0, 256)) {
104 fprintf(stderr
, "Unable to create framebuffer palette: %s\n",
106 screen
= 0; //XXX should free it
112 extern uint8_t nascom_font_raw
[];
116 SDL_CreateRGBSurfaceFrom(
126 nascom_font
.w
= FONT_W
;
127 nascom_font
.h
= FONT_H
;
128 nascom_font
.h_pitch
= FONT_H_PITCH
;
130 if (!nascom_font
.surf
) {
131 fprintf(stderr
, "no font :-( \n");
135 nascom_font
.surf
= SDL_DisplayFormat(nascom_font
.surf
);
144 unsigned char keym
[9] = {
145 0, /* ? ? ? Shift ? ? ? ? */
146 0, /* ?!TXF5BH ! = Up*/
147 0, /* ?!YZD6NJ ! = Left*/
148 0, /* ?!USE7MK ! = Down */
149 0, /* ?!IAW8,L ! = Right */
153 0 /* ? ? CR - Newline BS */
156 unsigned char keyp
= 0;
163 "Usage: %s {flags} {commands}\n"
164 " -m <file> use <file> as monitor (default is nassys3.nal)\n"
170 void load_nascom(const char *file
)
172 FILE *f
= fopen(file
, "r");
173 int a
, b1
, b2
, b3
, b4
, b5
, b6
, b7
, b8
;
183 printf("Loading %s", file
);
186 if (fscanf(f
, "%x %x %x %x %x %x %x %x %x",
187 &a
, &b1
, &b2
, &b3
, &b4
, &b5
, &b6
, &b7
, &b8
) == 9) {
201 while (ch
!= -1 && ch
!= '\n');
209 printf(". Successfully loaded %d bytes\n", count
);
213 f
= fopen("blob", "w");
214 fwrite((const void *) ram
, 1, 2048, f
);
219 static char * kbd_translation
[] = {
228 /* 8 */ "xzxxx-\r\010"
236 unsigned last_generation
= 0;
241 while (SDL_PollEvent(&event
)) {
242 switch (event
.type
) {
243 case SDL_MOUSEMOTION
:
244 /*printf("Mouse moved by %d,%d to (%d,%d)\n",
245 event.motion.xrel, event.motion.yrel,
246 event.motion.x, event.motion.y);*/
248 case SDL_MOUSEBUTTONDOWN
:
249 /*printf("Mouse button %d pressed at (%d,%d)\n",
250 event.button.button, event.button.x, event.button.y);*/
254 if (event
.key
.keysym
.sym
== 27 && event
.type
== SDL_KEYDOWN
) {
259 if (event
.key
.keysym
.sym
< 128) {
260 int ch
= toupper(event
.key
.keysym
.sym
);
261 for (i
= 0; i
< 9; ++i
)
262 for (bit
= 0; bit
< 8; ++bit
)
263 if (kbd_translation
[i
][7-bit
] == ch
) {
264 //printf(" -> %d/%d", i, bit);
268 //printf("%d?\n", event.key.keysym.sym);
272 switch (event
.key
.keysym
.sym
) {
273 case SDLK_LCTRL
: i
= 0, bit
= 3; break;
275 case SDLK_RSHIFT
: i
= 0, bit
= 4; break;
276 case SDLK_RCTRL
: i
= 0, bit
= 5; break;
277 case SDLK_UP
: i
= 1, bit
= 6; break;
278 case SDLK_LEFT
: i
= 2, bit
= 6; break;
279 case SDLK_DOWN
: i
= 3, bit
= 6; break;
280 case SDLK_RIGHT
: i
= 4, bit
= 6; break;
284 case SDLK_LALT
: i
= 5, bit
= 6; break;
285 case SDLK_KP_ENTER
:i
= 8, bit
= 6; break;
287 /* Undocumented hack */
289 f
= fopen("screendump", "w");
290 fwrite((const void *) (ram
+0x800), 1, 1024, f
);
292 if (vflag
) printf("Screen dumped\n");
296 //printf("%d? ", event.key.keysym.sym);
297 //printf(" keysym %s\n", SDL_GetKeyName(event.key.keysym.sym));
303 if (event
.type
== SDL_KEYDOWN
)
306 keym
[i
] &= ~(1 << bit
);
313 //printf("Unknown event: %d\n", event.type);
318 /* Only update the screen if the framebuffer has been written
320 if (last_generation
!= framebuffer_generation
) {
322 unsigned p
= 0x800 + 10;
323 last_generation
= framebuffer_generation
;
325 for (y
= 1; y
< 16; ++y
, p
+= 64) {
326 for (x
= 0; x
< 48; ++x
)
327 RenderItem(&nascom_font
, RAM(p
+ x
), x
* FONT_W
, y
* FONT_H
);
330 // Nascom is strange in that the last line is the first line!
331 for (x
= 0; x
< 48; ++x
)
332 RenderItem(&nascom_font
, RAM(p
+ x
), x
* FONT_W
, 0);
334 SDL_UpdateRect(screen
, 0, 0, screen
->w
, screen
->h
);
335 // SDL_Flip(screen); either seem to work
338 SDL_Delay(1000 / 30); // 30 fps
354 void simulate(void *dummy
)
356 simz80(pc
, 1000, sim_delay
);
359 int main(int argc
, char **argv
)
363 if (mysetup(argc
, argv
))
366 monitor
= "nassys3.nal";
371 for (c
=0; c
<MEMSIZE
/4; ++c
) pagetable
[c
]=ram
+(c
<<12);
374 while ((c
= getopt(argc
, argv
, "m:v")) != EOF
)
387 puts("VirtualNascom, a Nascom 2 emulator version " VERSION
"\n"
388 "Copyright 2000 Tommy Thorn. Based on\n"
389 "Yet Another Z80 Emulator version " YAZEVERSION
390 ", Copyright 1995,1998 Frank D. Cringle.\n"
391 "NasEmu comes with ABSOLUTELY NO WARRANTY; for details\n"
392 "see the file \"COPYING\" in the distribution directory.\n");
394 load_nascom(monitor
);
395 load_nascom("basic.nal");
397 for (; optind
< argc
; optind
++)
398 load_nascom(argv
[optind
]);
400 SDL_CreateThread((int (*)(void *))simulate
, NULL
);
404 fprintf(stderr
,"HALT\n");
405 fprintf(stderr
,"PC SP IR IX IY AF BC DE HL AF' BC' DE' HL'\n");
406 fprintf(stderr
,"%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
407 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
);
410 void out(unsigned int port
, unsigned char value
)
412 unsigned int down_trans
;
414 if (0) fprintf(stdout
, "[%02x] <- %02x\n", port
, value
);
419 down_trans
= port0
& ~value
;
422 if ((1 & down_trans
) && keyp
< 9) keyp
++;
423 if (2 & down_trans
) keyp
= 0;
430 int in(unsigned int port
)
432 if (0) fprintf(stdout
, "<- [%02x]\n", port
);
437 /* printf("[%d]", keyp); */
440 /* Status port on the UART */
447 void slow_write(unsigned int a
, unsigned char v
)
450 unsigned int y
= (a
-0x800) / 64;
451 unsigned int x
= (a
-0x800) % 64;
452 /* fprintf(stdout, "putbyte %04x %02x '%c'\n", a, v, v); */
453 if (10 <= x
&& x
< 58 && ' ' <= v
) {
459 //xputch(x-10, y, v);
460 //fprintf(stderr, "\033[%d;%dH%c", 1+y, 1+x-10, v);
461 framebuffer_generation
++;
465 if (0x800 <= a
&& a
<= 0xE000)