2 * Z80SIM - a Z80-CPU simulator
4 * Copyright (C) 1987-2017 by Udo Munk
7 * 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
8 * 11-JAN-89 Release 1.1
9 * 08-FEB-89 Release 1.2
10 * 13-MAR-89 Release 1.3
11 * 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
12 * 20-DEC-90 Release 1.5 Ported to COHERENT 3.0
13 * 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
14 * and some optimisation
15 * 25-JUN-92 Release 1.7 comments in english and ported to COHERENT 4.0
16 * 02-OCT-06 Release 1.8 modified to compile on modern POSIX OS's
17 * 18-NOV-06 Release 1.9 modified to work with CP/M sources
18 * 08-DEC-06 Release 1.10 modified MMU for working with CP/NET
19 * 17-DEC-06 Release 1.11 TCP/IP sockets for CP/NET
20 * 25-DEC-06 Release 1.12 CPU speed option
21 * 19-FEB-07 Release 1.13 various improvements
22 * 06-OCT-07 Release 1.14 bug fixes and improvements
23 * 06-AUG-08 Release 1.15 many improvements and Windows support via Cygwin
24 * 25-AUG-08 Release 1.16 console status I/O loop detection and line discipline
25 * 20-OCT-08 Release 1.17 frontpanel integrated and Altair/IMSAI emulations
26 * 24-JAN-14 Release 1.18 bug fixes and improvements
27 * 02-MAR-14 Release 1.19 source cleanup and improvements
28 * 14-MAR-14 Release 1.20 added Tarbell SD FDC and printer port to Altair
29 * 29-MAR-14 Release 1.21 many improvements
30 * 29-MAY-14 Release 1.22 improved networking and bugfixes
31 * 04-JUN-14 Release 1.23 added 8080 emulation
32 * 06-SEP-14 Release 1.24 bugfixes and improvements
33 * 18-FEB-15 Release 1.25 bugfixes, improvements, added Cromemco Z-1
34 * 18-APR-15 Release 1.26 bugfixes and improvements
35 * 18-JAN-16 Release 1.27 bugfixes and improvements
36 * 05-MAY-16 Release 1.28 improved usability
37 * 20-NOV-16 Release 1.29 bugfixes and improvements
38 * 15-DEC-16 Release 1.30 improved memory management, machine cycle correct CPUs
39 * 28-DEC-16 Release 1.31 improved memory management, reimplemented MMUs
40 * 12-JAN-17 Release 1.32 improved configurations, front panel, added IMSAI VIO
41 * 07-FEB-17 Release 1.33 bugfixes, improvements, better front panels
42 * 16-MAR-17 Release 1.34 improvements, added ProcTec VDM-1
43 * 03-AUG-17 Release 1.35 added UNIX sockets, bugfixes, improvements
44 * 21-DEC-17 Release 1.36 bugfixes and improvements
48 * This module contains the 'main()' function of the simulator,
49 * where the options are checked and variables are initialised.
50 * After initialisation of the UNIX interrupts ( int_on() )
51 * and initialisation of the I/O simulation ( init_io() )
52 * the user interface ( mon() ) is called.
68 //#include "../../frontpanel/frontpanel.h"
71 #define BUFSIZE 256 /* buffer size for file I/O */
73 static void init_cpu(void);
75 static void save_core(void);
76 static int load_mos(int, char *), load_hex(char *), checksum(char *);
77 extern void int_on(void), int_off(void), mon(void);
78 extern void init_io(void), exit_io(void);
79 extern int exatoi(char *);
81 BYTE *wrk_ram; /* work pointer for the memory */
83 int main(int argc, char *argv[])
87 char *pn = basename(argv[0]);
93 const char *rom = "-r ";
99 tmax = CPU_SPEED * 10000;
102 while (--argc > 0 && (*++argv)[0] == '-')
103 for (s = argv[0] + 1; *s != '\0'; s++)
106 case 's': /* save core and CPU on exit */
110 case 'l': /* load core and CPU from file */
114 case 'u': /* trap undocumented ops */
118 case 'i': /* trap I/O on unused ports */
122 case 'm': /* initialise Z80 memory */
123 if (*(s+1) != '\0') {
124 m_flag = exatoi(s+1);
131 m_flag = exatoi(argv[0]);
135 case 'f': /* set emulation speed */
136 if (*(s+1) != '\0') {
144 f_flag = atoi(argv[0]);
146 tmax = f_flag * 10000;
149 case 'x': /* get filename with Z80 executable */
167 case 'r': /* load default boot ROM */
169 strcpy(xfn, BOOTROM);
174 case 'd': /* get path for disk images */
204 printf("illegal option %c\n", *s);
209 printf("usage:\t%s -z -8 -s -l -i -u %s-m val -f freq -x filename -d diskpath\n", pn, rom);
211 printf("usage:\t%s -z -8 -s -l -i -u %s-m val -f freq -x filename\n", pn, rom);
213 puts("\t-z = emulate Zilog Z80");
214 puts("\t-8 = emulate Intel 8080");
215 puts("\t-s = save core and CPU");
216 puts("\t-l = load core and CPU");
217 puts("\t-i = trap on I/O to unused ports");
218 puts("\t-u = trap on undocumented instructions");
220 puts("\t-r = load and execute default ROM");
221 printf("\t %s\n", BOOTROM);
223 puts("\t-m = init memory with val (00-FF)");
224 puts("\t-f = CPU clock frequency freq in MHz");
225 puts("\t-x = load and execute filename");
227 puts("\t-d = use disks images at diskpath");
228 puts("\t default path for disk images:");
230 printf("\t %s\n", DISKSDIR);
238 puts("####### ##### ### ##### ### # #");
239 puts(" # # # # # # # # ## ##");
240 puts(" # # # # # # # # # # #");
241 puts(" # ##### # # ##### ##### # # # #");
242 puts(" # # # # # # # # #");
243 puts(" # # # # # # # # # #");
244 puts("####### ##### ### ##### ### # #");
248 puts(" ##### ### ##### ### ##### ### # #");
249 puts("# # # # # # # # # # # ## ##");
250 puts("# # # # # # # # # # # # # #");
251 puts(" ##### # # ##### # # ##### ##### # # # #");
252 puts("# # # # # # # # # # # #");
253 puts("# # # # # # # # # # # # #");
254 puts(" ##### ### ##### ### ##### ### # #");
257 printf("\nRelease %s, %s\n", RELEASE, COPYR);
260 printf("%s Release %s, %s\n\n", USR_COM, USR_REL, USR_CPR);
265 printf("CPU speed is %d MHz\n", f_flag);
267 printf("CPU speed is unlimited\n");
271 /* if the machine has configuration files try to find them */
273 /* first try ./conf */
274 if ((stat("./conf", &sbuf) == 0) && S_ISDIR(sbuf.st_mode)) {
275 strcpy(&confdir[0], "./conf");
276 /* then CONFDIR as set in Makefile */
278 strcpy(&confdir[0], CONFDIR);
281 //printf("config = %s\n", &confdir[0]);
284 /* seed random generator */
285 gettimeofday(&tv, NULL);
288 config(); /* read system configuration */
289 init_memory(); /* initialise memory configuration */
290 init_cpu(); /* initialise CPU */
291 wrk_ram = mem_base(); /* set work pointer for memory */
293 /* fill memory content with some initial value */
295 memset((char *) wrk_ram, m_flag, 65536);
297 for (i = 0; i < 65536; i++)
298 *(wrk_ram + i) = (BYTE) (rand() % 256);
301 init_rom(); /* initialise ROM's */
303 if (l_flag) /* load core */
307 int_on(); /* initialize UNIX interrupts */
308 init_io(); /* initialize I/O devices */
310 mon(); /* run system */
312 if (s_flag) /* save core */
315 exit_io(); /* stop I/O devices */
316 int_off(); /* stop UNIX interrupts */
324 static void init_cpu(void)
326 /* same for i8080 and Z80 */
338 if (cpu == I8080) { /* i8080 specific */
339 F &= ~(N2_FLAG | N1_FLAG);
341 } else { /* Z80 specific */
361 IFF = int_int = int_nmi = int_protection = int_mode = 0;
373 * This function saves the CPU and the memory into the file core.z80
375 static void save_core(void)
379 if ((fd = open("core.z80", O_WRONLY | O_CREAT, 0600)) == -1) {
380 puts("can't open file core.z80");
383 write(fd, (char *) &A, sizeof(A));
384 write(fd, (char *) &F, sizeof(F));
385 write(fd, (char *) &B, sizeof(B));
386 write(fd, (char *) &C, sizeof(C));
387 write(fd, (char *) &D, sizeof(D));
388 write(fd, (char *) &E, sizeof(E));
389 write(fd, (char *) &H, sizeof(H));
390 write(fd, (char *) &L, sizeof(L));
391 write(fd, (char *) &A_, sizeof(A_));
392 write(fd, (char *) &F_, sizeof(F_));
393 write(fd, (char *) &B_, sizeof(B_));
394 write(fd, (char *) &C_, sizeof(C_));
395 write(fd, (char *) &D_, sizeof(D_));
396 write(fd, (char *) &E_, sizeof(E_));
397 write(fd, (char *) &H_, sizeof(H_));
398 write(fd, (char *) &L_, sizeof(L_));
399 write(fd, (char *) &I, sizeof(I));
400 write(fd, (char *) &IFF, sizeof(IFF));
401 write(fd, (char *) &R, sizeof(R));
402 write(fd, (char *) &PC, sizeof(PC));
403 write(fd, (char *) &SP, sizeof(SP));
404 write(fd, (char *) &IX, sizeof(IX));
405 write(fd, (char *) &IY, sizeof(IY));
406 write(fd, (char *) mem_base(), 65536);
411 * This function loads the CPU and memory from the file core.z80
417 if ((fd = open("core.z80", O_RDONLY)) == -1) {
418 puts("can't open file core.z80");
421 read(fd, (char *) &A, sizeof(A));
422 read(fd, (char *) &F, sizeof(F));
423 read(fd, (char *) &B, sizeof(B));
424 read(fd, (char *) &C, sizeof(C));
425 read(fd, (char *) &D, sizeof(D));
426 read(fd, (char *) &E, sizeof(E));
427 read(fd, (char *) &H, sizeof(H));
428 read(fd, (char *) &L, sizeof(L));
429 read(fd, (char *) &A_, sizeof(A_));
430 read(fd, (char *) &F_, sizeof(F_));
431 read(fd, (char *) &B_, sizeof(B_));
432 read(fd, (char *) &C_, sizeof(C_));
433 read(fd, (char *) &D_, sizeof(D_));
434 read(fd, (char *) &E_, sizeof(E_));
435 read(fd, (char *) &H_, sizeof(H_));
436 read(fd, (char *) &L_, sizeof(L_));
437 read(fd, (char *) &I, sizeof(I));
438 read(fd, (char *) &IFF, sizeof(IFF));
439 read(fd, (char *) &R, sizeof(R));
440 read(fd, (char *) &PC, sizeof(PC));
441 read(fd, (char *) &SP, sizeof(SP));
442 read(fd, (char *) &IX, sizeof(IX));
443 read(fd, (char *) &IY, sizeof(IY));
444 read(fd, (char *) mem_base(), 65536);
451 * Read a file into the memory of the emulated CPU.
452 * The following file formats are supported:
454 * binary images with Mostek header
457 int load_file(char *s)
461 register char *pfn = fn;
464 while (isspace((int)*s))
466 while (*s != ',' && *s != '\n' && *s != '\0')
469 if (strlen(fn) == 0) {
470 puts("no input file given");
473 if ((fd = open(fn, O_RDONLY)) == -1) {
474 printf("can't open file %s\n", fn);
478 wrk_ram = mem_base() + exatoi(++s);
481 read(fd, (char *) fileb, 5); /* read first 5 bytes of file */
482 if (*fileb == (BYTE) 0xff) { /* Mostek header ? */
483 lseek(fd, 0l, SEEK_SET);
484 return (load_mos(fd, fn));
488 return (load_hex(fn));
493 * Loader for binary images with Mostek header.
494 * Format of the first 3 bytes:
498 * ll = load address low
499 * lh = load address high
501 static int load_mos(int fd, char *fn)
504 unsigned count, readn;
507 read(fd, (char *) fileb, 3); /* read load address */
508 if (wrk_ram == NULL) /* and set if not given */
509 wrk_ram = mem_base() + (fileb[2] << 8) + fileb[1];
510 count = mem_base() + 65535 - wrk_ram;
511 if ((readn = read(fd, (char *) wrk_ram, count)) == count) {
512 puts("Too much to load, stopped at 0xffff");
516 printf("Loader statistics for file %s:\n", fn);
517 printf("START : %04x\n", (unsigned int)(wrk_ram - mem_base()));
518 printf("END : %04x\n", (unsigned int)(wrk_ram - mem_base()
520 printf("LOADED: %04x\n\n", readn);
521 PC = wrk_ram - mem_base();
526 * Loader for Intel hex
528 static int load_hex(char *fn)
540 if ((fd = fopen(fn, "r")) == NULL) {
541 printf("can't open file %s\n", fn);
545 while (fgets(&buf[0], BUFSIZE, fd) != NULL) {
547 while (isspace((int)*s))
551 if (checksum(s + 1) != 0) {
552 printf("invalid checksum in hex record: %s\n", s);
556 count = (*s <= '9') ? (*s - '0') << 4 :
557 (*s - 'A' + 10) << 4;
559 count += (*s <= '9') ? (*s - '0') :
564 addr = (*s <= '9') ? (*s - '0') << 4 :
565 (*s - 'A' + 10) << 4;
567 addr += (*s <= '9') ? (*s - '0') :
571 addr += (*s <= '9') ? (*s - '0') << 4 :
572 (*s - 'A' + 10) << 4;
574 addr += (*s <= '9') ? (*s - '0') :
580 eaddr = addr + count - 1;
582 for (i = 0; i < count; i++) {
583 data = (*s <= '9') ? (*s - '0') << 4 :
584 (*s - 'A' + 10) << 4;
586 data += (*s <= '9') ? (*s - '0') :
589 *(mem_base() + addr + i) = data;
594 count = eaddr - saddr + 1;
595 printf("Loader statistics for file %s:\n", fn);
596 printf("START : %04xH\n", saddr);
597 printf("END : %04xH\n", eaddr);
598 printf("LOADED: %04xH (%d)\n\n", count, count);
600 wrk_ram = mem_base() + saddr;
606 * Verify checksum of Intel hex records
608 static int checksum(char *s)
612 while ((*s != '\r') && (*s != '\n')) {
615 (*s - 'A' + 10) << 4;
623 if ((chk & 255) == 0)