203 lines
5.6 KiB
C
203 lines
5.6 KiB
C
/*
|
|
* Z80SIM - a Z80-CPU simulator
|
|
*
|
|
* Copyright (C) 1987-2006 by Udo Munk
|
|
*
|
|
* History:
|
|
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
|
* 11-JAN-89 Release 1.1
|
|
* 08-FEB-89 Release 1.2
|
|
* 13-MAR-89 Release 1.3
|
|
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
|
|
* 20-DEC-90 Release 1.5 Ported to COHERENT 3.0
|
|
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
|
|
* and some optimization
|
|
* 25-JUN-92 Release 1.7 comments in english and ported to COHERENT 4.0
|
|
* 03-OCT-06 Release 1.8 modified to compile on modern POSIX OS's
|
|
*/
|
|
|
|
/*
|
|
* This modul contain the 'main()' function of the simulator,
|
|
* where the options are checked and variables are initialized.
|
|
* After initialization of the UNIX interrupts ( int_on() )
|
|
* and initialization of the I/O simulation ( init_io() )
|
|
* the user interface ( mon() ) is called.
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <fcntl.h>
|
|
#include <memory.h>
|
|
#include "sim.h"
|
|
#include "simglb.h"
|
|
|
|
static void save_core(void), load_core(void);
|
|
extern void int_on(void), int_off(void), mon(void);
|
|
extern void init_io(void), exit_io(void);
|
|
extern int exatoi(char *);
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
register char *s, *p;
|
|
register char *pn = argv[0];
|
|
|
|
while (--argc > 0 && (*++argv)[0] == '-')
|
|
for (s = argv[0] + 1; *s != '\0'; s++)
|
|
switch (*s) {
|
|
case 's': /* save core and CPU on exit */
|
|
s_flag = 1;
|
|
break;
|
|
case 'l': /* load core and CPU from file */
|
|
l_flag = 1;
|
|
break;
|
|
case 'h': /* execute HALT opcode */
|
|
break_flag = 0;
|
|
break;
|
|
case 'i': /* trap I/O on unused ports */
|
|
i_flag = 1;
|
|
break;
|
|
case 'm': /* initialize Z80 memory */
|
|
m_flag = exatoi(s+1);
|
|
s += strlen(s+1);
|
|
break;
|
|
case 'f':
|
|
f_flag = atoi(s+1);
|
|
s += strlen(s+1);
|
|
freq = (float) 1 / (float) f_flag;
|
|
break;
|
|
case 'x': /* get filename with Z80 executable */
|
|
x_flag = 1;
|
|
s++;
|
|
p = xfn;
|
|
while (*s)
|
|
*p++ = *s++;
|
|
*p = '\0';
|
|
s--;
|
|
break;
|
|
case '?':
|
|
goto usage;
|
|
default:
|
|
printf("illegal option %c\n", *s);
|
|
usage: printf("usage:\t%s -s -l -i -h -mn -fn -xfilename\n", pn);
|
|
puts("\ts = save core and cpu");
|
|
puts("\tl = load core and cpu");
|
|
puts("\ti = trap on I/O to unused ports");
|
|
puts("\th = execute HALT op-code");
|
|
puts("\tm = init memory with n");
|
|
puts("\tf = CPU frequenzy n in MHz (not implemented yet)");
|
|
puts("\tx = load and execute filename");
|
|
exit(1);
|
|
}
|
|
|
|
putchar('\n');
|
|
puts("####### ##### ### ##### ### # #");
|
|
puts(" # # # # # # # # ## ##");
|
|
puts(" # # # # # # # # # # #");
|
|
puts(" # ##### # # ##### ##### # # # #");
|
|
puts(" # # # # # # # # #");
|
|
puts(" # # # # # # # # # #");
|
|
puts("####### ##### ### ##### ### # #");
|
|
printf("\nRelease %s, %s\n", RELEASE, COPYR);
|
|
#ifdef USR_COM
|
|
printf("%s Release %s, %s\n", USR_COM, USR_REL, USR_CPR);
|
|
#endif
|
|
putchar('\n');
|
|
fflush(stdout);
|
|
|
|
wrk_ram = PC = STACK = ram;
|
|
memset((char *) ram, m_flag, 32768);
|
|
memset((char *) ram + 32768, m_flag, 32768);
|
|
if (l_flag)
|
|
load_core();
|
|
int_on();
|
|
init_io();
|
|
mon();
|
|
if (s_flag)
|
|
save_core();
|
|
exit_io();
|
|
int_off();
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* This function saves the CPU and the memory into the file core.z80
|
|
*
|
|
*/
|
|
static void save_core(void)
|
|
{
|
|
int fd;
|
|
|
|
if ((fd = open("core.z80", O_WRONLY | O_CREAT, 0600)) == -1) {
|
|
puts("can't open file core.z80");
|
|
return;
|
|
}
|
|
write(fd, (char *) &A, sizeof(A));
|
|
write(fd, (char *) &F, sizeof(F));
|
|
write(fd, (char *) &B, sizeof(B));
|
|
write(fd, (char *) &C, sizeof(C));
|
|
write(fd, (char *) &D, sizeof(D));
|
|
write(fd, (char *) &E, sizeof(E));
|
|
write(fd, (char *) &H, sizeof(H));
|
|
write(fd, (char *) &L, sizeof(L));
|
|
write(fd, (char *) &A_, sizeof(A_));
|
|
write(fd, (char *) &F_, sizeof(F_));
|
|
write(fd, (char *) &B_, sizeof(B_));
|
|
write(fd, (char *) &C_, sizeof(C_));
|
|
write(fd, (char *) &D_, sizeof(D_));
|
|
write(fd, (char *) &E_, sizeof(E_));
|
|
write(fd, (char *) &H_, sizeof(H_));
|
|
write(fd, (char *) &L_, sizeof(L_));
|
|
write(fd, (char *) &I, sizeof(I));
|
|
write(fd, (char *) &IFF, sizeof(IFF));
|
|
write(fd, (char *) &R, sizeof(R));
|
|
write(fd, (char *) &PC, sizeof(PC));
|
|
write(fd, (char *) &STACK, sizeof(STACK));
|
|
write(fd, (char *) &IX, sizeof(IX));
|
|
write(fd, (char *) &IY, sizeof(IY));
|
|
write(fd, (char *) ram, 32768);
|
|
write(fd, (char *) ram + 32768, 32768);
|
|
close(fd);
|
|
}
|
|
|
|
/*
|
|
* This function loads the CPU and memory from the file core.z80
|
|
*
|
|
*/
|
|
static void load_core(void)
|
|
{
|
|
int fd;
|
|
|
|
if ((fd = open("core.z80", O_RDONLY)) == -1) {
|
|
puts("can't open file core.z80");
|
|
return;
|
|
}
|
|
read(fd, (char *) &A, sizeof(A));
|
|
read(fd, (char *) &F, sizeof(F));
|
|
read(fd, (char *) &B, sizeof(B));
|
|
read(fd, (char *) &C, sizeof(C));
|
|
read(fd, (char *) &D, sizeof(D));
|
|
read(fd, (char *) &E, sizeof(E));
|
|
read(fd, (char *) &H, sizeof(H));
|
|
read(fd, (char *) &L, sizeof(L));
|
|
read(fd, (char *) &A_, sizeof(A_));
|
|
read(fd, (char *) &F_, sizeof(F_));
|
|
read(fd, (char *) &B_, sizeof(B_));
|
|
read(fd, (char *) &C_, sizeof(C_));
|
|
read(fd, (char *) &D_, sizeof(D_));
|
|
read(fd, (char *) &E_, sizeof(E_));
|
|
read(fd, (char *) &H_, sizeof(H_));
|
|
read(fd, (char *) &L_, sizeof(L_));
|
|
read(fd, (char *) &I, sizeof(I));
|
|
read(fd, (char *) &IFF, sizeof(IFF));
|
|
read(fd, (char *) &R, sizeof(R));
|
|
read(fd, (char *) &PC, sizeof(PC));
|
|
read(fd, (char *) &STACK, sizeof(STACK));
|
|
read(fd, (char *) &IX, sizeof(IX));
|
|
read(fd, (char *) &IY, sizeof(IY));
|
|
read(fd, (char *) ram, 32768);
|
|
read(fd, (char *) ram + 32768, 32768);
|
|
close(fd);
|
|
}
|