|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 15042 (0x3ac2) Types: TextFile Names: »msdos.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Nethack/msdos.c«
/* SCCS Id: @(#)msdos.c 2.1 87/10/19 /* An assortment of MSDOS functions. */ #include <stdio.h> #include "hack.h" #ifdef MSDOS # include <dos.h> void flushout() { (void) fflush(stdout); } getuid() { return 1; } char * getlogin() { return ((char *) NULL); } # ifdef REDO tgetch() { char ch, popch(); static char DOSgetch(), BIOSgetch(); if (!(ch = popch())) { # ifdef DGK /* BIOSgetch can use the numeric key pad on IBM compatibles. */ if (flags.IBMBIOS) ch = BIOSgetch(); else # endif ch = DOSgetch(); } return ((ch == '\r') ? '\n' : ch); } # else /* REDO /**/ tgetch() { char ch; static char DOSgetch(), BIOSgetch(); # ifdef DGK /* BIOSgetch can use the numeric key pad on IBM compatibles. */ if (flags.IBMBIOS) ch = BIOSgetch(); else # endif ch = DOSgetch(); return ((ch == '\r') ? '\n' : ch); } # endif /* REDO /**/ # define DIRECT_INPUT 0x7 static char DOSgetch() { union REGS regs; regs.h.ah = DIRECT_INPUT; intdos(®s, ®s); if (!regs.h.al) { /* an extended code -- not yet supported */ regs.h.ah = DIRECT_INPUT; intdos(®s, ®s); /* eat the next character */ regs.h.al = 0; /* and return a 0 */ } return (regs.h.al); } # ifdef DGK # include <ctype.h> # include <fcntl.h> # define Sprintf (void) sprintf # define WARN 1 # define NOWARN 0 static char * getcomspec(warn) { return getenv("COMSPEC"); } # ifdef SHELL # include <process.h> dosh() { extern char orgdir[]; char *comspec; if (comspec = getcomspec()) { settty("To return to HACK, type \"exit\" at the DOS prompt.\n"); chdirx(orgdir, 0); if (spawnl(P_WAIT, comspec, comspec, NULL) < 0) { printf("\nCan't spawn %s !\n", comspec); flags.toplin = 0; more(); } chdirx(hackdir, 0); start_screen(); docrt(); } else pline("No COMSPEC !? Can't exec COMMAND.COM"); return(0); } # endif /* SHELL */ /* Normal characters are output when the shift key is not pushed. * Shift characters are output when either shift key is pushed. */ # define KEYPADHI 83 # define KEYPADLOW 71 # define iskeypad(x) (KEYPADLOW <= (x) && (x) <= KEYPADHI) static struct { char normal, shift; } keypad[KEYPADHI - KEYPADLOW + 1] = { {'y', 'Y'}, /* 7 */ {'k', 'K'}, /* 8 */ {'u', 'U'}, /* 9 */ {'m', CTRL('P')}, /* - */ {'h', 'H'}, /* 4 */ {'g', 'g'}, /* 5 */ {'l', 'L'}, /* 6 */ {'p', 'P'}, /* + */ {'b', 'B'}, /* 1 */ {'j', 'J'}, /* 2 */ {'n', 'N'}, /* 3 */ {'i', 'I'}, /* Ins */ {'.', ':'} /* Del */ }; /* BIOSgetch gets keys directly with a BIOS call. */ # define SHIFT (0x1 | 0x2) # define KEYBRD_BIOS 0x16 static char BIOSgetch() { unsigned char scan, shift, ch; union REGS regs; /* Get scan code. */ regs.h.ah = 0; int86(KEYBRD_BIOS, ®s, ®s); ch = regs.h.al; scan = regs.h.ah; /* Get shift status. */ regs.h.ah = 2; int86(KEYBRD_BIOS, ®s, ®s); shift = regs.h.al; /* If scan code is for the keypad, translate it. */ if (iskeypad(scan)) { if (shift & SHIFT) ch = keypad[scan - KEYPADLOW].shift; else ch = keypad[scan - KEYPADLOW].normal; } return ch; } /* construct the string file.level */ void name_file(file, level) char *file; int level; { char *tf; if (tf = rindex(file, '.')) Sprintf(tf+1, "%d", level); } # define FINDFIRST 0x4E00 # define FINDNEXT 0x4F00 # define GETDTA 0x2F00 # define SETFILETIME 0x5701 # define GETSWITCHAR 0x3700 # define FREESPACE 0x36 static char switchar() { union REGS regs; regs.x.ax = GETSWITCHAR; intdos(®s, ®s); return regs.h.dl; } long freediskspace(path) char *path; { union REGS regs; regs.h.ah = FREESPACE; if (path[0] && path[1] == ':') regs.h.dl = (toupper(path[0]) - 'A') + 1; else regs.h.dl = 0; intdos(®s, ®s); if (regs.x.ax == 0xFFFF) return -1L; /* bad drive number */ else return ((long) regs.x.bx * regs.x.cx * regs.x.ax); } /* Functions to get filenames using wildcards */ static findfirst(path) char *path; { union REGS regs; struct SREGS sregs; regs.x.ax = FINDFIRST; regs.x.cx = 0; /* normal files */ regs.x.dx = FP_OFF(path); sregs.ds = FP_SEG(path); intdosx(®s, ®s, &sregs); return !regs.x.cflag; } static findnext() { union REGS regs; regs.x.ax = FINDNEXT; intdos(®s, ®s); return !regs.x.cflag; } #ifndef __TURBOC__ /* Get disk transfer area, Turbo C already has getdta */ static char * getdta() { union REGS regs; struct SREGS sregs; char *ret; regs.x.ax = GETDTA; intdosx(®s, ®s, &sregs); FP_OFF(ret) = regs.x.bx; FP_SEG(ret) = sregs.es; return ret; } #endif long filesize(file) char *file; { char *dta; if (findfirst(file)) { dta = getdta(); return (* (long *) (dta + 26)); } else return -1L; } void eraseall(path, files) char *path, *files; { char *dta, buf[PATHLEN]; dta = getdta(); Sprintf(buf, "%s%s", path, files); if (findfirst(buf)) do { Sprintf(buf, "%s%s", path, dta + 30); (void) unlink(buf); } while (findnext()); } /* Rewritten for version 3.3 to be faster */ void copybones(mode) { char from[PATHLEN], to[PATHLEN], last[13], copy[8]; char *frompath, *topath, *dta, *comspec; int status; long fs; extern saveprompt; if (!ramdisk) return; /* Find the name of the last file to be transferred */ frompath = (mode != TOPERM) ? permbones : levels; dta = getdta(); last[0] = '\0'; Sprintf(from, "%s%s", frompath, allbones); if (findfirst(from)) do { strcpy(last, dta + 30); } while (findnext()); topath = (mode == TOPERM) ? permbones : levels; if (last[0]) { Sprintf(copy, "%cC copy", switchar()); /* Remove any bones files in `to' directory. */ eraseall(topath, allbones); /* Copy `from' to `to' */ Sprintf(to, "%s%s", topath, allbones); comspec = getcomspec(); status =spawnl(P_WAIT, comspec, comspec, copy, from, to, "> nul", NULL); } else return; /* See if the last file got there. If so, remove the ramdisk bones * files. */ Sprintf(to, "%s%s", topath, last); if (findfirst(to)) { if (mode == TOPERM) eraseall(frompath, allbones); return; } /* Last file didn't get there. */ Sprintf(to, "%s%s", topath, allbones); msmsg("Cannot copy `%s' to `%s' -- %s\n", from, to, (status < 0) ? "can't spawn COMSPEC !" : (freediskspace(topath) < filesize(from)) ? "insufficient disk space." : "bad path(s)?"); if (mode == TOPERM) { msmsg("Bones will be left in `%s'\n", *levels ? levels : hackdir); return; } else { /* Remove all bones files on the RAMdisk */ eraseall(levels, allbones); playwoRAMdisk(); } } playwoRAMdisk() { msmsg("Do you wish to play without a RAMdisk (y/n) ? "); /* Set ramdisk false *before* exit'ing (because msexit calls * copybones) */ ramdisk = FALSE; if (getchar() != 'y') { settty("Be seeing you ...\n"); exit(0); } set_lock_and_bones(); return; } saveDiskPrompt(start) { extern saveprompt; char buf[BUFSIZ], *bp; int fd; if (saveprompt) { /* Don't prompt if you can find the save file */ if ((fd = open(SAVEF, 0)) >= 0) { (void) close(fd); return 1; } remember_topl(); home(); cl_end(); msmsg("If save file is on a SAVE disk, put that disk in now.\n"); cl_end(); msmsg("File name (default `%s'%s) ? ", SAVEF, start ? "" : ", <Esc> cancels save"); getlin(buf); home(); cl_end(); curs(1, 2); cl_end(); if (!start && *buf == '\033') return 0; /* Strip any whitespace. Also, if nothing was entered except * whitespace, do not change the value of SAVEF. */ for (bp = buf; *bp; bp++) if (!isspace(*bp)) { strncpy(SAVEF, bp, PATHLEN); break; } } return 1; } /* Return 1 if the record file was found */ static record_exists() { int fd; if ((fd = open(RECORD, 0)) >= 0) { close(fd); return TRUE; } return FALSE; } /* Return 1 if the comspec was found */ static comspec_exists() { int fd; char *comspec; if (comspec = getcomspec()) if ((fd = open(comspec, 0)) >= 0) { close(fd); return TRUE; } return FALSE; } /* Prompt for game disk, then check for record file. */ void gameDiskPrompt() { extern saveprompt; if (saveprompt) { if (record_exists() && comspec_exists()) return; (void) putchar('\n'); getreturn("when the GAME disk has been put in"); } if (comspec_exists() && record_exists()) return; if (!comspec_exists()) msmsg("\n\nWARNING: can't find comspec `%s'!\n", getcomspec()); if (!record_exists()) msmsg("\n\nWARNING: can't find record file `%s'!\n", RECORD); msmsg("If the GAME disk is not in, put it in now.\n"); getreturn("to continue"); } /* Read configuration */ void read_config_file() { char tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN]; char buf[BUFSZ], *bufp; FILE *fp, *fopenp(); extern char plname[]; extern int saveprompt; tmp_ramdisk[0] = 0; tmp_levels[0] = 0; if ((fp = fopenp(configfile, "r")) == NULL) { msmsg("Warning: no configuration file!\n"); getreturn("to continue"); return; } while (fgets(buf, BUFSZ, fp)) { if (*buf == '#') continue; /* remove trailing whitespace */ bufp = index(buf, '\n'); while (bufp > buf && isspace(*bufp)) bufp--; if (bufp == buf) continue; /* skip all-blank lines */ else *(bufp + 1) = 0; /* 0 terminate line */ /* find the '=' */ if (!(bufp = strchr(buf, '='))) { msmsg("Bad option line: '%s'\n", buf); getreturn("to continue"); continue; } /* skip whitespace between '=' and value */ while (isspace(*++bufp)) ; /* Go through possible variables */ if (!strncmp(buf, "HACKDIR", 4)) { strncpy(hackdir, bufp, PATHLEN); } else if (!strncmp(buf, "RAMDISK", 3)) { strncpy(tmp_ramdisk, bufp, PATHLEN); } else if (!strncmp(buf, "LEVELS", 4)) { strncpy(tmp_levels, bufp, PATHLEN); } else if (!strncmp(buf, "OPTIONS", 4)) { parseoptions(bufp, TRUE); if (plname[0]) /* If a name was given */ plnamesuffix(); /* set the character class */ } else if (!strncmp(buf, "SAVE", 4)) { char *ptr; if (ptr = index(bufp, ';')) { *ptr = '\0'; if (*(ptr+1) == 'n' || *(ptr+1) == 'N') saveprompt = FALSE; } (void) strncpy(SAVEF, bufp, PATHLEN); append_slash(SAVEF); #ifdef GRAPHICS } else if (!strncmp(buf, "GRAPHICS", 4)) { char translate[17]; short i; if ((i = sscanf(bufp, "%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u", &translate[0], &translate[1], &translate[2], &translate[3], &translate[4], &translate[5], &translate[6], &translate[7], &translate[8], &translate[9], &translate[10], &translate[11], &translate[12], &translate[13], &translate[14], &translate[15], &translate[16])) < 0) { msmsg ("Syntax error in GRAPHICS\n"); getreturn("to continue"); } translate[i] = '\0'; #endif /* GRAPHICS /**/ /* * You could have problems here if you configure FOUNTAINS, SPIDERS or NEWCLASS * in or out and forget to change the tail entries in your graphics string. */ #define SETPCHAR(f, n) showsyms.f = (strlen(translate) > n) ? translate[n] : defsyms.f SETPCHAR(stone, 0); SETPCHAR(vwall, 1); SETPCHAR(hwall, 2); SETPCHAR(tlcorn, 3); SETPCHAR(trcorn, 4); SETPCHAR(blcorn, 5); SETPCHAR(brcorn, 6); SETPCHAR(door, 7); SETPCHAR(room, 8); SETPCHAR(corr, 9); SETPCHAR(upstair, 10); SETPCHAR(dnstair, 11); SETPCHAR(trap, 12); #ifdef FOUNTAINS SETPCHAR(pool, 13); SETPCHAR(fountain, 14); #endif #ifdef NEWCLASS SETPCHAR(throne, 15); #endif #ifdef SPIDERS SETPCHAR(web, 16); #endif #undef SETPCHAR } else { msmsg("Bad option line: '%s'\n", buf); getreturn("to continue"); } } fclose(fp); strcpy(permbones, tmp_levels); if (tmp_ramdisk[0]) { strcpy(levels, tmp_ramdisk); if (strcmpi(permbones, levels)) /* if not identical */ ramdisk = TRUE; } else strcpy(levels, tmp_levels); strcpy(bones, levels); } /* Set names for bones[] and lock[] */ void set_lock_and_bones() { if (!ramdisk) { strcpy(levels, permbones); strcpy(bones, permbones); } append_slash(permbones); append_slash(levels); append_slash(bones); strcat(bones, allbones); strcpy(lock, levels); strcat(lock, alllevels); } /* Add a backslash to any name not ending in /, \ or : There must * be room for the \ */ void append_slash(name) char *name; { char *ptr; if (!*name) return; ptr = name + (strlen(name) - 1); if (*ptr != '\\' && *ptr != '/' && *ptr != ':') { *++ptr = '\\'; *++ptr = '\0'; } } void getreturn(str) char *str; { int ch; msmsg("Hit <RETURN> %s.", str); while ((ch = getchar()) != '\n') ; } void msmsg(fmt, a1, a2, a3) char *fmt; long a1, a2, a3; { printf(fmt, a1, a2, a3); flushout(); } /* Chdrive() changes the default drive. */ #define SELECTDISK 0x0E void chdrive(str) char *str; { char *ptr; union REGS inregs; char drive; if ((ptr = index(str, ':')) != NULL) { drive = toupper(*(ptr - 1)); inregs.h.ah = SELECTDISK; inregs.h.dl = drive - 'A'; intdos(&inregs, &inregs); } } /* Use the IOCTL DOS function call to change stdin and stdout to raw * mode. For stdin, this prevents MSDOS from trapping ^P, thus * freeing us of ^P toggling 'echo to printer'. * Thanks to Mark Zbikowski (markz@microsoft.UUCP). */ # define DEVICE 0x80 # define RAW 0x20 # define IOCTL 0x44 # define STDIN fileno(stdin) # define STDOUT fileno(stdout) # define GETBITS 0 # define SETBITS 1 static unsigned old_stdin, old_stdout, ioctl(); disable_ctrlP() { if (!flags.rawio) return; old_stdin = ioctl(STDIN, GETBITS, 0); old_stdout = ioctl(STDOUT, GETBITS, 0); if (old_stdin & DEVICE) ioctl(STDIN, SETBITS, old_stdin | RAW); if (old_stdout & DEVICE) ioctl(STDOUT, SETBITS, old_stdout | RAW); } enable_ctrlP() { if (!flags.rawio) return; if (old_stdin) (void) ioctl(STDIN, SETBITS, old_stdin); if (old_stdout) (void) ioctl(STDOUT, SETBITS, old_stdout); } static unsigned ioctl(handle, mode, setvalue) unsigned setvalue; { union REGS regs; regs.h.ah = IOCTL; regs.h.al = mode; regs.x.bx = handle; regs.h.dl = setvalue; regs.h.dh = 0; /* Zero out dh */ intdos(®s, ®s); return (regs.x.dx); } /* Follow the PATH, trying to fopen the file. */ #define PATHSEP ';' FILE * fopenp(name, mode) char *name, *mode; { char buf[BUFSIZ], *bp, *pp, *getenv(), lastch; FILE *fp; /* Try the default directory first. Then look along PATH. */ strcpy(buf, name); if (fp = fopen(buf, mode)) return fp; else { pp = getenv("PATH"); while (pp && *pp) { bp = buf; while (*pp && *pp != PATHSEP) lastch = *bp++ = *pp++; if (lastch != '\\' && lastch != '/') *bp++ = '\\'; strcpy(bp, name); if (fp = fopen(buf, mode)) return fp; if (*pp) pp++; } } return NULL; } # endif /* DGK */ /* Chdir back to original directory */ # undef exit void msexit(code) { # ifdef CHDIR extern char orgdir[]; # endif # ifdef DGK flushout(); enable_ctrlP(); /* in case this wasn't done */ if (ramdisk) copybones(TOPERM); # endif # ifdef CHDIR chdir(orgdir); /* chdir, not chdirx */ # ifdef DGK chdrive(orgdir); # endif # endif exit(code); } #endif /* MSDOS */