void check_BDOS_hook(z80info *z80) { int i; char name[32]; char name2[32]; FILE *fp; char *s, *t; const char *mode; if (trace_bdos) { printf("\r\nbdos %d %s (AF=%04x BC=%04x DE=%04x HL =%04x SP=%04x STACK=", C, bdos_decode(C), AF, BC, DE, HL, SP); for (i = 0; i < 8; ++i) printf(" %4x", z80->mem[SP + 2*i] + 256 * z80->mem[SP + 2*i + 1]); printf(")\r\n"); } switch (C) { case 0: /* System Reset */ warmboot(z80); return; #if 0 for (i = 0; i < 0x1600; ++i) z80->mem[i+BIOS-0x1600] = cpmsys[i]; BC = 0; PC = BIOS-0x1600+3; SP = 0x80; #endif break; case 1: /* Console Input */ HL = kget(0); B = H; A = L; if (A < ' ') { switch(A) { case '\r': case '\n': case '\t': vt52(A); break; default: vt52('^'); vt52((A & 0xff)+'@'); if (A == 3) { /* ctrl-C pressed */ /* PC = BIOS+3; check_BIOS_hook(); */ warmboot(z80); return; } } } else { vt52(A); } break; case 2: /* Console Output */ vt52(0x7F & E); HL = 0; B = H; A = L; break; case 6: /* direct I/O */ switch (E) { case 0xff: if (!constat()) { HL = 0; B = H; A = L; F = 0; break; } case 0xfd: HL = kget(0); B = H; A = L; F = 0; break; case 0xfe: HL = constat() ? 0xff : 0; B = H; A = L; F = 0; break; default: vt52(0x7F & E); HL = 0; B = H; A = L; } break; case 9: /* Print String */ s = (char *)(z80->mem + DE); while (*s != '$') vt52(0x7F & *s++); HL = 0; B = H; A = L; break; case 10: /* Read Command Line */ s = rdcmdline(z80, *(unsigned char *)(t = (char *)(z80->mem + DE)), 1); if (PC == BIOS+3) { /* ctrl-C pressed */ /* check_BIOS_hook(); */ /* execute WBOOT */ warmboot(z80); return; } ++t; for (i = 0; i <= *(unsigned char *)s; ++i) t[i] = s[i]; HL = 0; B = H; A = L; break; case 12: /* Return Version Number */ HL = 0x22; /* Emulate CP/M 2.2 */ B = H; A = L; F = 0; break; case 26: /* Set DMA Address */ z80->dma = DE; HL = 0; B = H; A = L; break; case 32: /* Get/Set User Code */ if (E == 0xff) { /* Get Code */ HL = usercode; B = H; A = L; } else { usercode = E; HL = 0; /* Or does it get usercode? */ B = H; A = L; } break; /* dunno if these are correct */ case 11: /* Console Status */ HL = (constat() ? 0xff : 0x00); B = H; A = L; F = 0; break; case 13: /* reset disk system */ /* storedfps = 0; */ /* WS crashes then */ if (dp) closedir(dp); dp = NULL; z80->dma = 0x80; HL = 0; B = H; A = L; /* select only A:, all r/w */ break; case 14: /* select disk */ HL = 0; B = H; A = L; break; case 15: /* open file */ mode = "r+b"; fileio: FCB_to_filename(z80->mem+DE, name); /* Try lowercase */ if (!(fp = fopen(name, mode))) { FCB_to_ufilename(z80->mem+DE, name); /* Try all uppercase instead */ if (!(fp = fopen(name, mode))) { FCB_to_filename(z80->mem+DE, name); if (*mode == 'r') { char ss[50]; sprintf(ss, "%s/%s", CPMLIBDIR, name); fp = fopen(ss, mode); if (!fp) fp = fopen(ss, "rb"); } if (!fp) { /* still no success */ HL = 0xFF; B = H; A = L; F = 0; break; } } } /* success */ /* memset(z80->mem + DE + 12, 0, 33-12); */ /* User has to set EX, S2, and CR: don't change these- some set them to non-zero */ z80->mem[DE + FCB_S1] = 0; /* memset(z80->mem + DE + 16, 0, 16); */ /* Clear D0-Dn */ /* Should we clear R0 - R2? Nope: then we overlap the following area. */ /* memset(z80->mem + DE + 33, 0, 3); */ /* We need to set high bit of S2: means file is open? */ z80->mem[DE + FCB_S2] |= 0x80; z80->mem[DE + FCB_RC] = 0; /* rc field of FCB */ if (fixrc(z80, fp)) { /* Not a real file? */ HL = 0xFF; B = H; A = L; F = 0; fclose(fp); break; } HL = 0; B = H; A = L; F = 0; /* where to store fp? */ storefp(z80, fp, DE); /* printf("opening file %s\n", name); */ break; case 16: /* close file */ z80->mem[DE + FCB_S2] &= 0x7F; /* Clear high bit: indicates closed */ fp = getfp(z80, DE); delfp(z80, DE); fclose(fp); HL = 0; B = H; A = L; /* printf("close file\n"); */ break; case 17: /* search for first */ if (dp) closedir(dp); if (!(dp = opendir("."))) { fprintf(stderr, "opendir fails\n"); resetterm(); exit(1); } sfn = 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: HL = 0xff; B = H; A = L; F = 0; break; } /* printf("\r\nlooking at %s\r\n", de->d_name); */ /* compare data */ memset(p = z80->mem+z80->dma, 0, 128); /* dmaaddr instead of DIRBUF!! */ if (*de->d_name == '.') goto nocpmname; if (strchr(sr = de->d_name, '.')) { if (strlen(de->d_name) > 12) /* POSIX: namlen */ goto nocpmname; } else if (strlen(de->d_name) > 8) goto nocpmname; /* seems OK */ for (i = 0; i < 8; ++i) if (*sr != '.' && *sr) { *++p = toupper(*(unsigned char *)sr); sr++; } else *++p = ' '; /* skip dot */ while (*sr && *sr != '.') ++sr; while (*sr == '.') ++sr; for (i = 0; i < 3; ++i) if (*sr != '.' && *sr) { *++p = toupper(*(unsigned char *)sr); sr++; } else *++p = ' '; /* OK, fcb block is filled */ /* match name */ p -= 11; sr = (char *)(z80->mem + sfn); for (i = 1; i <= 12; ++i) if (sr[i] != '?' && sr[i] != p[i]) goto nocpmname; /* yup, it matches */ HL = 0x00; /* always at pos 0 */ B = H; A = L; F = 0; p[32] = p[64] = p[96] = 0xe5; } break; case 19: /* delete file (no wildcards yet) */ FCB_to_filename(z80->mem + DE, name); unlink(name); HL = 0; B = H; A = L; break; case 20: /* read sequential */ fp = getfp(z80, DE); readseq: if (!fseek(fp, SEQ_ADDRESS, SEEK_SET) && ((i = fread(z80->mem+z80->dma, 1, 128, fp)) > 0)) { long ofst = ftell(fp) + 127; if (i != 128) memset(z80->mem+z80->dma+i, 0x1a, 128-i); z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); fixrc(z80, fp); HL = 0x00; B = H; A = L; } else { HL = 0x1; /* ff => pip error */ B = H; A = L; } break; case 21: /* write sequential */ fp = getfp(z80, DE); writeseq: if (!fseek(fp, SEQ_ADDRESS, SEEK_SET) && fwrite(z80->mem+z80->dma, 1, 128, fp) == 128) { long ofst = ftell(fp); z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); fixrc(z80, fp); HL = 0x00; B = H; A = L; } else { HL = 0xff; B = H; A = L; } break; case 22: /* make file */ mode = "w+b"; goto fileio; case 23: /* rename file */ FCB_to_filename(z80->mem + DE, name); FCB_to_filename(z80->mem + DE + 16, name2); /* printf("rename %s %s called\n", name, name2); */ rename(name, name2); HL = 0; B = H; A = L; break; case 24: /* return login vector */ HL = 1; /* only A: online */ B = H; A = L; F = 0; break; case 25: /* return current disk */ HL = 0; /* only A: */ B = H; A = L; F = 0; break; case 29: /* return r/o vector */ HL = 0; /* none r/o */ B = H; A = L; F = 0; break; case 31: /* get disk parameters */ HL = DPB0; /* only A: */ B = H; A = L; break; case 33: /* read random record */ { long ofst; fp = getfp(z80, DE); /* printf("data is %02x %02x %02x\n", z80->mem[z80->regde+33], z80->mem[z80->regde+34], z80->mem[z80->regde+35]); */ ofst = ADDRESS; z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); goto readseq; } case 34: /* write random record */ { long ofst; fp = getfp(z80, DE); /* printf("data is %02x %02x %02x\n", z80->mem[z80->regde+33], z80->mem[z80->regde+34], z80->mem[z80->regde+35]); */ ofst = ADDRESS; z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); goto writeseq; } case 35: /* compute file size */ fp = getfp(z80, DE); fseek(fp, 0L, SEEK_END); /* fall through */ case 36: /* set random record */ fp = getfp(z80, DE); { long ofst = ftell(fp) + 127; long pos = (ofst >> 7); HL = 0x00; /* dunno, if necessary */ B = H; A = L; z80->mem[DE + FCB_R0] = pos & 0xff; z80->mem[DE + FCB_R1] = pos >> 8; z80->mem[DE + FCB_R2] = pos >> 16; z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); fixrc(z80, fp); } break; case 41: for (s = (char *)(z80->mem + DE); *s; ++s) *s = tolower(*(unsigned char *)s); HL = (restricted_mode || chdir((char *)(z80->mem + DE))) ? 0xff : 0x00; B = H; A = L; break; default: printf("\n\nUnrecognized BDOS-Function:\n"); printf("AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x\nStack =", AF, BC, DE, HL, SP); for (i = 0; i < 8; ++i) printf(" %4x", z80->mem[SP + 2*i] + 256 * z80->mem[SP + 2*i + 1]); printf("\r\n"); resetterm(); exit(1); } z80->mem[PC = DIRBUF-1] = 0xc9; /* Return instruction */ return; }
static void boot(z80info *z80) { z80->drive = 0; warmboot(z80); }
void main(void) { warmboot(); }