billr@saab.CNA.TEK.COM (Bill Randle) (07/12/90)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 10, Issue 72 Archive-name: nethack3p9/Part27 Supersedes: NetHack3: Volume 7, Issue 56-93 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 27 (of 56)." # Contents: others/msdos.c src/restore.c # Wrapped by billr@saab on Wed Jul 11 17:11:32 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'others/msdos.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'others/msdos.c'\" else echo shar: Extracting \"'others/msdos.c'\" \(30281 characters\) sed "s/^X//" >'others/msdos.c' <<'END_OF_FILE' X/* SCCS Id: @(#)msdos.c 3.0 89/12/26 X/* NetHack may be freely redistributed. See license for details. */ X/* An assortment of MSDOS functions. X */ X X#define NEED_VARARGS X#include "hack.h" X X#ifdef MSDOS X X# ifdef TOS X# include <osbind.h> X# ifndef WORD X# define WORD short /* 16 bits -- redefine if necessary */ X# endif X# else X# ifdef __TURBOC__ /* avoid incompatible redeclaration */ X# undef getdate X# endif X# include <dos.h> X# endif X# ifdef OS2 X# include "def_os2.h" /* OS2 definitions (Timo Hakulinen) */ X# endif X X#include <ctype.h> X#include <fcntl.h> X#include <process.h> X Xstatic char NDECL(DOSgetch); X# ifdef DGK Xstatic char NDECL(BIOSgetch); X# endif X# ifdef TOS Xstatic void NDECL(init_aline); Xchar *_a_line; /* for Line A variables */ X# else Xstatic unsigned int FDECL(ioctl, (int,int,unsigned)); Xstatic boolean NDECL(comspec_exists); X# endif X Xstatic int FDECL(findfirst, (char *)); Xstatic int NDECL(findnext); Xstatic boolean NDECL(record_exists); X# if !defined(TOS) && !defined(__TURBOC__) && !defined(OS2) Xstatic char NDECL(switchar); X# endif X# ifndef OS2 Xstatic char * NDECL(getdta); X# endif X Xvoid Xflushout() X{ X (void) fflush(stdout); X return; X} X Xint Xtgetch() { X char ch; X X# ifdef DGK X /* BIOSgetch can use the numeric key pad on IBM compatibles. */ X if (flags.IBMBIOS) X ch = BIOSgetch(); X else X# endif X ch = DOSgetch(); X return ((ch == '\r') ? '\n' : ch); X} X X# if !defined(OS2) && !defined(TOS) X/* X * MS-DOS functions X */ X#define DIRECT_INPUT 0x07 /* Unfiltered Character Input Without Echo */ X#define FATINFO 0x1B /* Get Default Drive Data */ X/* MS-DOS 2.0+: */ X#define GETDTA 0x2F /* Get DTA Address */ X#define FREESPACE 0x36 /* Get Drive Allocation Info */ X#define GETSWITCHAR 0x3700 /* Get Switch Character */ X#define FINDFIRST 0x4E /* Find First File */ X#define FINDNEXT 0x4F /* Find Next File */ X#define SETFILETIME 0x5701 /* Set File Date & Time */ X/* X * BIOS interrupts X */ X#define KEYBRD_BIOS 0x16 X#define VIDEO_BIOS 0x10 X/* X * Keyboard BIOS functions X */ X#define READCHAR 0x00 /* Read Character from Keyboard */ X#define GETKEYFLAGS 0x02 /* Get Keyboard Flags */ X/* X * Video BIOS functions X */ X#define SETCURPOS 0x02 /* Set Cursor Position */ X#define GETMODE 0x0f /* Get Video Mode */ X#define FONTINFO 0x1130 /* Get Font Info */ X# endif X X X/* X * Keyboard translation tables. X */ X# ifdef TOS X#define KEYPADLO 0x61 X#define KEYPADHI 0x71 X# else X#define KEYPADLO 0x47 X#define KEYPADHI 0x53 X# endif X X#define PADKEYS (KEYPADHI - KEYPADLO + 1) X#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI) X X/* X * Keypad keys are translated to the normal values below. X * When IBM_BIOS is active, shifted keypad keys are translated to the X * shift values below. X */ Xstatic const struct pad { X char normal, shift, cntrl; X} keypad[PADKEYS] = { X# ifdef TOS X {C('['), 'Q', C('[')}, /* UNDO */ X {'?', '/', '?'}, /* HELP */ X {'(', 'a', '('}, /* ( */ X {')', 'w', ')'}, /* ) */ X {'/', '/', '/'}, /* / */ X {C('p'), '$', C('p')}, /* * */ X# endif X {'y', 'Y', C('y')}, /* 7 */ X {'k', 'K', C('k')}, /* 8 */ X {'u', 'U', C('u')}, /* 9 */ X# ifndef TOS X {'m', C('p'), C('p')}, /* - */ X# endif X {'h', 'H', C('h')}, /* 4 */ X# ifdef TOS X {'.', '.', '.'}, X# else X {'g', 'g', 'g'}, /* 5 */ X# endif X {'l', 'L', C('l')}, /* 6 */ X# ifndef TOS X {'p', 'P', C('p')}, /* + */ X# endif X {'b', 'B', C('b')}, /* 1 */ X {'j', 'J', C('j')}, /* 2 */ X {'n', 'N', C('n')}, /* 3 */ X {'i', 'I', C('i')}, /* Ins */ X {'.', ':', ':'} /* Del */ X}, numpad[PADKEYS] = { X# ifdef TOS X {C('['), 'Q', C('[')} , /* UNDO */ X {'?', '/', '?'}, /* HELP */ X {'(', 'a', '('}, /* ( */ X {')', 'w', ')'}, /* ) */ X {'/', '/', '/'}, /* / */ X {C('p'), '$', C('p')}, /* * */ X# endif X {'7', M('7'), '7'}, /* 7 */ X {'8', M('8'), '8'}, /* 8 */ X {'9', M('9'), '9'}, /* 9 */ X# ifndef TOS X {'m', C('p'), C('p')}, /* - */ X# endif X {'4', M('4'), '4'}, /* 4 */ X# ifdef TOS X {'.', '.', '.'}, /* 5 */ X# else X {'g', 'G', 'g'}, /* 5 */ X# endif X {'6', M('6'), '6'}, /* 6 */ X# ifndef TOS X {'p', 'P', C('p')}, /* + */ X# endif X {'1', M('1'), '1'}, /* 1 */ X {'2', M('2'), '2'}, /* 2 */ X {'3', M('3'), '3'}, /* 3 */ X {'i', 'I', C('i')}, /* Ins */ X {'.', ':', ':'} /* Del */ X}; X X/* X * Unlike Ctrl-letter, the Alt-letter keystrokes have no specific ASCII X * meaning unless assigned one by a keyboard conversion table, so the X * keyboard BIOS normally does not return a character code when Alt-letter X * is pressed. So, to interpret unassigned Alt-letters, we must use a X * scan code table to translate the scan code into a letter, then set the X * "meta" bit for it. -3. X */ X#define SCANLO 0x10 X#define SCANHI 0x32 X#define SCANKEYS (SCANHI - SCANLO + 1) X#define inmap(x) (SCANLO <= (x) && (x) <= SCANHI) X Xstatic const char scanmap[SCANKEYS] = { /* ... */ X 'q','w','e','r','t','y','u','i','o','p','[',']', '\n', X 0, 'a','s','d','f','g','h','j','k','l',';','\'', '`', X 0, '\\', 'z','x','c','v','b','N','m' /* ... */ X}; X X# ifdef DGK X/* X * BIOSgetch gets keys directly with a BIOS call. X */ X#define SHIFT (0x1 | 0x2) X#define CTRL 0x4 X#define ALT 0x8 X Xstatic char XBIOSgetch() { X unsigned char scan, shift, ch; X const struct pad *kpad; X X# ifdef OS2 X KBDKEYINFO CharData; X USHORT IOWait = 0; X HKBD KbdHandle = 0; X X KbdCharIn(&CharData,IOWait,KbdHandle); X ch = CharData.chChar; X scan = CharData.chScan; X shift = CharData.fsState; X# else /* OS2 */ X# ifdef TOS X long x; X# else X union REGS regs; X# endif X X /* Get scan code. X */ X# ifdef TOS X x = Crawcin(); X ch = x & 0x0ff; X scan = (x & 0x00ff0000L) >> 16; X# else X regs.h.ah = READCHAR; X int86(KEYBRD_BIOS, ®s, ®s); X ch = regs.h.al; X scan = regs.h.ah; X# endif X /* Get shift status. X */ X# ifdef TOS X shift = Kbshift(-1); X# else X regs.h.ah = GETKEYFLAGS; X int86(KEYBRD_BIOS, ®s, ®s); X shift = regs.h.al; X# endif X# endif /* OS2 */ X X /* Translate keypad keys */ X if (iskeypad(scan)) { X kpad = flags.num_pad ? numpad : keypad; X if (shift & SHIFT) X ch = kpad[scan - KEYPADLO].shift; X else if (shift & CTRL) X ch = kpad[scan - KEYPADLO].cntrl; X else X ch = kpad[scan - KEYPADLO].normal; X } X /* Translate unassigned Alt-letters */ X if ((shift & ALT) && !ch) { X if (inmap(scan)) X ch = scanmap[scan - SCANLO]; X return (isprint(ch) ? M(ch) : ch); X } X return ch; X} X Xstatic char XDOSgetch() { X# ifdef TOS X return (Crawcin() & 0x007f); X# else X# ifdef OS2 X KBDKEYINFO CharData; X USHORT IOWait = 0; X HKBD KbdHandle = 0; X X KbdCharIn(&CharData,IOWait,KbdHandle); X if (CharData.chChar == 0) { /* an extended code -- not yet supported */ X KbdCharIn(&CharData,IOWait,KbdHandle); /* eat the next character */ X CharData.chChar = 0; /* and return a 0 */ X } X return (CharData.chChar); X# else X union REGS regs; X char ch; X struct pad (*kpad)[PADKEYS]; X X regs.h.ah = DIRECT_INPUT; X intdos(®s, ®s); X ch = regs.h.al; X X /* X * The extended codes for Alt-shifted letters, and unshifted keypad X * and function keys, correspond to the scan codes. So we can still X * translate the unshifted cursor keys and Alt-letters. -3. X */ X if (ch == 0) { /* an extended key */ X regs.h.ah = DIRECT_INPUT; X intdos(®s, ®s); /* get the extended key code */ X ch = regs.h.al; X X if (iskeypad(ch)) { /* unshifted keypad keys */ X kpad = (void *)(flags.num_pad ? numpad : keypad); X ch = (*kpad)[ch - KEYPADLO].normal; X } else if (inmap(ch)) { /* Alt-letters */ X ch = scanmap[ch - SCANLO]; X if (isprint(ch)) ch = M(ch); X } else ch = 0; /* munch it */ X } X return (ch); X# endif /* OS2 */ X# endif /* TOS */ X} X X X# ifndef TOS X X# ifdef __TURBOC__ X#define switchar() (char)getswitchar() X# else X# ifndef OS2 Xstatic char Xswitchar() X{ X union REGS regs; X X regs.x.ax = GETSWITCHAR; X intdos(®s, ®s); X return regs.h.dl; X} X# endif /* OS2 */ X# endif /* __TURBOC__ */ X# endif /* TOS */ X Xstatic const char *COMSPEC = X# ifdef TOS X"SHELL"; X# else X"COMSPEC"; X# endif X X#define getcomspec() getenv(COMSPEC) X X# ifdef SHELL Xint Xdosh() { X extern char orgdir[]; X char *comspec; X X if (comspec = getcomspec()) { X# if defined(DGK) && !defined(TOS) /* TOS has a variety of shells */ X settty("To return to NetHack, enter \"exit\" at the DOS prompt.\n"); X# else X settty((char *)0); X# endif /* DGK */ X chdirx(orgdir, 0); X if (spawnl(P_WAIT, comspec, comspec, NULL) < 0) { X Printf("\nCan't spawn \"%s\"!\n", comspec); X flags.toplin = 0; X more(); X } X#ifdef TOS X/* Some shells (e.g. Gulam) turn the cursor off when they exit */ X if (flags.IBMBIOS) { X (void)Cursconf(1, -1); X get_scr_size(); /* maybe they changed the screen */ X } X#else X gettty(); /* ctrl-P might get turned back on (TH) */ X get_scr_size(); /* maybe the screen mode changed (TH) */ X#endif X chdirx(hackdir, 0); X start_screen(); X docrt(); X } else X# ifdef OS2 X pline("Can't execute CMD.EXE"); X# else X# ifdef TOS X pline("Can't find SHELL."); X# else X pline("Can't find COMSPEC."); X# endif X# endif /* OS2 */ X return 0; X} X# endif /* SHELL */ X X#ifndef TOS X Xlong Xfreediskspace(path) Xchar *path; X{ X# ifdef OS2 X struct { X ULONG idFileSystem; X ULONG cSectorUnit; X ULONG cUnit; X ULONG cUnitAvail; X USHORT cbSector; X } FSInfoBuf; X USHORT DriveNumber, FSInfoLevel = 1, res; X X if (path[0] && path[1] == ':') X DriveNumber = (toupper(path[0]) - 'A') + 1; X else X DriveNumber = 0; X res = DosQFSInfo(DriveNumber,FSInfoLevel,(PBYTE)&FSInfoBuf,sizeof(FSInfoBuf)); X if (res) X return -1L; /* error */ X else X return ((long) FSInfoBuf.cSectorUnit * FSInfoBuf.cUnitAvail * X FSInfoBuf.cbSector); X# else /* OS2 */ X union REGS regs; X X regs.h.ah = FREESPACE; X if (path[0] && path[1] == ':') X regs.h.dl = (toupper(path[0]) - 'A') + 1; X else X regs.h.dl = 0; X intdos(®s, ®s); X if (regs.x.ax == 0xFFFF) X return -1L; /* bad drive number */ X else X return ((long) regs.x.bx * regs.x.cx * regs.x.ax); X# endif /* OS2 */ X} X X# ifdef OS2 XFILEFINDBUF ResultBuf; XHDIR DirHandle; X# endif X X/* Functions to get filenames using wildcards X */ Xstatic int Xfindfirst(path) Xchar *path; X{ X# ifdef OS2 X USHORT res, SearchCount = 1; X X DirHandle = 1; X res = DosFindFirst((PSZ)path,&DirHandle,0,&ResultBuf,sizeof(FILEFINDBUF),&SearchCount,0L); X return(!res); X# else X union REGS regs; X struct SREGS sregs; X X regs.h.ah = FINDFIRST; X regs.x.cx = 0; /* attribute: normal files */ X regs.x.dx = FP_OFF(path); X sregs.ds = FP_SEG(path); X intdosx(®s, ®s, &sregs); X return !regs.x.cflag; X# endif /* OS2 */ X} X Xstatic int Xfindnext() { X# ifdef OS2 X USHORT res, SearchCount = 1; X X res = DosFindNext(DirHandle,&ResultBuf,sizeof(FILEFINDBUF),&SearchCount); X return(!res); X# else X union REGS regs; X X regs.h.ah = FINDNEXT; X intdos(®s, ®s); X return !regs.x.cflag; X# endif /* OS2 */ X} X X# ifndef OS2 X/* Get disk transfer area, Turbo C already has getdta */ Xstatic char * Xgetdta() { X union REGS regs; X struct SREGS sregs; X char *ret; X X regs.h.ah = GETDTA; X intdosx(®s, ®s, &sregs); X# ifdef MK_FP X ret = MK_FP(sregs.es, regs.x.bx); X# else X FP_OFF(ret) = regs.x.bx; X FP_SEG(ret) = sregs.es; X# endif X return ret; X} X# endif /* OS2 */ X X# else /* TOS */ X Xlong Xfreediskspace(path) Xchar *path; X{ X int drive = 0; X struct { X long freal; /*free allocation units*/ X long total; /*total number of allocation units*/ X long bps; /*bytes per sector*/ X long pspal; /*physical sectors per allocation unit*/ X } freespace; X if (path[0] && path[1] == ':') X drive = (toupper(path[0]) - 'A') + 1; X if (Dfree(&freespace,drive)<0) return -1; X return freespace.freal*freespace.bps*freespace.pspal; X} X Xstatic int Xfindfirst(path) Xchar *path; X{ X return (Fsfirst(path, 0) == 0); X} X Xstatic int findnext() { X return (Fsnext() == 0); X} X Xstatic char * Xgetdta() { X return (char *) Fgetdta(); X} X X# endif /* TOS */ X Xlong Xfilesize(file) Xchar *file; X{ X# ifndef OS2 X char *dta; X# endif X X if (findfirst(file)) { X# ifdef OS2 X return (* (long *) (ResultBuf.cbFileAlloc)); X# else X dta = getdta(); X return (* (long *) (dta + 26)); X# endif X } else X return -1L; X} X Xvoid Xeraseall(path, files) Xconst char *path, *files; X{ X# ifndef OS2 X char *dta; X# endif X char buf[PATHLEN]; X X# ifndef OS2 X dta = getdta(); X# endif X Sprintf(buf, "%s%s", path, files); X if (findfirst(buf)) X do { X Sprintf(buf, "%s%s", path, X# ifdef OS2 X ResultBuf.achName X# else X dta + 30 X# endif X ); X (void) unlink(buf); X } while (findnext()); X return; X} X X/* Rewritten for version 3.3 to be faster X */ Xvoid Xcopybones(mode) Xint mode; X{ X char from[PATHLEN], to[PATHLEN], last[13]; X char *frompath, *topath; X# ifndef OS2 X char *dta; X# endif X# ifndef TOS X int status; X char copy[8], *comspec; X extern saveprompt; X# endif X X if (!ramdisk) X return; X X /* Find the name of the last file to be transferred X */ X frompath = (mode != TOPERM) ? permbones : levels; X# ifndef OS2 X dta = getdta(); X# endif X last[0] = '\0'; X Sprintf(from, "%s%s", frompath, allbones); X topath = (mode == TOPERM) ? permbones : levels; X# ifdef TOS X eraseall(topath, allbones); X# endif X if (findfirst(from)) X do { X# ifdef TOS X Sprintf(from, "%s%s", frompath, dta+30); X Sprintf(to, "%s%s", topath, dta+30); X if (_copyfile(from, to)) X goto error_copying; X# endif X Strcpy(last, X# ifdef OS2 X ResultBuf.achName X# else X dta + 30 X# endif X ); X } while (findnext()); X# ifdef TOS X else X return; X# else X if (last[0]) { X Sprintf(copy, "%cC copy", X# ifdef OS2 X '/' X# else X switchar() X# endif X ); X X /* Remove any bones files in `to' directory. X */ X eraseall(topath, allbones); X X /* Copy `from' to `to' */ X Sprintf(to, "%s%s", topath, allbones); X comspec = getcomspec(); X status =spawnl(P_WAIT, comspec, comspec, copy, from, X to, "> nul", NULL); X } else X return; X# endif /* TOS */ X X /* See if the last file got there. If so, remove the ramdisk bones X * files. X */ X Sprintf(to, "%s%s", topath, last); X if (findfirst(to)) { X if (mode == TOPERM) X eraseall(frompath, allbones); X return; X } X X# ifdef TOS Xerror_copying: X# endif X /* Last file didn't get there. X */ X Sprintf(to, "%s%s", topath, allbones); X msmsg("Can't copy \"%s\" to \"%s\" -- ", from, to); X# ifndef TOS X if (status < 0) X msmsg("can't spawn \"%s\"!", comspec); X else X# endif X msmsg((freediskspace(topath) < filesize(from)) ? X "insufficient disk space." : "bad path(s)?"); X if (mode == TOPERM) { X msmsg("Bones will be left in \"%s\"\n", X *levels ? levels : hackdir); X } else { X /* Remove all bones files on the RAMdisk */ X eraseall(levels, allbones); X playwoRAMdisk(); X } X return; X} X X#if 0 /* defined(MSDOS) && !defined(TOS) && !defined(OS2) */ Xboolean Xremoveable_drive(drive) Xchar drive; X/* check whether current drive is a fixed disk, X so we don't ask the player to insert one */ X{ X union REGS regs; X char *fat_id; X X regs.h.ah = FATINFO; X intdos(®s, ®s); X /* also returns size info, as X AL (sectors/cluster) * CX (bytes/sector) * DX (clusters/disk) */ X# ifdef MK_FP X fat_id = MK_FP(sregs.ds, regs.x.bx); X# else X FP_OFF(fat_id) = regs.x.bx; X FP_SEG(fat_id) = sregs.ds; X# endif X return (*fat_id != 0xF8); X} X#endif /* 0 */ X Xvoid XplaywoRAMdisk() { X msmsg("Do you wish to play without a RAMdisk? "); X X /* Set ramdisk false *before* exit-ing (because msexit calls X * copybones) X */ X ramdisk = FALSE; X if (yn() != 'y') { X settty("Be seeing you...\n"); X exit(0); X } X set_lock_and_bones(); X return; X} X Xint XsaveDiskPrompt(start) Xint start; X{ X extern saveprompt; X char buf[BUFSIZ], *bp; X int fd; X X if (saveprompt) { X /* Don't prompt if you can find the save file */ X if ((fd = open(SAVEF, 0)) >= 0) { X (void) close(fd); X return 1; X } X remember_topl(); X home(); X cl_end(); X msmsg("If save file is on a save disk, insert that disk now.\n"); X cl_end(); X msmsg("File name (default \"%s\"%s) ? ", SAVEF, X start ? "" : ", <Esc> cancels save"); X getlin(buf); X home(); X cl_end(); X curs(1, 2); X cl_end(); X if (!start && *buf == '\033') X return 0; X X /* Strip any whitespace. Also, if nothing was entered except X * whitespace, do not change the value of SAVEF. X */ X for (bp = buf; *bp; bp++) X if (!isspace(*bp)) { X strncpy(SAVEF, bp, PATHLEN); X break; X } X } X return 1; X} X X/* Return 1 if the record file was found */ Xstatic boolean Xrecord_exists() { X int fd; X# ifdef OS2_CODEVIEW X char tmp[PATHLEN]; X X Strcpy(tmp,hackdir); X append_slash(tmp); X Strcat(tmp,RECORD); X if ((fd = open(tmp, 0)) >= 0) { X# else X if ((fd = open(RECORD, 0)) >= 0) { X# endif X (void) close(fd); X return TRUE; X } X return FALSE; X} X X# ifdef TOS X#define comspec_exists() 1 X# else X/* Return 1 if the comspec was found */ Xstatic boolean Xcomspec_exists() { X int fd; X char *comspec; X X if (comspec = getcomspec()) X if ((fd = open(comspec, 0)) >= 0) { X (void) close(fd); X return TRUE; X } X return FALSE; X} X# endif X X/* Prompt for game disk, then check for record file. X */ Xvoid XgameDiskPrompt() { X extern int saveprompt; X X if (saveprompt) { X if (record_exists() && comspec_exists()) X return; X (void) putchar('\n'); X getreturn("when the game disk has been inserted"); X } X if (comspec_exists() && record_exists()) X return; X X if (!comspec_exists()) X msmsg("\n\nWARNING: can't find command processor \"%s\"!\n", getcomspec()); X if (!record_exists()) X msmsg("\n\nWARNING: can't find record file \"%s\"!\n", RECORD); X msmsg("If the game disk is not in, insert it now.\n"); X getreturn("to continue"); X return; X} X X# endif /* DGK */ X X/* Read configuration */ Xvoid Xread_config_file() { X# ifdef DGK X char tmp_ramdisk[PATHLEN]; X extern int saveprompt; X# else X#define fopenp fopen X# endif X char tmp_levels[PATHLEN]; X char buf[BUFSZ], *bufp; X FILE *fp; X extern char plname[]; X X# ifdef DGK X tmp_ramdisk[0] = 0; X# endif X tmp_levels[0] = 0; X if ((fp = fopenp(configfile, "r")) == (FILE *)0) { X msmsg("Warning: no configuration file!\n"); X getreturn("to continue"); X return; X } X while (fgets(buf, BUFSZ, fp)) { X if (*buf == '#') X continue; X X /* remove trailing whitespace X */ X bufp = index(buf, '\n'); X while (bufp > buf && isspace(*bufp)) X bufp--; X if (bufp == buf) X continue; /* skip all-blank lines */ X else X *(bufp + 1) = 0; /* 0 terminate line */ X X /* find the '=' */ X if (!(bufp = strchr(buf, '='))) { X msmsg("Bad option line: \"%s\"\n", buf); X getreturn("to continue"); X continue; X } X X /* skip whitespace between '=' and value */ X while (isspace(*++bufp)) X ; X X /* Go through possible variables */ X if (!strncmp(buf, "HACKDIR", 4)) { X strncpy(hackdir, bufp, PATHLEN); X X# ifdef DGK X } else if (!strncmp(buf, "RAMDISK", 3)) { X strncpy(tmp_ramdisk, bufp, PATHLEN); X# endif X X } else if (!strncmp(buf, "LEVELS", 4)) { X strncpy(tmp_levels, bufp, PATHLEN); X X } else if (!strncmp(buf, "OPTIONS", 4)) { X parseoptions(bufp, TRUE); X if (plname[0]) /* If a name was given */ X plnamesuffix(); /* set the character class */ X X } else if (!strncmp(buf, "SAVE", 4)) { X# ifdef DGK X char *ptr; X if (ptr = index(bufp, ';')) { X *ptr = '\0'; X if (*(ptr+1) == 'n' || *(ptr+1) == 'N') X saveprompt = FALSE; X } X# endif /* DGK */ X (void) strncpy(SAVEF, bufp, PATHLEN); X (void) strncpy(SAVEP, bufp, PATHLEN); X append_slash(SAVEF); X append_slash(SAVEP); X } else if (!strncmp(buf, "GRAPHICS", 4)) { X unsigned int translate[MAXPCHARS+1]; X int lth; X#ifdef OVERLAY X /* THIS is what I call a stupid hack, but MSC cannot survive X the overlays without it (TH) */ X lth = sscanf(bufp, X "%d%d%d%d%d%d%d%d%d%d%d%d", X &translate[0], &translate[1], &translate[2], X &translate[3], &translate[4], &translate[5], X &translate[6], &translate[7], &translate[8], X &translate[9], &translate[10], &translate[11]); X lth += sscanf(bufp, X "%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%d%d%d%d%d%d%d%d%d%d%d%d", X &translate[12], &translate[13], &translate[14], X &translate[15], &translate[16], &translate[17], X &translate[18], &translate[19], &translate[20], X &translate[21], &translate[22], &translate[23]); X lth += sscanf(bufp, X "%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%d%d%d%d%d%d%d%d%d%d%d", X &translate[24], &translate[25], &translate[26], X &translate[27], &translate[28], &translate[29], X &translate[30], &translate[31], &translate[32], X &translate[33], &translate[34]); X#else X lth = sscanf(bufp, X "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", X &translate[0], &translate[1], &translate[2], X &translate[3], &translate[4], &translate[5], X &translate[6], &translate[7], &translate[8], X &translate[9], &translate[10], &translate[11], X &translate[12], &translate[13], &translate[14], X &translate[15], &translate[16], &translate[17], X &translate[18], &translate[19], &translate[20], X &translate[21], &translate[22], &translate[23], X &translate[24], &translate[25], &translate[26], X &translate[27], &translate[28], &translate[29], X &translate[30], &translate[31], &translate[32], X &translate[33], &translate[34]); X#endif /* OVERLAY */ X if (lth <= 0) { X msmsg ("Syntax error in GRAPHICS\n"); X getreturn("to continue"); X } X assign_graphics(translate, lth); X } else { X msmsg("Bad option line: \"%s\"\n", buf); X getreturn("to continue"); X } X } X (void) fclose(fp); X X# ifdef DGK X Strcpy(permbones, tmp_levels); X if (tmp_ramdisk[0]) { X Strcpy(levels, tmp_ramdisk); X if (strcmp(permbones, levels)) /* if not identical */ X ramdisk = TRUE; X } else X# endif /* DGK */ X Strcpy(levels, tmp_levels); X Strcpy(bones, levels); X return; X} X X# ifdef DGK X/* Set names for bones[] and lock[] X */ Xvoid Xset_lock_and_bones() { X if (!ramdisk) { X Strcpy(levels, permbones); X Strcpy(bones, permbones); X } X append_slash(permbones); X append_slash(levels); X append_slash(bones); X Strcat(bones, allbones); X Strcpy(lock, levels); X Strcat(lock, alllevels); X return; X} X# endif /* DGK */ X X/* Add a backslash to any name not ending in /, \ or : There must X * be room for the \ X */ Xvoid Xappend_slash(name) Xchar *name; X{ X char *ptr; X X if (!*name) X return; X ptr = name + (strlen(name) - 1); X if (*ptr != '\\' && *ptr != '/' && *ptr != ':') { X *++ptr = '\\'; X *++ptr = '\0'; X } X return; X} X Xvoid Xgetreturn(str) Xconst char *str; X{ X# ifdef TOS X msmsg("Hit <Return> %s.", str); X# else X msmsg("Hit <Enter> %s.", str); X# endif X while (Getchar() != '\n') ; X return; X} X Xvoid Xmsmsg VA_DECL(const char *, fmt) X VA_START(fmt); X VA_INIT(fmt, const char *); X Vprintf(fmt, VA_ARGS); X flushout(); X VA_END(); X return; X} X X/* Chdrive() changes the default drive. X */ X# ifndef __TURBOC__ X# ifndef OS2 X#define SELECTDISK 0x0E X# endif Xvoid Xchdrive(str) Xchar *str; X{ X char *ptr; X# ifndef TOS X# ifndef OS2 X union REGS inregs; X# endif X# endif X char drive; X X if ((ptr = index(str, ':')) != NULL) { X drive = toupper(*(ptr - 1)); X# ifdef TOS X (void)Dsetdrv(drive - 'A'); X# else X# ifdef OS2 X DosSelectDisk((USHORT)(drive - 'A' + 1)); X# else X inregs.h.ah = SELECTDISK; X inregs.h.dl = drive - 'A'; X intdos(&inregs, &inregs); X# endif X# endif X } X return; X} X# else Xextern int setdisk(int); X Xvoid Xchdrive(str) Xchar *str; X{ X if (str[1] == ':') X (void)setdisk((int)(toupper(str[0]) - 'A')); X return; X} X# endif X X# ifndef TOS X/* Use the IOCTL DOS function call to change stdin and stdout to raw X * mode. For stdin, this prevents MSDOS from trapping ^P, thus X * freeing us of ^P toggling 'echo to printer'. X * Thanks to Mark Zbikowski (markz@microsoft.UUCP). X */ X X# ifndef OS2 X#define DEVICE 0x80 X#define RAW 0x20 X#define IOCTL 0x44 X#define STDIN fileno(stdin) X#define STDOUT fileno(stdout) X#define GETBITS 0 X#define SETBITS 1 X# endif X Xstatic unsigned int old_stdin, old_stdout; X Xvoid Xdisable_ctrlP() { X# ifdef OS2 X KBDINFO KbdInfo; X HKBD KbdHandle = 0; X# endif X X# ifdef DGK X if (!flags.rawio) return; X# endif X# ifdef OS2 X KbdInfo.cb = sizeof(KbdInfo); X KbdGetStatus(&KbdInfo,KbdHandle); X KbdInfo.fsMask &= 0xFFF7; /* ASCII off */ X KbdInfo.fsMask |= 0x0004; /* BINARY on */ X KbdSetStatus(&KbdInfo,KbdHandle); X# else X old_stdin = ioctl(STDIN, GETBITS, 0); X old_stdout = ioctl(STDOUT, GETBITS, 0); X if (old_stdin & DEVICE) X ioctl(STDIN, SETBITS, old_stdin | RAW); X if (old_stdout & DEVICE) X ioctl(STDOUT, SETBITS, old_stdout | RAW); X# endif /* OS2 */ X return; X} X Xvoid Xenable_ctrlP() { X# ifdef OS2 X KBDINFO KbdInfo; X HKBD KbdHandle = 0; X# endif X X# ifdef DGK X if (!flags.rawio) return; X# endif X# ifdef OS2 X KbdInfo.cb = sizeof(KbdInfo); X KbdGetStatus(&KbdInfo,KbdHandle); X KbdInfo.fsMask &= 0xFFFB; /* BINARY off */ X KbdInfo.fsMask |= 0x0008; /* ASCII on */ X KbdSetStatus(&KbdInfo,KbdHandle); X# else X if (old_stdin) X (void) ioctl(STDIN, SETBITS, old_stdin); X if (old_stdout) X (void) ioctl(STDOUT, SETBITS, old_stdout); X# endif X return; X} X X# ifndef OS2 Xstatic unsigned int Xioctl(handle, mode, setvalue) Xint handle, mode; Xunsigned setvalue; X{ X union REGS regs; X X regs.h.ah = IOCTL; X regs.h.al = mode; X regs.x.bx = handle; X regs.h.dl = setvalue; X regs.h.dh = 0; /* Zero out dh */ X intdos(®s, ®s); X return (regs.x.dx); X} X# endif /* OS2 */ X# endif /* TOS */ X X# ifdef DGK X/* Follow the PATH, trying to fopen the file. X */ X# ifdef TOS X#define PATHSEP ',' X# else X#define PATHSEP ';' X# endif X XFILE * Xfopenp(name, mode) Xconst char *name, *mode; X{ X char buf[BUFSIZ], *bp, *pp, lastch = 0; X FILE *fp; X X /* Try the default directory first. Then look along PATH. X */ X Strcpy(buf, name); X if (fp = fopen(buf, mode)) X return fp; X else { X pp = getenv("PATH"); X while (pp && *pp) { X bp = buf; X while (*pp && *pp != PATHSEP) X lastch = *bp++ = *pp++; X if (lastch != '\\' && lastch != '/') X *bp++ = '\\'; X Strcpy(bp, name); X if (fp = fopen(buf, mode)) X return fp; X if (*pp) X pp++; X } X } X# ifdef OS2_CODEVIEW /* one more try for hackdir */ X Strcpy(buf,hackdir); X append_slash(buf); X Strcat(buf,name); X if(fp = fopen(buf,mode)) X return fp; X# endif X return (FILE *)0; X} X# endif /* DGK */ X X/* Chdir back to original directory X */ X#undef exit X# ifdef TOS Xextern boolean run_from_desktop; /* set in pcmain.c */ X# endif X Xvoid exit(int); Xvoid Xmsexit(code) Xint code; X{ X# ifdef CHDIR X extern char orgdir[]; X# endif X X flushout(); X# ifndef TOS X enable_ctrlP(); /* in case this wasn't done */ X# endif X# ifdef DGK X if (ramdisk) copybones(TOPERM); X# endif X# ifdef CHDIR X chdir(orgdir); /* chdir, not chdirx */ X chdrive(orgdir); X# endif X# ifdef TOS X if (run_from_desktop) X getreturn("to continue"); /* so the user can read the score list */ X# ifdef TEXTCOLOR X if (flags.IBMBIOS && flags.use_color) X restore_colors(); X# endif X# endif X exit(code); X return; X} X X# ifdef DGK /* for flags.IBMBIOS */ Xvoid Xget_scr_size() X{ X# ifdef OS2 X VIOMODEINFO ModeInfo; X HVIO VideoHandle = 0; X X ModeInfo.cb = sizeof(ModeInfo); X X (void) VioGetMode(&ModeInfo,VideoHandle); X X CO = ModeInfo.col; X LI = ModeInfo.row; X# else X# ifndef TOS X union REGS regs; X X if (!flags.IBMBIOS) { /* assume standard screen size */ X CO = 80; X LI = 24; X return; X } X X regs.x.ax = FONTINFO; X regs.x.bx = 0; /* current ROM BIOS font */ X regs.h.dl = 24; /* default row count */ X /* in case no EGA/MCGA/VGA */ X int86(VIDEO_BIOS, ®s, ®s); /* Get Font Information */ X X /* MDA/CGA/PCjr ignore INT 10h, Function 11h, but since we X * cleverly loaded up DL with the default, everything's fine. X * X * Otherwise, DL now contains rows - 1. Also, CX contains the X * points (bytes per character) and ES:BP points to the font X * table. -3. X */ X X regs.h.ah = GETMODE; X int86(VIDEO_BIOS, ®s, ®s); /* Get Video Mode */ X X /* This goes back all the way to the original PC. Completely X * safe. AH contains # of columns, AL contains display mode, X * and BH contains the active display page. X */ X X LI = regs.h.dl + 1; X CO = regs.h.ah; X# else /* TOS */ X init_aline(); X LI = (*((WORD *)(_a_line + -42L))) + 1; X CO = (*((WORD *)(_a_line + -44L))) + 1; X# endif /* TOS */ X# endif /* OS2 */ X} X X# ifndef TOS Xvoid Xgotoxy(x,y) Xint x,y; X{ X# ifdef OS2 X HVIO VideoHandle = 0; X X x--; y--; /* (0,0) is upper right corner */ X X (void) VioSetCurPos(x, y, VideoHandle); X# else X union REGS regs; X X x--; y--; /* (0,0) is upper right corner */ X X regs.h.ah = SETCURPOS; X regs.h.bh = 0; /* display page */ X regs.h.dh = y; /* row */ X regs.h.dl = x; /* column */ X int86(VIDEO_BIOS, ®s, ®s); /* Set Cursor Position */ X X /* This, too, goes back all the way to the original PC. If X * we ever get so fancy as to swap display pages (i doubt it), X * then we'll need to set BH appropriately. This function X * returns nothing. -3. X */ X# endif /* OS2 */ X} X# endif /* TOS */ X# endif /* DGK */ X X#endif /* MSDOS */ X X X#ifdef TOS X# define BIGBUF 8192 X Xint X_copyfile(from, to) Xchar *from, *to; X{ X int fromfd, tofd, r; X char *buf; X X if ((fromfd = open(from, O_RDONLY|O_BINARY, 0)) < 0) X return -1; X if ((tofd = open(to, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, FCMASK)) < 0) X return -1; X if (!(buf = (char *)malloc((size_t)BIGBUF))) X return -1; X while ( (r = read(fromfd, buf, BIGBUF)) > 0) X write(tofd, buf, r); X close(fromfd); X close(tofd); X free(buf); X return 0; /* successful */ X} X Xint kbhit() X{ X return Cconis(); X} X Xstatic void Xinit_aline() X{ X# ifdef __GNUC__ X asm(" .word 0xa000; movel d0, __a_line"); X# else X asm(" .dc.w 0xa000"); /* tweak as necessary for your compiler */ X asm(" move.l d0, __a_line"); X# endif X} X X# ifdef TEXTCOLOR Xstatic unsigned orig_color[4] = {-1, -1, -1, -1}; Xstatic unsigned new_color[4] = { 0x0, 0x730, 0x047, 0x555 }; Xstatic int numcolors = 2; X Xvoid set_colors() X{ X int i; X char *s; X static char newhe[] = "\033q\033b\017\033c0"; X X if (!flags.IBMBIOS) X return; X init_aline(); X numcolors = 1 << (((unsigned char *) _a_line)[1]); X if (numcolors == 2) { /* mono */ X flags.use_color = FALSE; X return; X } X else if (numcolors == 4) { X for (i = 0; i < 4; i++) X orig_color[i] = Setcolor(i, new_color[i]); X } X else { X orig_color[0] = Setcolor(0, new_color[0]); X orig_color[1] = Setcolor(15, 0x777); X hilites[0] = ""; X for (i = 1; i < 16; i++) { X s = (char *) alloc(sizeof("\033b0")); X sprintf(s, "\033b%c", '0'+i); X hilites[i] = s; X } X HE = newhe; X } X} X Xvoid restore_colors() X{ X int i; X X if (numcolors == 2) X return; X else if (numcolors == 4) X for (i = 0; i < 4; i++) X (void) Setcolor(i, orig_color[i]); X else { X (void) Setcolor(0, orig_color[0]); X (void) Setcolor(15, orig_color[1]); X } X} X# endif /* TEXTCOLOR */ X#endif /* TOS */ END_OF_FILE if test 30281 -ne `wc -c <'others/msdos.c'`; then echo shar: \"'others/msdos.c'\" unpacked with wrong size! fi # end of 'others/msdos.c' fi if test -f 'src/restore.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/restore.c'\" else echo shar: Extracting \"'src/restore.c'\" \(25217 characters\) sed "s/^X//" >'src/restore.c' <<'END_OF_FILE' X/* SCCS Id: @(#)restore.c 3.0 88/10/25 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X#include "lev.h" X X#ifdef WORM X#include "wseg.h" X#endif X Xstatic void FDECL(stuff_objs, (struct obj *)); Xstatic void NDECL(find_lev_obj); X#ifndef NO_SIGNAL Xstatic void NDECL(inven_inuse); X#endif Xstatic struct obj * FDECL(restobjchn, (int,BOOLEAN_P)); Xstatic struct monst * FDECL(restmonchn, (int,BOOLEAN_P)); Xstatic void FDECL(restgenoinfo, (int)); X Xboolean restoring = FALSE; X#ifdef TUTTI_FRUTTI Xstatic struct fruit NEARDATA *oldfruit; X#endif Xstatic long NEARDATA omoves; X X/* X * "stuff" objects back into containers (relink the fcobj list). X */ Xstatic void Xstuff_objs(cobj) Xregister struct obj *cobj; X{ X register struct obj *otmp, *otmp2; X X for(; cobj; cobj = cobj->nobj) X if(Is_container(cobj)) X X for(otmp = cobj->nobj; X otmp && otmp->cobj == (struct obj *) -1; otmp = otmp2) { X X otmp2 = otmp->nobj; X X otmp->cobj = cobj; X cobj->nobj = otmp2; X otmp->nobj = fcobj; X fcobj = otmp; X } X} X X/* Recalculate level.objects[x][y], since this info was not saved. */ Xstatic void Xfind_lev_obj() X{ X register struct obj *fobjtmp = (struct obj *)0; X register struct obj *otmp; X int x,y; X X for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++) X level.objects[x][y] = (struct obj *)0; X X /* Reverse the entire fobj chain, which is necessary so that we can X * place the objects in the proper order. X */ X while(otmp = fobj) { X fobj = otmp->nobj; X otmp->nobj = fobjtmp; X fobjtmp = otmp; X } X /* Set level.objects (as well as reversing the chain back again) */ X while(otmp = fobjtmp) { X place_object(otmp, otmp->ox, otmp->oy); X fobjtmp = otmp->nobj; X otmp->nobj = fobj; X fobj = otmp; X } X} X X#ifndef NO_SIGNAL Xstatic void Xinven_inuse() X/* Things that were marked "in_use" when the game was saved (ex. via the X * infamous "HUP" cheat) get used up here. X */ X{ X register struct obj *otmp, *otmp2; X X for(otmp = invent; otmp; otmp = otmp2) { X otmp2 = otmp->nobj; X if(otmp->olet != ARMOR_SYM && otmp->olet != WEAPON_SYM X && otmp->otyp != PICK_AXE && otmp->otyp != UNICORN_HORN X && otmp->in_use) { X pline("Finishing off %s...", xname(otmp)); X useup(otmp); X } X } X} X#endif X Xstatic struct obj * Xrestobjchn(fd, ghostly) Xregister int fd; Xboolean ghostly; X{ X register struct obj *otmp, *otmp2; X register struct obj *first = 0; X#ifdef TUTTI_FRUTTI X register struct fruit *oldf; X#endif X int xl; X#if defined(LINT) || defined(__GNULINT__) X /* suppress "used before set" warning from lint */ X otmp2 = 0; X#endif X while(1) { X mread(fd, (genericptr_t) &xl, sizeof(xl)); X if(xl == -1) break; X otmp = newobj(xl); X if(!first) first = otmp; X else otmp2->nobj = otmp; X mread(fd, (genericptr_t) otmp, (unsigned) xl + sizeof(struct obj)); X if(!otmp->o_id) otmp->o_id = flags.ident++; X#ifdef TUTTI_FRUTTI X if(ghostly && otmp->otyp == SLIME_MOLD) { X for(oldf=oldfruit; oldf; oldf=oldf->nextf) X if (oldf->fid == otmp->spe) break; X if(!oldf) impossible("no old fruit?"); X else otmp->spe = fruitadd(oldf->fname); X } X#endif X /* Ghost levels get object age shifted from old player's clock to X * new player's clock. Assumption: new player arrived immediately X * after old player died. X */ X if (ghostly) otmp->age = monstermoves-omoves+otmp->age; X otmp2 = otmp; X } X if(first && otmp2->nobj){ X impossible("Restobjchn: error reading objchn."); X otmp2->nobj = 0; X } X X stuff_objs(first); X return(first); X} X Xstatic struct monst * Xrestmonchn(fd, ghostly) Xregister int fd; Xboolean ghostly; X{ X register struct monst *mtmp, *mtmp2; X register struct monst *first = 0; X int xl; X X struct permonst *monbegin; X off_t differ; X X mread(fd, (genericptr_t)&monbegin, sizeof(monbegin)); X#if !defined(MSDOS) && !defined(M_XENIX) && !defined(THINKC4) && !defined(HPUX) && !defined(VAXC) X differ = (genericptr_t)(&mons[0]) - (genericptr_t)(monbegin); X#else X differ = (long)(&mons[0]) - (long)(monbegin); X#endif X X#if defined(LINT) || defined(__GNULINT__) X /* suppress "used before set" warning from lint */ X mtmp2 = 0; X#endif X while(1) { X mread(fd, (genericptr_t) &xl, sizeof(xl)); X if(xl == -1) break; X mtmp = newmonst(xl); X if(!first) first = mtmp; X else mtmp2->nmon = mtmp; X mread(fd, (genericptr_t) mtmp, (unsigned) xl + sizeof(struct monst)); X if(!mtmp->m_id) X mtmp->m_id = flags.ident++; X#if !defined(MSDOS) && !defined(M_XENIX) && !defined(THINKC4) && !defined(HPUX) && !defined(VAXC) X /* ANSI type for differ is ptrdiff_t -- X * long may be wrong for segmented architecture -- X * may be better to cast pointers to (struct permonst *) X * rather than (genericptr_t) X * this code handles save file -- so any bug should glow X * probably best not to keep lint from complaining X */ X/*#ifdef LINT /* possible compiler/hardware dependency - */ X/* if (differ) mtmp->data = NULL;*/ X/*#else*/ X mtmp->data = (struct permonst *) X ((genericptr_t)mtmp->data + differ); X/*#endif /*LINT*/ X#else X mtmp->data = (struct permonst *) X ((long) mtmp->data + differ); X#endif X if(mtmp->minvent) X mtmp->minvent = restobjchn(fd, ghostly); X mtmp2 = mtmp; X } X if(first && mtmp2->nmon){ X impossible("Restmonchn: error reading monchn."); X mtmp2->nmon = 0; X } X return(first); X} X Xstatic void Xrestgenoinfo(fd) Xregister int fd; X{ X register int i; X X for (i = 0; i < NUMMONS; i++) X mread(fd, (genericptr_t) &(mons[i].geno), sizeof(unsigned)); X} X Xint Xdorecover(fd) Xregister int fd; X{ X register int nfd; X int tmp; /* not a register ! */ X xchar ltmp; X unsigned int mid; /* idem */ X struct obj *otmp; X#ifdef TUTTI_FRUTTI X struct fruit *fruit; X#endif X struct flag oldflags; X X oldflags = flags; X X#ifdef ZEROCOMP X minit(); X#endif X restoring = TRUE; X getlev(fd, 0, (xchar)0, FALSE); X invent = restobjchn(fd, FALSE); X for(otmp = invent; otmp; otmp = otmp->nobj) X if(otmp->owornmask) X setworn(otmp, otmp->owornmask); X fallen_down = restmonchn(fd, FALSE); X restgenoinfo(fd); X mread(fd, (genericptr_t) &tmp, sizeof tmp); X#ifdef WIZARD X if(!wizard) X#endif X if(tmp != getuid()) { /* strange ... */ X (void) close(fd); X (void) unlink(SAVEF); X#ifdef AMIGA_WBENCH X ami_wbench_unlink(SAVEF); X#endif X (void) puts("Saved game was not yours."); X restoring = FALSE; X return(0); X } X mread(fd, (genericptr_t) &flags, sizeof(struct flag)); X /* Some config file and command line OPTIONS take precedence over X * those in save file. X */ X flags.DECgraphics = oldflags.DECgraphics; X flags.IBMgraphics = oldflags.IBMgraphics; X#if defined(MSDOS) && defined(DGK) X flags.rawio = oldflags.rawio; X flags.IBMBIOS = oldflags.IBMBIOS; X#endif X#ifdef TEXTCOLOR X flags.use_color = oldflags.use_color; X#endif X /* these come from the current environment; ignore saved values */ X flags.echo = oldflags.echo; X flags.cbreak = oldflags.cbreak; X X mread(fd, (genericptr_t) &dlevel, sizeof dlevel); X mread(fd, (genericptr_t) &maxdlevel, sizeof maxdlevel); X mread(fd, (genericptr_t) &moves, sizeof moves); X mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves); X mread(fd, (genericptr_t) &wiz_level, sizeof wiz_level); X mread(fd, (genericptr_t) &medusa_level, sizeof medusa_level); X mread(fd, (genericptr_t) &bigroom_level, sizeof bigroom_level); X#ifdef ORACLE X mread(fd, (genericptr_t) &oracle_level, sizeof oracle_level); X#endif X#ifdef REINCARNATION X mread(fd, (genericptr_t) &rogue_level, sizeof rogue_level); X if (dlevel==rogue_level) X (void) memcpy((genericptr_t)savesyms, X (genericptr_t)showsyms, sizeof savesyms); X#endif X#ifdef STRONGHOLD X mread(fd, (genericptr_t) &stronghold_level, sizeof stronghold_level); X mread(fd, (genericptr_t) &tower_level, sizeof tower_level); X mread(fd, (genericptr_t) tune, sizeof tune); X# ifdef MUSIC X mread(fd, (genericptr_t) &music_heard, sizeof music_heard); X# endif X#endif X mread(fd, (genericptr_t) &is_maze_lev, sizeof is_maze_lev); X mread(fd, (genericptr_t) &u, sizeof(struct you)); X if(u.uhp <= 0) { X (void) close(fd); X (void) unlink(SAVEF); X#ifdef AMIGA_WBENCH X ami_wbench_unlink(SAVEF); X#endif X (void) puts("You were not healthy enough to survive restoration."); X restoring = FALSE; X return(0); X } X#ifdef SPELLS X mread(fd, (genericptr_t) spl_book, X sizeof(struct spell) * (MAXSPELL + 1)); X#endif X#ifdef NAMED_ITEMS X mread(fd, (genericptr_t) artiexist, X (unsigned int)(sizeof(boolean) * artifact_num)); X#endif X if(u.ustuck) X mread(fd, (genericptr_t) &mid, sizeof mid); X mread(fd, (genericptr_t) pl_character, sizeof pl_character); X#ifdef TUTTI_FRUTTI X mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit); X mread(fd, (genericptr_t) ¤t_fruit, sizeof current_fruit); X ffruit = 0; X while (fruit = newfruit(), X mread(fd, (genericptr_t)fruit, sizeof(struct fruit)), X fruit->fid) { X fruit->nextf = ffruit; X ffruit = fruit; X } X free((genericptr_t) fruit); X#endif X X restnames(fd); X#if defined(DGK) || defined(MACOS) X# ifdef MACOS X#define msmsg printf X# endif X msmsg("\n"); X cl_end(); X msmsg("You got as far as level %d%s.\n", maxdlevel, X flags.debug ? " in WIZARD mode" : X flags.explore ? " in discovery mode" : ""); X cl_end(); X msmsg("Restoring: "); X#endif X while(1) { X#ifdef ZEROCOMP X if(mread(fd, (genericptr_t) <mp, sizeof ltmp) < 0) X#else X if(read(fd, (genericptr_t) <mp, sizeof ltmp) != sizeof ltmp) X#endif X break; X getlev(fd, 0, ltmp, FALSE); X glo(ltmp); X#if defined(DGK) || defined(MACOS) X msmsg("."); X#endif X#if defined(MSDOS) && !defined(TOS) X nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); X#else X# ifdef MACOS X { X Str255 fileName; X OSErr er; X struct term_info *t; X short oldVolume; X extern WindowPtr HackWindow; X X t = (term_info *)GetWRefCon(HackWindow); X (void)GetVol(&fileName, &oldVolume); X (void)SetVol(0L, t->system.sysVRefNum); X fileName[0] = (uchar)strlen(lock); X Strcpy((char *)&fileName[1], lock); X X if (er = Create(&fileName, 0, CREATOR, LEVEL_TYPE)) X SysBeep(1); X msmsg("."); X nfd = open(lock, O_WRONLY | O_BINARY); X (void)SetVol(0L, oldVolume); X } X# else X nfd = creat(lock, FCMASK); X# endif /* MACOS */ X#endif X if (nfd < 0) panic("Cannot open temp file %s!\n", lock); X#if defined(DGK) X if (!savelev(nfd, ltmp, COUNT | WRITE)) { X X /* The savelev can't proceed because the size required X * is greater than the available disk space. X */ X msmsg("\nNot enough space on `%s' to restore your game.\n", X levels); X X /* Remove levels and bones that may have been created. X */ X (void) close(nfd); X eraseall(levels, alllevels); X eraseall(levels, allbones); X X /* Perhaps the person would like to play without a X * RAMdisk. X */ X if (ramdisk) { X /* PlaywoRAMdisk may not return, but if it does X * it is certain that ramdisk will be 0. X */ X playwoRAMdisk(); X /* Rewind save file and try again */ X (void) lseek(fd, (off_t)0, 0); X return dorecover(fd); X } else { X msmsg("Be seeing you...\n"); X exit(0); X } X } X#else X savelev(nfd, ltmp); X#endif X#ifdef ZEROCOMP X bflush(nfd); X#endif X (void) close(nfd); X } X#ifdef BSD X (void) lseek(fd, 0L, 0); X#else X (void) lseek(fd, (off_t)0, 0); X#endif X#ifdef ZEROCOMP X minit(); X#endif X getlev(fd, 0, (xchar)0, FALSE); X (void) close(fd); X#if defined(WIZARD) || defined(EXPLORE_MODE) X if( X# ifdef WIZARD X !wizard X# ifdef EXPLORE_MODE X && X# endif X# endif X# ifdef EXPLORE_MODE X !discover X# endif X ) X#endif X (void) unlink(SAVEF); X#ifdef AMIGA_WBENCH X ami_wbench_unlink(SAVEF); X#endif X#ifdef REINCARNATION X /* this can't be done earlier because we need to check the initial X * showsyms against the one saved in each of the non-rogue levels */ X if (dlevel==rogue_level) { X (void) memcpy((genericptr_t)showsyms, X (genericptr_t)defsyms, sizeof showsyms); X showsyms[S_ndoor] = showsyms[S_vodoor] = X showsyms[S_hodoor] = '+'; X } X#endif X if(u.ustuck) { X register struct monst *mtmp; X X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if(mtmp->m_id == mid) goto monfnd; X panic("Cannot find the monster ustuck."); X monfnd: X u.ustuck = mtmp; X } X setsee(); /* only to recompute seelx etc. - these weren't saved */ X#ifdef DGK X gameDiskPrompt(); X#endif X max_rank_sz(); /* to recompute mrank_sz (pri.c) */ X#ifdef POLYSELF X set_uasmon(); X#endif X /* take care of iron ball & chain */ X for(otmp = fobj; otmp; otmp = otmp->nobj) X if(otmp->owornmask) X setworn(otmp, otmp->owornmask); X#ifndef NO_SIGNAL X /* in_use processing must be after: X * inven has been read so fcobj has been built and freeinv() works X * current level has been restored so billing information is available X */ X inven_inuse(); X#endif X docrt(); X restoring = FALSE; X return(1); X} X Xvoid Xgetlev(fd, pid, lev, ghostly) Xint fd, pid; Xxchar lev; Xboolean ghostly; X{ X register struct gold *gold; X register struct trap *trap; X register struct monst *mtmp; X#ifdef WORM X register struct wseg *wtmp; X register int tmp; X#endif X long nhp; X int hpid; X xchar dlvl; X symbol_array osymbol; X int x, y; X uchar osym, nsym; X#ifdef TOS X short tlev; X#endif X X#if defined(MSDOS) && !defined(TOS) && !defined(LATTICE) && !defined(AZTEC_C) X setmode(fd, O_BINARY); /* is this required for TOS??? NO --ERS */ X#endif X#ifdef TUTTI_FRUTTI X /* Load the old fruit info. We have to do it first, so the infor- X * mation is available when restoring the objects. X */ X if (ghostly) { X struct fruit *fruit; X X oldfruit = 0; X while (fruit = newfruit(), X mread(fd, (genericptr_t)fruit, sizeof(struct fruit)), X fruit->fid) { X fruit->nextf = oldfruit; X oldfruit = fruit; X } X free((genericptr_t) fruit); X } X#endif X X /* First some sanity checks */ X mread(fd, (genericptr_t) &hpid, sizeof(hpid)); X#ifdef TOS X mread(fd, (genericptr_t) &tlev, sizeof(tlev)); X dlvl=tlev&0x00ff; X#else X mread(fd, (genericptr_t) &dlvl, sizeof(dlvl)); X#endif X if((pid && pid != hpid) || (lev && dlvl != lev)) { X#ifdef WIZARD X if (wizard) { X if (pid && pid != hpid) X pline("PID (%d) doesn't match saved PID (%d)!", hpid, pid); X else if (lev && dlvl != lev) X pline("This is level %d, not %d!", dlvl, lev); X } X#endif X pline("Strange, this map is not as I remember it."); X pline("Somebody is trying some trickery here..."); X pline("This game is void."); X done(TRICKED); X } X X#if defined(SMALLDATA) && defined(MACOS) X { X /* this assumes that the size of a row of struct rm's is <128 */ X short i, length, j; X char *ptr, *src, *p, *d; X X d = calloc(ROWNO*COLNO, sizeof(struct rm)); X p = d; X mread(fd, (genericptr_t)&j, sizeof(short)); X mread(fd, (genericptr_t)d, j); X for (i = 0; i < COLNO; i++) { X length = (short)(*p++); X ptr = p; X src = (char *)&levl[i][0]; X UnpackBits(&ptr, &src, ROWNO * sizeof(struct rm)); X if ((ptr - p) != length) X panic("restore - corrupted file on unpacking\n"); X p = ptr; X } X free(d); X } X#else X mread(fd, (genericptr_t) levl, sizeof(levl)); X#endif X mread(fd, (genericptr_t) osymbol, sizeof(osymbol)); X#ifdef REINCARNATION X if (memcmp((genericptr_t) osymbol, ((dlevel==rogue_level) X ? (genericptr_t)savesyms : (genericptr_t)showsyms), X sizeof (osymbol)) X && dlvl != rogue_level) { X /* rogue level always uses default syms. Although showsyms X * will be properly initialized from environment when restoring X * a game, this routine is called upon saving as well as X * restoring; when saving on the Rogue level, showsyms will X * be wrong, so use savesyms (which is always right, both on X * saving and restoring). X */ X#else X if (memcmp((genericptr_t) osymbol, X (genericptr_t) showsyms, sizeof (showsyms))) { X#endif X for (x = 0; x < COLNO; x++) X for (y = 0; y < ROWNO; y++) { X osym = levl[x][y].scrsym; X nsym = 0; X switch (levl[x][y].typ) { X case STONE: X case SCORR: X if (osym == osymbol[S_stone]) X nsym = showsyms[S_stone]; X break; X case ROOM: X#ifdef STRONGHOLD X case DRAWBRIDGE_DOWN: X#endif /* STRONGHOLD /**/ X if (osym == osymbol[S_room]) X nsym = showsyms[S_room]; X break; X case DOOR: X if (osym == osymbol[S_ndoor]) X nsym = showsyms[S_ndoor]; X else if (osym == osymbol[S_vodoor]) X nsym = showsyms[S_vodoor]; X else if (osym == osymbol[S_hodoor]) X nsym = showsyms[S_hodoor]; X else if (osym == osymbol[S_cdoor]) X nsym = showsyms[S_cdoor]; X break; X case CORR: X if (osym == osymbol[S_corr]) X nsym = showsyms[S_corr]; X break; X case VWALL: X if (osym == osymbol[S_vwall]) X nsym = showsyms[S_vwall]; X#ifdef STRONGHOLD X else if (osym == osymbol[S_dbvwall]) X nsym = showsyms[S_dbvwall]; X#endif X break; X case HWALL: X if (osym == osymbol[S_hwall]) X nsym = showsyms[S_hwall]; X#ifdef STRONGHOLD X else if (osym == osymbol[S_dbhwall]) X nsym = showsyms[S_dbhwall]; X#endif X break; X case TLCORNER: X if (osym == osymbol[S_tlcorn]) X nsym = showsyms[S_tlcorn]; X break; X case TRCORNER: X if (osym == osymbol[S_trcorn]) X nsym = showsyms[S_trcorn]; X break; X case BLCORNER: X if (osym == osymbol[S_blcorn]) X nsym = showsyms[S_blcorn]; X break; X case BRCORNER: X if (osym == osymbol[S_brcorn]) X nsym = showsyms[S_brcorn]; X break; X case SDOOR: X if (osym == osymbol[S_vwall]) X nsym = showsyms[S_vwall]; X else if (osym == osymbol[S_hwall]) X nsym = showsyms[S_hwall]; X break; X case CROSSWALL: X if (osym == osymbol[S_crwall]) X nsym = showsyms[S_crwall]; X break; X case TUWALL: X if (osym == osymbol[S_tuwall]) X nsym = showsyms[S_tuwall]; X break; X case TDWALL: X if (osym == osymbol[S_tdwall]) X nsym = showsyms[S_tdwall]; X break; X case TLWALL: X if (osym == osymbol[S_tlwall]) X nsym = showsyms[S_tlwall]; X break; X case TRWALL: X if (osym == osymbol[S_trwall]) X nsym = showsyms[S_trwall]; X break; X case STAIRS: X if (osym == osymbol[S_upstair]) X nsym = showsyms[S_upstair]; X else if (osym == osymbol[S_dnstair]) X nsym = showsyms[S_dnstair]; X break; X#ifdef STRONGHOLD X case LADDER: X if (osym == osymbol[S_upladder]) X nsym = showsyms[S_upladder]; X else if (osym == osymbol[S_dnladder]) X nsym = showsyms[S_dnladder]; X break; X#endif /* STRONGHOLD /**/ X case POOL: X case MOAT: X#ifdef STRONGHOLD X case DRAWBRIDGE_UP: X#endif /* STRONGHOLD /**/ X if (osym == osymbol[S_pool]) X nsym = showsyms[S_pool]; X break; X#ifdef FOUNTAINS X case FOUNTAIN: X if (osym == osymbol[S_fountain]) X nsym = showsyms[S_fountain]; X break; X#endif /* FOUNTAINS /**/ X#ifdef THRONES X case THRONE: X if (osym == osymbol[S_throne]) X nsym = showsyms[S_throne]; X break; X#endif /* THRONES /**/ X#ifdef SINKS X case SINK: X if (osym == osymbol[S_sink]) X nsym = showsyms[S_sink]; X break; X#endif /* SINKS /**/ X#ifdef ALTARS X case ALTAR: X if (osym == osymbol[S_altar]) X nsym = showsyms[S_altar]; X break; X#endif /* ALTARS /**/ X default: X break; X } X if (nsym) X levl[x][y].scrsym = nsym; X } X } X X mread(fd, (genericptr_t)&omoves, sizeof(omoves)); X mread(fd, (genericptr_t)&xupstair, sizeof(xupstair)); X mread(fd, (genericptr_t)&yupstair, sizeof(yupstair)); X mread(fd, (genericptr_t)&xdnstair, sizeof(xdnstair)); X mread(fd, (genericptr_t)&ydnstair, sizeof(ydnstair)); X#ifdef STRONGHOLD X mread(fd, (genericptr_t)&xupladder, sizeof(xupladder)); X mread(fd, (genericptr_t)&yupladder, sizeof(yupladder)); X mread(fd, (genericptr_t)&xdnladder, sizeof(xdnladder)); X mread(fd, (genericptr_t)&ydnladder, sizeof(ydnladder)); X#endif X mread(fd, (genericptr_t)&fountsound, sizeof(fountsound)); X mread(fd, (genericptr_t)&sinksound, sizeof(sinksound)); X fmon = restmonchn(fd, ghostly); X X /* regenerate animals while on another level */ X { long tmoves = (monstermoves > omoves) ? monstermoves-omoves : 0; X register struct monst *mtmp2; X X for(mtmp = fmon; mtmp; mtmp = mtmp2) { X X mtmp2 = mtmp->nmon; X if((mtmp->data->geno&G_GENOD) && !(mtmp->data->geno&G_UNIQ)) { X /* mondead() would try to link the monster's objects X * into fobj and the appropriate nexthere chain. X * unfortunately, such things will not have sane X * values until after find_lev_obj() well below X * here, so we'd go chasing random pointers if we X * tried that. we could save the monster's objects X * in another chain and insert them in the level X * later, but that's a lot of work for very little X * gain. hence, just throw the objects away via X * mongone() and pretend the monster wandered off X * somewhere private before the genocide. X */ X mongone(mtmp); X continue; X } X X if (ghostly) { X /* reset peaceful/malign relative to new character */ X if(!mtmp->isshk) X /* shopkeepers will reset based on name */ X mtmp->mpeaceful = peace_minded(mtmp->data); X set_malign(mtmp); X } else if (mtmp->mtame && tmoves > 250) X mtmp->mtame = mtmp->mpeaceful = 0; X X /* restore shape changers - Maarten Jan Huisjes */ X if (mtmp->data == &mons[PM_CHAMELEON] X && !Protection_from_shape_changers X && !mtmp->cham) X mtmp->cham = 1; X else if(Protection_from_shape_changers) { X if (mtmp->cham) { X mtmp->cham = 0; X (void) newcham(mtmp, &mons[PM_CHAMELEON]); X } else if(is_were(mtmp->data) && !is_human(mtmp->data)) X (void) new_were(mtmp); X } X X if (!ghostly) { X nhp = mtmp->mhp + X (regenerates(mtmp->data) ? tmoves : tmoves/20); X if(!mtmp->mcansee && mtmp->mblinded) { X if (mtmp->mblinded < tmoves) mtmp->mblinded = 0; X else mtmp->mblinded -= tmoves; X } X if(!mtmp->mcanmove && mtmp->mfrozen) { X if (mtmp->mfrozen < tmoves) mtmp->mfrozen = 0; X else mtmp->mfrozen -= tmoves; X } X if(nhp > mtmp->mhpmax) X mtmp->mhp = mtmp->mhpmax; X else X#ifdef LINT /* (long)newhp -> (schar = short int) mhp; ok in context of text above */ X mtmp->mhp = 0; X#else X mtmp->mhp = nhp; X#endif X } X } X } X X fgold = 0; X while(gold = newgold(), X mread(fd, (genericptr_t)gold, sizeof(struct gold)), X gold->gx) { X gold->ngold = fgold; X fgold = gold; X } X free((genericptr_t) gold); X ftrap = 0; X while (trap = newtrap(), X mread(fd, (genericptr_t)trap, sizeof(struct trap)), X trap->tx) { X trap->ntrap = ftrap; X ftrap = trap; X } X free((genericptr_t) trap); X fobj = restobjchn(fd, ghostly); X find_lev_obj(); X billobjs = restobjchn(fd, ghostly); X rest_engravings(fd); X mread(fd, (genericptr_t)rooms, sizeof(rooms)); X mread(fd, (genericptr_t)doors, sizeof(doors)); X#ifdef WORM X mread(fd, (genericptr_t)wsegs, sizeof(wsegs)); X for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){ X wheads[tmp] = wsegs[tmp] = wtmp = newseg(); X while(1) { X mread(fd, (genericptr_t)wtmp, sizeof(struct wseg)); X if(!wtmp->nseg) break; X wheads[tmp]->nseg = wtmp = newseg(); X wheads[tmp] = wtmp; X } X } X mread(fd, (genericptr_t)wgrowtime, sizeof(wgrowtime)); X#endif X X /* reset level.monsters for new level */ X for (x = 0; x < COLNO; x++) X for (y = 0; y < ROWNO; y++) X level.monsters[x][y] = (struct monst *) 0; X for (mtmp = level.monlist; mtmp; mtmp = mtmp->nmon) X place_monster(mtmp, mtmp->mx, mtmp->my); X X#ifdef TUTTI_FRUTTI X /* Now get rid of all the temp fruits... */ X if (ghostly) { X struct fruit *fruit; X X while(oldfruit) { X fruit = oldfruit->nextf; X free((genericptr_t) oldfruit); X oldfruit = fruit; X } X } X#endif X if(ghostly && lev > medusa_level && lev < stronghold_level && X xdnstair == 0) { X coord cc; X X mazexy(&cc); X xdnstair = cc.x; X ydnstair = cc.y; X levl[cc.x][cc.y].typ = STAIRS; X } X} X X#ifdef ZEROCOMP X#define RLESC '\0' /* Leading character for run of RLESC's */ X Xstatic unsigned char NEARDATA inbuf[BUFSZ]; Xstatic unsigned short NEARDATA inbufp = 0; Xstatic unsigned short NEARDATA inbufsz = 0; Xstatic short NEARDATA inrunlength = -1; Xstatic int NEARDATA mreadfd; Xstatic int NDECL(mgetc); X Xstatic int Xmgetc() X{ X if (inbufp >= inbufsz) { X inbufsz = read(mreadfd, (genericptr_t)inbuf, (int)sizeof inbuf); X if (!inbufsz) { X if (inbufp > sizeof inbuf) X error("EOF on file #%d.\n", mreadfd); X inbufp = 1 + sizeof inbuf; /* exactly one warning :-) */ X return -1; X } X inbufp = 0; X } X return inbuf[inbufp++]; X} X Xvoid Xminit() X{ X inbufsz = 0; X inbufp = 0; X inrunlength = -1; X} X Xint Xmread(fd, buf, len) Xint fd; Xgenericptr_t buf; Xregister unsigned len; X{ X /*register int readlen = 0;*/ X mreadfd = fd; X while (len--) { X if (inrunlength > 0) { X inrunlength--; X *(*((char **)&buf))++ = '\0'; X } else { X register short ch = mgetc(); X if (ch < 0) return -1; /*readlen;*/ X if ((*(*(char **)&buf)++ = ch) == RLESC) { X inrunlength = mgetc(); X } X } X /*readlen++;*/ X } X return 0; /*readlen;*/ X} X X#else /* ZEROCOMP */ X Xvoid Xmread(fd, buf, len) Xregister int fd; Xregister genericptr_t buf; Xregister unsigned int len; X{ X register int rlen; X X#if defined(BSD) || defined(ULTRIX) X rlen = read(fd, buf, (int) len); X if(rlen != len){ X#else /* e.g. SYSV, __TURBOC__ */ X rlen = read(fd, buf, (unsigned) len); X if((unsigned)rlen != len){ X#endif X pline("Read %d instead of %u bytes.\n", rlen, len); X if(restoring) { X (void) unlink(SAVEF); X#ifdef AMIGA_WBENCH X ami_wbench_unlink(SAVEF); X#endif X error("Error restoring old game."); X } X panic("Error reading level file."); X } X} X#endif /* ZEROCOMP */ END_OF_FILE if test 25217 -ne `wc -c <'src/restore.c'`; then echo shar: \"'src/restore.c'\" unpacked with wrong size! fi # end of 'src/restore.c' fi echo shar: End of archive 27 \(of 56\). cp /dev/null ark27isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 56 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0