home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************/
- /* */
- /* */
- /* CP/M emulator version 0.1 */
- /* */
- /* written by Michael Bischoff (mbi@mo.math.nat.tu-bs.de) */
- /* June-1994 */
- /* */
- /* This file is distributed under the GNU COPYRIGHT */
- /* see COPYRIGHT.GNU for Copyright details */
- /* */
- /* */
- /*****************************************************************************/
- #include "cpmemu.h"
- #include <ctype.h>
- #include <unistd.h>
-
- #define CPMLIBDIR "/usr/local/lib/cpm"
-
- struct z80regs z80regs,
- z80regs0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned short dmaaddr = 0x80;
- unsigned short usercode = 0x00;
- unsigned char z80mem[65536L+6];
- static int SPT = 64;
-
- union zeropage {
- struct c {
- uchar jpbyte0;
- ushrt wbootvec;
- uchar iobyte;
- uchar usrdrv;
- uchar jpbyte5;
- ushrt bdosvec;
- uchar fill1[0x54];
- uchar fcb[36];
- uchar dma[128];
- };
- uchar z[256];
- } zeropage;
-
- static char zeropage0[8] = {
- 0xc3, (BIOS+3) & 0xff, (BIOS+3) >> 8, 0x80, 0x00, 0xc3, BDOS & 0xff, BDOS >> 8 };
- static char cpmsys[0x1600];
- unsigned bios_dma = 0x80, bios_track = 0, bios_sector = 0;
- static FILE *bios_fp = NULL;
- static const char *cpmimage;
-
- /* BIOS data locations: */
- #define DPH0 (BIOS+0x36U)
- #define DPB0 (DPH0+16U)
- #define DATA_START (DPB0+15U)
- #define DIRBUF 0xff80U /* fixed! */
-
-
- static void make_jumpers(void) {
- int i;
- for (i = 0; i < 18; ++i) {
- /* make jump table at BIOS start. This HAS to be a true jump table, */
- /* since some programs rely on this */
- z80mem[BIOS+3*i] = 0xc3; /* Z80-jump instruction */
- z80mem[BIOS+3*i+1] = DIRBUF - 20 + i;
- z80mem[BIOS+3*i+2] = DIRBUF >> 8;
- }
- z80mem[0x38] = 0xc9; /* no interrupt */
- }
- /* just for information: */
- static struct dph {
- ushrt xlat, scr1, scr2, scr3;
- ushrt dirbuf;
- ushrt dpb;
- ushrt csv;
- ushrt alv;
- } dph0 = { 0, 0, 0, 0, DIRBUF, DPB0, 0, 0 };
-
- void cpm_init(const char *imagefile, const char *systemfile, struct dpb *dpb0) {
- register unsigned i;
- FILE *fp;
-
- cpmimage = imagefile;
- memset(z80mem+0x100, 0x76, sizeof(z80mem)-0x100); /* HALT insn */
-
- if (!(fp = fopen(systemfile, "rb"))) {
- fprintf(stderr, "cpm: cannot open system file \"%s\"\n", systemfile);
- exit(1);
- }
- fread(cpmsys, 0x1600, 1, fp);
- if (!cpmsys[0] && !cpmsys[1] && !cpmsys[2]) {
- memmove(cpmsys, cpmsys+5, 0x806);
- memmove(cpmsys+0x806, cpmsys+0x806+7, 0xe00-13);
- }
- fclose(fp);
-
- for (i = 0; i <= NBREAKS; ++i)
- breakpoint[i].action = 0;
-
- for (i = 0; i < 8; ++i)
- zeropage.z[i] = zeropage0[i];
- for (i = 8; i < 256; ++i)
- zeropage.z[i] = 0x76;
- memcpy(z80mem, zeropage.z, 0x100);
- memcpy(z80mem+BIOS-0x1600, cpmsys, 0x1600);
-
- dpb0->blm = (1 << dpb0->bsh) - 1;
- dpb0->exm = dpb0->blm >> 3;
- if (dpb0->dsm >= 256)
- dpb0->exm >>= 1;
- /* build alloc0, alloc1 bitmasks */
- { int bits = ((int)dpb0->drm + 1) / ((int)dpb0->blm + 1) / 4;
- if (bits <= 8) {
- dpb0->alloc0 = 256 - (256 >> bits);
- dpb0->alloc1 = 0;
- } else {
- dpb0->alloc0 = 255;
- dpb0->alloc1 = 256 - (256 >> (bits-8));
- }
- }
-
- SPT = dpb0->spt;
- /* Transfer dpb */
- z80mem[DPB0+ 0] = dpb0->spt & 0xff;
- z80mem[DPB0+ 1] = dpb0->spt >> 8;
- z80mem[DPB0+ 2] = dpb0->bsh;
- z80mem[DPB0+ 3] = dpb0->blm;
- z80mem[DPB0+ 4] = dpb0->exm;
- z80mem[DPB0+ 5] = dpb0->dsm & 0xff;
- z80mem[DPB0+ 6] = dpb0->dsm >> 8;
- z80mem[DPB0+ 7] = dpb0->drm & 0xff;
- z80mem[DPB0+ 8] = dpb0->drm >> 8;
- z80mem[DPB0+ 9] = dpb0->alloc0;
- z80mem[DPB0+10] = dpb0->alloc1;
- z80mem[DPB0+11] = dpb0->cks & 0xff;
- z80mem[DPB0+12] = dpb0->cks >> 8;
- z80mem[DPB0+13] = dpb0->off & 0xff;
- z80mem[DPB0+14] = dpb0->off >> 8;
-
- i = DATA_START; /* begin allocating csv & alv */
- dph0.csv = i;
- i += dpb0->cks;
- dph0.alv = i;
- i += (dpb0->dsm+1 + 7) >> 3;
- if (i > DIRBUF-16) {
- fprintf(stderr, "Error configuring BIOS tables: out of memory!\n");
- exit(1);
- }
- /* Transfer dph */
- memcpy(z80mem+DPH0, &dph0, 16);
-
- make_jumpers();
- z80regs.sp = 0x80;
- }
-
- void loadfile(const char *name) {
- FILE *fp;
- unsigned p;
-
- if (!(fp = fopen(name, "rb"))) {
- fprintf(stderr, "cpm: cannot open file \"%s\"\n", name);
- exit(1);
- }
- p = 256;
- while (fread(z80mem+p, 1, 256, fp) == 256)
- p += 256;
- fclose(fp);
- }
-
- void cpminit2(int argc, char *argv[]) {
- z80mem[0x80] = 0;
- z80mem[0x81] = 0x0d;
- z80regs = z80regs0;
- z80regs.pc = BIOS-0x1600;
- z80regs.bc = 0;
- if (argc) {
- /* transfer command line into CCP */
- int i, p;
- p = BIOS - 0x1600 + 8;
- for (i = 0; i < argc; ++i) {
- char *s; /* transfer one arg */
- if (i)
- z80mem[p++] = ' ';
- for (s = argv[i]; *s; )
- z80mem[p++] = *s++;
- if (p > BIOS - 0x1600 + 128)
- break;
- }
- z80mem[p] = 0;
- z80mem[BIOS - 0x1600 + 7] = p - (BIOS - 0x1600 + 8);
- { unsigned char *s;
- for (s = z80mem + BIOS - 0x1600 + 8; *s; ++s)
- if (islower(*s))
- *s = toupper(*s);
- }
- silent_exit = 1;
- /* patch CCP return: */
- for (p = BDOS; p > BIOS-0x1600; --p)
- if (z80mem[p] == 0xcd && z80mem[p+1] == 0x00 && z80mem[p+2] == 0x01) {
- z80mem[p+3] = 0xc3;
- z80mem[p+4] = (unsigned char)(BIOS & 0xffU);
- z80mem[p+5] = (unsigned char)(BIOS>>8);
- break;
- }
- if (p == BIOS-0x1600) {
- fprintf(stderr, "FATAL: cannot patch CCP return address\n");
- exit(1);
- }
- }
- }
-
-
- /* return 0 = invalid (TRAP), 1 = BIOS hook */
- extern jmp_buf mainloop;
- static int storedfps = 0;
-
- static void open_image(void) {
- if (!(bios_fp = fopen(cpmimage, "r+b"))) {
- fprintf(stderr, "cpm: cannot open disk image \"%s\"\n", cpmimage);
- exit(1);
- }
- }
-
-
- int check_BIOS_hook(void) {
- int i;
- static uchar buffbios[128];
- static int currdsk = 0;
-
- if (z80regs.pc >= BIOS) {
- switch (z80regs.pc) {
- case BIOS: /* System Reset (coldboot) */
- case DIRBUF-20:
- if (!silent_exit)
- printf("\nCp/M BIOS COLDBOOT takes you back to Linux\n");
- exit(0);
- case BIOS+3: /* System Reset (warmboot) */
- case DIRBUF-19:
- if (silent_exit)
- exit(0);
- storedfps = 0; /* clean up! */
- for (i = 0; i < 0x1600; ++i)
- z80mem[i+BIOS-0x1600] = cpmsys[i];
- for (i = 0; i < 8; ++i)
- z80mem[i] = zeropage.z[i];
- z80regs.bc = 0;
- z80regs.pc = BIOS-0x1600+3;
- z80regs.sp = 0x80;
- make_jumpers();
- if (bios_fp)
- fflush(bios_fp); /* prepare for disk change */
- return 1;
- case BIOS+6: /* Console Status */
- case DIRBUF-18:
- z80regs.af = kbhit() ? 0xff : 0x00;
- ret1:
- z80mem[z80regs.pc=DIRBUF-1] = 0xc9;
- return 1;
- case BIOS+9: /* Console In */
- case DIRBUF-17:
- z80regs.af = conin();
- goto ret1;
- case BIOS+12: /* Console Out */
- case DIRBUF-16:
- vt52(z80regs.bc & 0xff);
- goto ret1;
- case BIOS+15: /* List Out */
- case DIRBUF-15:
- goto ret1;
- case BIOS+18: /* Punch Out */
- case DIRBUF-14:
- goto ret1;
- case BIOS+21: /* Reader In */
- case DIRBUF-13:
- z80regs.af = 0;
- goto ret1;
- case BIOS+24: /* Home */
- case DIRBUF-12:
- bios_track = 0;
- bios_sector = 0;
- goto ret1;
- case BIOS+27: /* Seldsk */
- case DIRBUF-11:
- currdsk = z80regs.bc & 0xff;
- if (z80regs.bc & 0xff)
- z80regs.hl = 0xffff;
- else
- z80regs.hl = DPH0;
- goto ret1;
- case BIOS+30: /* Settrack */
- case DIRBUF-10:
- bios_track = z80regs.bc;
- goto ret1;
- case BIOS+33: /* Set sector */
- case DIRBUF- 9:
- bios_sector = z80regs.bc & 0xff;
- goto ret1;
- case BIOS+36: /* Set dma */
- case DIRBUF- 8:
- bios_dma = z80regs.bc;
- goto ret1;
- case BIOS+39: /* Read */
- case DIRBUF- 7:
- if (currdsk) {
- fprintf(stderr, "BDOS Err on %c: Select\n", currdsk+'A');
- exit(1);
- }
- if (!bios_fp)
- open_image();
- fseek(bios_fp, ((long)bios_sector + (long)SPT * (long)bios_track) * 128L, 0);
- fread(buffbios, 1, 128, bios_fp);
- for (i = 0; i < 128; ++i)
- z80mem[i + bios_dma] = buffbios[i];
- z80regs.af = 0;
- goto ret1;
- case BIOS+42: /* Write */
- case DIRBUF- 6:
- if (currdsk) {
- fprintf(stderr, "BDOS Err on %c: Select\n", currdsk+'A');
- exit(1);
- }
- if (!bios_fp)
- open_image();
- fseek(bios_fp, ((long)bios_sector + (long)SPT * (long)bios_track) * 128L, 0);
- for (i = 0; i < 128; ++i)
- buffbios[i] = z80mem[i + bios_dma];
- fwrite(buffbios, 1, 128, bios_fp);
- z80regs.af = 0;
- goto ret1;
- case BIOS+45: /* List Status */
- case DIRBUF- 5:
- z80regs.af = 0; /* not ready */
- goto ret1;
- case BIOS+48: /* Sectran */ /* no sectran */
- case DIRBUF- 4:
- z80regs.hl = z80regs.bc & 0xff;
- goto ret1;
- default:
- printf("Program traps in BIOS:\n");
- debug = 1;
- longjmp(mainloop, 1);
- }
- }
- return 0;
- }
-
- /* #include "cpmemu.h" */
-
- #if 0
- static struct FCB {
- char drive;
- char name[11];
- char data[24];
- } samplefcb;
- #endif
- static void FCB_to_filename(unsigned char *p, char *name) {
- int i;
- /* strcpy(name, "test/");
- name += 5; */
- for (i = 0; i < 8; ++i)
- if (p[i+1] != ' ')
- *name++ = tolower(p[i+1]);
- if (p[9] != ' ') {
- *name++ = '.';
- for (i = 0; i < 3; ++i)
- if (p[i+9] != ' ')
- *name++ = tolower(p[i+9]);
- }
- *name = '\0';
- }
-
- static struct stfps {
- FILE *fp;
- unsigned where;
- char name[12];
- } stfps[100];
-
- static void storefp(FILE *fp, unsigned where) {
- int i;
- int ind = -1;
- for (i = 0; i < storedfps; ++i)
- if (stfps[i].where == 0xffffU)
- ind = i;
- else if (stfps[i].where == where) {
- ind = i;
- goto putfp;
- }
- if (ind < 0) {
- if (++storedfps > 100) {
- fprintf(stderr, "out of fp stores!\n");
- exit(1);
- }
- ind = storedfps - 1;
- }
- stfps[ind].where = where;
- putfp:
- stfps[ind].fp = fp;
- memcpy(stfps[ind].name, z80mem+z80regs.de+1, 11);
- stfps[ind].name[11] = '\0';
- }
- #if 1
- static FILE *getfp(unsigned where) {
- int i;
- for (i = 0; i < storedfps; ++i)
- if (stfps[i].where == where) {
- /* check name? */
- return stfps[i].fp;
- }
- /* fcb not found. maybe it has been moved? */
- for (i = 0; i < storedfps; ++i)
- if (stfps[i].where != 0xffffU &&
- !memcmp(z80mem+z80regs.de+1, stfps[i].name, 11)) {
- stfps[i].where = where; /* moved FCB */
- return stfps[i].fp;
- }
-
- fprintf(stderr, "error: cannot find fp entry for FCB at %04x"
- " fctn %d, FCB named %s\n", where, z80regs.bc & 0xff,
- z80mem+where+1);
- for (i = 0; i < storedfps; ++i)
- if (stfps[i].where != 0xffffU)
- printf("%s %04x\n", stfps[i].name, stfps[i].where);
- exit(1);
- }
- static void delfp(unsigned where) {
- int i;
- for (i = 0; i < storedfps; ++i)
- if (stfps[i].where == where) {
- stfps[i].where = 0xffffU;
- return;
- }
- fprintf(stderr, "error: cannot del fp entry for FCB at %04x\n", where);
- exit(1);
- }
- #endif
-
-
-
- #include <dirent.h>
- #include <sys/stat.h>
-
- #define ADDRESS (((long)z80mem[z80regs.de+33] + \
- (long)z80mem[z80regs.de+34] * 256) * 128L)
- /* (long)z80mem[z80regs.de+35] * 65536L; */
-
- static DIR *dp = NULL;
- static unsigned sfn = 0;
-
- /* emulation of BDOS calls */
-
- void check_BDOS_hook(void) {
- int i;
- char name[32];
- char name2[32];
- struct stat stbuf;
- FILE *fp;
- char *s, *t;
- const char *mode;
- switch (z80regs.bc & 0xff) {
- case 0: /* System Reset */
- if (silent_exit) {
- /* printf("\nProgram terminates normally (BDOS function 0)\n"); */
- exit(0);
- }
- for (i = 0; i < 0x1600; ++i)
- z80mem[i+BIOS-0x1600] = cpmsys[i];
- z80regs.bc = 0;
- z80regs.pc = BIOS-0x1600+3;
- z80regs.sp = 0x80;
- break;
- case 1: /* Console Input */
- z80regs.af = z80regs.hl = conin();
- if ((z80regs.hl & 0xff) < ' ') {
- switch(z80regs.hl) {
- case '\r':
- case '\n':
- case '\t':
- putch(z80regs.hl);
- break;
- default:
- putch('^');
- putch((z80regs.hl & 0xff)+'@');
- if (z80regs.hl == 3) { /* ctrl-C pressed */
- z80regs.pc = BIOS+3;
- check_BIOS_hook();
- return;
- }
- }
- } else {
- vt52(z80regs.hl);
- }
- break;
- case 2: /* Console Output */
- vt52(z80regs.de & 0xff);
- break;
- case 6: /* direct I/O */
- switch (z80regs.de & 0xff) {
- case 0xff: if (!kbhit()) {
- z80regs.af = z80regs.hl = 0;
- break;
- }
- case 0xfd: z80regs.af = z80regs.hl = conin();
- break;
- case 0xfe: z80regs.af = z80regs.hl = kbhit() ? 0xff : 0;
- break;
- default: vt52(z80regs.de & 0xff);
- }
- break;
- case 9: /* Print String */
- s = z80mem +z80regs.de;
- while (*s != '$')
- vt52(*s++);
- break;
- case 10: /* Read Command Line */
- s = rdcmdline(*(t = z80mem+z80regs.de), 1);
- if (z80regs.pc == BIOS+3) { /* ctrl-C pressed */
- check_BIOS_hook(); /* execute WBOOT */
- return;
- }
- ++t;
- for (i = 0; i <= *s; ++i)
- t[i] = s[i];
- break;
- case 12: /* Return Version Number */
- z80regs.af = z80regs.hl = 0x22; /* emulate Cp/M 2.2 */
- break;
- case 26: /* Set DMA Address */
- dmaaddr = z80regs.de;
- break;
- case 32: /* Get/Set User Code */
- if (z80regs.de & 0xff == 0xff) /* Get Code */
- z80regs.af = z80regs.hl = usercode;
- else
- usercode = z80regs.de & 0x0f;
- break;
-
- /* dunno if these are correct */
-
- case 11: /* Console Status */
- z80regs.af = z80regs.hl = kbhit() ? 0xff : 0x00;
- break;
-
- case 13: /* reset disk system */
- /* storedfps = 0; */ /* WS crashes then */
- if (dp)
- closedir(dp);
- dp = NULL;
- dmaaddr = 0x80;
- /* select only A:, all r/w */
- break;
- case 14: /* select disk */
- break;
- case 15: /* open file */
- mode = "r+b";
- fileio:
- FCB_to_filename(z80mem+z80regs.de, name);
- if (!(fp = fopen(name, mode))) {
- if (*mode == 'r') {
- char ss[50];
- sprintf(ss, "%s/%s", CPMLIBDIR, name);
- fp = fopen(ss, "rb");
- }
- if (!fp) {
- /* still no success */
- z80regs.af = z80regs.hl = 0xff;
- break;
- }
- }
- /* success */
- memset(z80mem+z80regs.de+12, 0, 33-12);
- z80mem[z80regs.de+15] = 0; /* rc field of FCB */
- if (fstat(fileno(fp), &stbuf) || !S_ISREG(stbuf.st_mode)) {
- z80regs.af = z80regs.hl = 0xff;
- fclose(fp);
- break;
- }
- { unsigned long pos;
- pos = (stbuf.st_size + 127) >> 7; /* number of records */
- if (pos > 128)
- z80mem[z80regs.de+15] = 0x80;
- else
- z80mem[z80regs.de+15] = pos;
- }
- z80regs.af = z80regs.hl = 0;
- /* where to store fp? */
- storefp(fp, z80regs.de);
- /* printf("opening file %s\n", name); */
- break;
- case 16: /* close file */
- fp = getfp(z80regs.de);
- delfp(z80regs.de);
- fclose(fp);
- break;
- case 17: /* search for first */
- if (dp)
- closedir(dp);
- if (!(dp = opendir("."))) {
- fprintf(stderr, "opendir fails\n");
- exit(1);
- }
- sfn = z80regs.de;
- /* fall through */
- case 18: /* search for next */
- if (!dp)
- goto retbad;
- { struct dirent *de;
- unsigned char *p;
- const char *sr;
- nocpmname:
- if (!(de = readdir(dp))) {
- closedir(dp);
- dp = NULL;
- retbad:
- z80regs.af = z80regs.hl = 0xff;
- break;
- }
- /* compare data */
- memset(p = z80mem+dmaaddr, 0, 128); /* dmaaddr instead of DIRBUF!! */
- if (*de->d_name == '.')
- goto nocpmname;
- if (strchr(sr = de->d_name, '.')) {
- if (de->d_reclen > 12) /* POSIX: namlen */
- goto nocpmname;
- } else if (de->d_reclen > 8)
- goto nocpmname;
- /* seems OK */
- for (i = 0; i < 8; ++i)
- if (*sr != '.' && *sr) {
- *++p = toupper(*sr); sr++;
- } else
- *++p = ' ';
- /* skip dot */
- while (*sr && *sr != '.')
- ++sr;
- while (*sr == '.')
- ++sr;
- for (i = 0; i < 3; ++i)
- if (*sr != '.' && *sr) {
- *++p = toupper(*sr); sr++;
- } else
- *++p = ' ';
- /* OK, fcb block is filled */
- /* match name */
- p -= 11;
- sr = z80mem+sfn;
- for (i = 1; i <= 12; ++i)
- if (sr[i] != '?' && sr[i] != p[i])
- goto nocpmname;
- /* yup, it matches */
- z80regs.af = z80regs.hl = 0x00; /* always at pos 0 */
- p[32] = p[64] = p[96] = 0xe5;
- }
- break;
- case 19: /* delete file (no wildcards yet) */
- FCB_to_filename(z80mem+z80regs.de, name);
- unlink(name);
- break;
- case 20: /* read sequential */
- fp = getfp(z80regs.de);
- readseq:
- if ((i = fread(z80mem+dmaaddr, 1, 128, fp)) > 0) {
- if (i != 128)
- memset(z80mem+dmaaddr+i, 0x1a, 128-i);
- z80regs.af = z80regs.hl = 0x00;
- } else
- z80regs.af = z80regs.hl = 0x1; /* ff => pip error */
- break;
- case 21: /* write sequential */
- fp = getfp(z80regs.de);
- writeseq:
- if (fwrite(z80mem+dmaaddr, 1, 128, fp) == 128)
- z80regs.af = z80regs.hl = 0x00;
- else
- z80regs.af = z80regs.hl = 0xff;
- break;
- case 22: /* make file */
- mode = "w+b";
- goto fileio;
- case 23: /* rename file */
- FCB_to_filename(z80mem+z80regs.de, name);
- FCB_to_filename(z80mem+z80regs.de+16, name2);
- /* printf("rename %s %s called\n", name, name2); */
- rename(name, name2);
- break;
- case 24: /* return login vector */
- z80regs.af = z80regs.hl = 1; /* only A: online */
- break;
- case 25: /* return current disk */
- z80regs.af = z80regs.hl = 0; /* only A: */
- break;
- case 29: /* return r/o vector */
- z80regs.af = z80regs.hl = 0; /* none r/o */
- break;
- case 33: /* read random record */
- fp = getfp(z80regs.de);
- /* printf("data is %02x %02x %02x\n", z80mem[z80regs.de+33],
- z80mem[z80regs.de+34], z80mem[z80regs.de+35]); */
- fseek(fp, ADDRESS, SEEK_SET);
- goto readseq;
- case 34: /* write random record */
- fp = getfp(z80regs.de);
- /* printf("data is %02x %02x %02x\n", z80mem[z80regs.de+33],
- z80mem[z80regs.de+34], z80mem[z80regs.de+35]); */
- fseek(fp, ADDRESS, SEEK_SET);
- goto writeseq;
- case 35: /* compute file size */
- fp = getfp(z80regs.de);
- fseek(fp, 0L, SEEK_END);
- /* fall through */
- case 36: /* set random record */
- fp = getfp(z80regs.de);
- { long pos;
- pos = ftell(fp) >> 7;
- z80regs.af = z80regs.hl = 0x00; /* dunno, if necessary */
- z80mem[z80regs.de+21] = pos & 0xff;
- z80mem[z80regs.de+22] = pos >> 8;
- z80mem[z80regs.de+23] = pos >> 16;
- }
- break;
- case 41:
- for (s = z80mem+z80regs.de; *s; ++s)
- *s = tolower(*s);
- z80regs.af = z80regs.hl =
- restricted_mode || chdir(z80mem+z80regs.de) ? 0xff : 0x00;
- break;
- default:
- printf("\n\nUnrecognized BDOS-Function:\n");
- printf("AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x\nStack =",
- z80regs.af, z80regs.bc, z80regs.de, z80regs.hl, z80regs.sp);
- for (i = 0; i < 8; ++i)
- printf(" %4x", z80mem[z80regs.sp+2*i]
- + 256 * z80mem[z80regs.sp+2*i+1]);
- printf("\n");
- exit(1);
- }
- z80mem[z80regs.pc=DIRBUF-1] = 0xc9;
- return;
- }
-