billr@saab.CNA.TEK.COM (Bill Randle) (07/12/90)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 10, Issue 84 Archive-name: nethack3p9/Part39 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 39 (of 56)." # Contents: amiga/amidos.c auxil/MacHelp others/Makefile.os2 # others/maintain.ovl # Wrapped by billr@saab on Wed Jul 11 17:11:51 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'amiga/amidos.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'amiga/amidos.c'\" else echo shar: Extracting \"'amiga/amidos.c'\" \(16788 characters\) sed "s/^X//" >'amiga/amidos.c' <<'END_OF_FILE' X/* SCCS Id: @(#)amidos.c msdos.c - Amiga version 3.0 89/05/01 X/* NetHack may be freely redistributed. See license for details. */ X/* An assortment of imitations of cheap plastic MSDOS functions. X */ X X#define NEED_VARARGS X#include "hack.h" X X#undef TRUE X#undef FALSE X#undef COUNT X#undef NULL X X#include <libraries/dos.h> X#ifdef LATTICE X#include <proto/exec.h> X#include <proto/dos.h> X#endif X X/* Prototypes for functions defined in amidos.c */ Xvoid NDECL (flushout); Xint NDECL (getpid); Xint FDECL (abs, (int x)); Xint NDECL (tgetch); Xint NDECL (dosh); Xlong FDECL (freediskspace, (char *path)); Xlong FDECL (filesize, (char *file)); Xvoid FDECL (eraseall, (char *path, X char *files)); Xchar *FDECL (CopyFile, (char *from, X char *to)); Xvoid FDECL (copybones, (int mode)); Xvoid NDECL (playwoRAMdisk); Xint FDECL (saveDiskPrompt, (int start)); Xvoid NDECL (gameDiskPrompt); Xvoid NDECL (read_config_file); Xvoid NDECL (set_lock_and_bones); Xvoid FDECL (append_slash, (char *name)); Xvoid FDECL (getreturn, (char *str)); Xvoid VDECL (msmsg, (char *fmt, ...)); XFILE * FDECL (fopenp, (char *name, X char *mode)); Xint FDECL (chdir, (char *dir)); Xvoid FDECL (msexit, (int code)); Xstatic boolean NDECL (record_exists); Xstatic int FDECL (strcmpi, (register char *a, register char *b)); X Xextern char Initialized; X X#ifdef AZTEC_C Xstruct DateStamp *FDECL(DateStamp, (struct DateStamp *)); XBPTR FDECL(Lock, (char *, long)); XBPTR FDECL(CurrentDir, (BPTR)); XBPTR FDECL(Open, (char *, long)); Xlong FDECL(Read, (BPTR, char *, long)); Xlong FDECL(Write, (BPTR, char *, long)); Xlong NDECL(IoErr); Xlong FDECL(AvailMem, (long)); Xvoid *FDECL(malloc, (unsigned int)); Xchar *FDECL(rindex, (char *, int)); Xchar *FDECL(index, (char *, int)); X#endif X Xint Enable_Abort = 0; /* for stdio package */ X X/* Initial path, so we can find NetHack.cnf */ X Xchar PATH[PATHLEN] = "Ram:;df0:;NetHack:"; X Xvoid Xflushout() X{ X (void) fflush(stdout); X} X X#ifndef getuid Xgetuid() X{ X return 1; X} X#endif X X/* X * Actually make up a process id. X * Makes sure one can mess less with saved levels... X */ X Xint getpid() X{ X static short pid; X X while (pid == 0) { X struct DateStamp dateStamp; X pid = rnd(30000); X pid += (short) DateStamp(&dateStamp); /* More or less random */ X pid ^= (short) (dateStamp.ds_Days >> 16) ^ X (short) (dateStamp.ds_Days) ^ X (short) (dateStamp.ds_Minute) + X (short) (dateStamp.ds_Tick); X pid %= 30000; X } X X return (int)pid; X} X X#ifndef getlogin Xchar * Xgetlogin() X{ X return ((char *) NULL); X} X#endif X Xint Xabs(x) Xint x; X{ X return x < 0? -x: x; X} X Xint Xtgetch() { X char ch; X X ch = WindowGetchar(); X return ((ch == '\r') ? '\n' : ch); X} X X#ifdef DGK X# include <ctype.h> X/* # include <fcntl.h> */ X X# define Sprintf (void) sprintf X X# ifdef SHELL Xint Xdosh() X{ X pline("No mysterious force prevented you from using multitasking."); X return 0; X} X# endif /* SHELL */ X X#define ID_DOS1_DISK 'DOS\1' X#define EXTENSION 72 X X/* X * This routine uses an approximation of the free bytes on a disk. X * How large a file you can actually write depends on the number of X * extension blocks you need for it. X * In each extenstion block there are maximum 72 pointers to blocks, X * so every 73 disk blocks have only 72 available for data. X * The (necessary) file header is also good for 72 data block pointers. X */ Xlong Xfreediskspace(path) Xchar *path; X{ X register long freeBytes = 0; X register struct InfoData *infoData; /* Remember... longword aligned */ X char fileName[32]; X X /* X * Find a valid path on the device of which we want the free space. X * If there is a colon in the name, it is an absolute path X * and all up to the colon is everything we need. X * Remember slashes in a volume name are allowed! X * If there is no colon, it is relative to the current directory, X * so must be on the current device, so "" is enough... X */ X { X register char *colon; X X strncpy(fileName, path, sizeof(fileName)-1); X fileName[31] = 0; X if (colon = index(fileName, ':')) X colon[1] = '\0'; X else X fileName[0] = '\0'; X } X X if (infoData = malloc(sizeof(struct InfoData))) { X BPTR fileLock; X if (fileLock = Lock(fileName, SHARED_LOCK)) { X if (Info(fileLock, infoData)) { X /* We got a kind of DOS volume, since we can Lock it. */ X /* Calculate number of blocks available for new file */ X /* Kludge for the ever-full VOID: (oops RAM:) device */ X if (infoData->id_UnitNumber == -1 && X infoData->id_NumBlocks == infoData->id_NumBlocksUsed) { X freeBytes = AvailMem(0L) - 64 * 1024L; X /* Just a stupid guess at the */ X /* Ram-Handler overhead per block: */ X freeBytes -= freeBytes/16; X } else { X /* Normal kind of DOS file system device/volume */ X freeBytes = infoData->id_NumBlocks - X infoData->id_NumBlocksUsed; X freeBytes -= (freeBytes + EXTENSION) / (EXTENSION + 1); X freeBytes *= infoData->id_BytesPerBlock; X } X if (freeBytes < 0) X freeBytes = 0; X } X UnLock(fileLock); X } X free(infoData); X } X return freeBytes; X} X X Xlong Xfilesize(file) Xchar *file; X{ X register BPTR fileLock; X register struct FileInfoBlock *fileInfoBlock; X register long size = 0; X X if (fileInfoBlock = malloc(sizeof(struct FileInfoBlock))) { X if (fileLock = Lock(file, SHARED_LOCK)) { X if (Examine(fileLock, fileInfoBlock)) { X size = fileInfoBlock->fib_Size; X } X UnLock(fileLock); X } X free(fileInfoBlock); X } X return size; X} X X/* X * On the Amiga, looking if a specific file exists is much faster X * than sequentially reading a directory. X */ X Xvoid Xeraseall(path, files) Xchar *path, *files; X{ X char buf[FILENAME]; X short i; X BPTR fileLock, dirLock; X X if (dirLock = Lock(path ,SHARED_LOCK)) { X dirLock = CurrentDir(dirLock); X X strcpy(buf, files); X for (i = 0; i <= MAXLEVEL; i++) { X name_file(buf, i); X if (fileLock = Lock(buf, SHARED_LOCK)) { X UnLock(fileLock); X DeleteFile(buf); X } else if (IoErr() == ERROR_DEVICE_NOT_MOUNTED) X break; X } X X UnLock(CurrentDir(dirLock)); X } X} X X/* This size makes that most files can be copied with two Read()/Write()s */ X X#define COPYSIZE 4096 X Xchar *CopyFile(from, to) Xchar *from, *to; X{ X register BPTR fromFile, toFile; X register char *buffer; X register long size; X char *error = NULL; X X if (buffer = malloc(COPYSIZE)) { X if (fromFile = Open(from, MODE_OLDFILE)) { X if (toFile = Open(to, MODE_NEWFILE)) { X while (size = Read(fromFile, buffer, (long)COPYSIZE)) { X if (size != Write(toFile, buffer, size)) { X error = "Write error"; X break; X } X } X Close(toFile); X } else /* Can't open destination file */ X error = "Cannot open destination"; X Close(fromFile); X } else /* Cannot open source file. Should not happen. */ X error = "Huh?? Cannot open source??"; X free(buffer); X return error; X } else /* Cannot obtain buffer for copying */ X return "No Memory !"; X} X Xvoid Xcopybones(mode) Xint mode; X{ X BPTR fileLock; X char from[FILENAME], to[FILENAME]; X char *frompath, *topath, *status; X short i; X extern int saveprompt; X X if (!ramdisk) X return; X X frompath = (mode != TOPERM) ? permbones : levels; X topath = (mode == TOPERM) ? permbones : levels; X X /* Remove any bones files in `to' directory. */ X eraseall(topath, allbones); X X /* Copy `from' to `to' */ X strcpy(from, frompath); X strcat(from, allbones); X strcpy(to, topath); X strcat(to, allbones); X X for (i = 1; i < MAXLEVEL; i++) { X name_file(from, i); X name_file(to, i); X if (fileLock = Lock(from, SHARED_LOCK)) { X UnLock(fileLock); X if (status = CopyFile(from, to)) X goto failed; X } else if (IoErr() == ERROR_DEVICE_NOT_MOUNTED) { X status = "disk not present"; X goto failed; X } X } X X /* X * The last file got there. Remove the ramdisk bones files. X */ X if (mode == TOPERM) X eraseall(frompath, allbones); X return; X X /* Last file didn't get there. */ X Xfailed: X msmsg("Cannot copy `%s' to `%s'\n(%s)\n", from, to, status); X X if (mode == TOPERM) { X msmsg("Bones will be left in `%s'\n", X *frompath ? frompath : hackdir); X return; X } else { X /* Remove all bones files on the RAMdisk */ X eraseall(levels, allbones); X playwoRAMdisk(); X } X} X Xvoid XplaywoRAMdisk() X{ X msmsg("Do you wish to play without a RAMdisk (y/n) ? "); X X /* Set ramdisk false *before* exit'ing (because msexit calls X * copybones) X */ X ramdisk = FALSE; X if (Getchar() != 'y') { X settty("Be seeing you ...\n"); X exit(0); X } X set_lock_and_bones(); X return; X} X Xint XsaveDiskPrompt(start) X{ X extern int saveprompt; X char buf[BUFSIZ], *bp; X BPTR fileLock; X X if (saveprompt) { X /* Don't prompt if you can find the save file */ X if (fileLock = Lock(SAVEF, SHARED_LOCK)) { X UnLock(fileLock); X return 1; X } X remember_topl(); X home(); X cl_end(); X msmsg("If save file is on a SAVE disk, put that disk in 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{ X FILE *file; X X if (file = fopenp(RECORD, "r")) { X fclose(file); X return TRUE; X } X return FALSE; X} X X/* Prompt for game disk, then check for record file. X */ Xvoid XgameDiskPrompt() X{ X extern int saveprompt; X X if (record_exists()) X return; X X if (saveprompt) { X (void) putchar('\n'); X getreturn("when the GAME disk has been put in"); X } X X if (!record_exists()) { X msmsg("\n\nWARNING: can't find record file `%s'!\n", RECORD); X X msmsg("If the GAME disk is not in, put it in now.\n"); X getreturn("to continue"); X } X} X X/* Read configuration */ Xvoid Xread_config_file() X{ X char tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN]; X char buf[BUFSZ], *bufp; X FILE *fp; X extern char plname[]; X extern int saveprompt; X X tmp_ramdisk[0] = 0; X tmp_levels[0] = 0; X if ((fp = fopenp(configfile, "r")) == NULL) { 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 = index(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 } else if (!strncmp(buf, "RAMDISK", 3)) { X strncpy(tmp_ramdisk, bufp, PATHLEN); 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, (boolean)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 char *ptr; X if (ptr = index(bufp, ';')) { X *ptr = '\0'; X if (*(ptr+1) == 'n' || *(ptr+1) == 'N') X saveprompt = FALSE; X } X (void) strncpy(SAVEF, bufp, PATHLEN); X append_slash(SAVEF); X } else if (!strncmp(buf, "GRAPHICS", 4)) { X unsigned int translate[MAXPCHARS+1]; /* for safety */ X int lth; X X if ((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])) < 0) { X msmsg ("Syntax error in GRAPHICS\n"); X getreturn("to continue"); X } /* Yuck! Worked only with low-byte first!!! */ X assign_graphics(translate, lth); X } else if (!strncmp(buf, "PATH", 4)) { X strncpy(PATH, bufp, PATHLEN); X X } else { X msmsg("Bad option line: '%s'\n", buf); X getreturn("to continue"); X } X } X fclose(fp); X X strcpy(permbones, tmp_levels); X if (tmp_ramdisk[0]) { X strcpy(levels, tmp_ramdisk); X if (strcmpi(permbones, levels)) /* if not identical */ X ramdisk = TRUE; X } else X strcpy(levels, tmp_levels); X strcpy(bones, levels); X} X X/* Set names for bones[] and lock[] */ X Xvoid Xset_lock_and_bones() X{ 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} X X/* X * Add a slash 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 != ':') { X *++ptr = '/'; X *++ptr = '\0'; X } X} X X Xvoid Xgetreturn(str) Xchar *str; X{ X int ch; X X msmsg("Hit <RETURN> %s.", str); X while ((ch = Getchar()) != '\n') X ; X} X Xvoid Xmsmsg VA_DECL(char *, fmt) X VA_START(fmt); X VA_INIT(fmt, char *); X#ifdef LATTICE X { X extern struct Screen *HackScreen; X char buf[100]; X vsprintf(buf,fmt,VA_ARGS); X if(HackScreen){ X WindowFPuts(buf); X WindowFlush(); X } else { X fprintf(stdout,buf); X fflush(stdout); X } X } X#else X vprintf(fmt, VA_ARGS); X (void) fflush(stdout); X#endif X VA_END(); X} X X/* Follow the PATH, trying to fopen the file. X */ X#define PATHSEP ';' X#undef fopen X XFILE * Xfopenp(name, mode) Xregister char *name, *mode; X{ X char buf[BUFSIZ], *bp, *pp, lastch; X FILE *fp; X register BPTR theLock; X X /* Try the default directory first. Then look along PATH. X */ X strcpy(buf, name); X if (theLock = Lock(buf, SHARED_LOCK)) { X UnLock(theLock); X if (fp = fopen(buf, mode)) X return fp; X } X pp = PATH; X while (pp && *pp) { X bp = buf; X while (*pp && *pp != PATHSEP) X lastch = *bp++ = *pp++; X if (lastch != ':' && lastch != '/' && bp != buf) X *bp++ = '/'; X strcpy(bp, name); X if (theLock = Lock(buf, SHARED_LOCK)) { X UnLock(theLock); X if (fp = fopen(buf, mode)) X return fp; X } X if (*pp) X pp++; X } X return NULL; X} X#endif /* DGK */ X X#ifdef CHDIR X X/* X * A not general-purpose directory changing routine. X * Assumes you want to return to the original directory eventually, X * by chdir()ing to orgdir. X * Assumes -1 is not a valid lock, since 0 is valid. X */ X X#define NO_LOCK ((BPTR) -1) X Xchar orgdir[1]; Xstatic BPTR OrgDirLock = NO_LOCK; X Xchdir(dir) Xchar *dir; X{ X if (dir == orgdir) { X /* We want to go back to where we came from. */ X if (OrgDirLock != NO_LOCK) { X UnLock(CurrentDir(OrgDirLock)); X OrgDirLock = NO_LOCK; X } X } else { X /* X * Go to some new place. If still at the original X * directory, save the FileLock. X */ X BPTR newDir; X X if (newDir = Lock(dir, SHARED_LOCK)) { X if (OrgDirLock == NO_LOCK) { X OrgDirLock = CurrentDir(newDir); X } else { X UnLock(CurrentDir(newDir)); X } X } else { X return -1; /* Failed */ X } X } X /* CurrentDir always succeeds if you have a lock */ X return 0; X} X X#endif X X/* Chdir back to original directory X */ X#undef exit Xvoid Xmsexit(code) X{ X#ifdef CHDIR X extern char orgdir[]; X#endif X X#ifdef DGK X (void) fflush(stdout); X if (ramdisk) X copybones(TOPERM); X#endif X#ifdef CHDIR X chdir(orgdir); /* chdir, not chdirx */ X#endif X X CleanUp(); X exit(code); X} X X/* X * Strcmp while ignoring case. Not general-purpose, so static. X */ X Xstatic int strcmpi(a, b) Xregister char *a, *b; X{ X while (tolower(*a) == tolower(*b)) { X if (!*a) /* *a == *b, so at end of both strings */ X return 0; /* equal. */ X a++; X b++; X } X return 1; X} X X/* X * memcmp - used to compare two struct symbols, in lev.c X */ X X#if defined(AZTEC_C) && !defined(memcmp) Xmemcmp(a, b, size) Xregister unsigned char *a, *b; Xregister int size; X{ X while (size--) { X if (*a++ != *b++) X return 1; /* not equal */ X } X X return 0; /* equal */ X} X#endif END_OF_FILE if test 16788 -ne `wc -c <'amiga/amidos.c'`; then echo shar: \"'amiga/amidos.c'\" unpacked with wrong size! fi # end of 'amiga/amidos.c' fi if test -f 'auxil/MacHelp' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'auxil/MacHelp'\" else echo shar: Extracting \"'auxil/MacHelp'\" \(3856 characters\) sed "s/^X//" >'auxil/MacHelp' <<'END_OF_FILE' X Macintosh Nethack Primer X XMovement X X y k u 7 8 9 UP the mouse X \|/ \|/ | cursor shows X h-.-l 4-.-6 LEFT<- ->RIGHT which way X /|\ /|\ | you'll move X b j n 1 2 3 DOWN when clicked. X keyboard numberpad cursor keys mouse click X XMove commands and modifiers: Xyuhjklbn: go one step in specified direction XYUHJKLBN: go in specified direction until you X hit a wall or run into something. X[CTRL]<dir>, Xg<dir>: run in direction <dir> until something X interesting is seen. X[SHIFT]<dir>, XG<dir>: same, except a branching corridor isn't considered X interesting. Xm<dir>: move without picking up objects. X XFor all Macintosh keyboards the [command] key (apple or pretzel key) Xfunctions as the [control] key and the [~] key functions as the [escape] Xkey. The normal [control] and [escape] keys are also supported. X XThe Number Pad XWhen the window title shows "[MOVE]", the number keys may also be used Xto move your character, otherwise they act as a numeric keypad. X XThe '5' key on the numberpad invokes the "open door" command. XThe '0' key on the numberpad invokes the "do inventory" command. X XThe 'g', 'G', '[SHIFT]', [CTRL] and 'm' modifiers may also be used with Xthe numberpad and the cursor keys. X XPress the clear key (or Num Lock) on the number pad to enable or disable Xusing the number pad for movement. X XThe Cursor XAlthough NetHack was meant to be played from a keyboard, on the Macintosh Xyou can essentially play NetHack using the mouse. The mouse cursor shows Xwhich direction you will try to move if you press the mouse button when Xthe mouse is in the Nethack window. Of course, if you're confused this may Xbe different. You may use the 'g', 'G', '[SHIFT]' and 'm' modifiers with Xthe mouse button, too. Note that [SHIFT]-clicking on the spot where you're Xstanding will "look" at the objects piled there. Holding down the mouse Xbutton will, after a delay, cause repeated moves in the indicated direction. X XThe cursor will at times also indicate your current state of well-being. XThese auxiliary cursors may look better on a non-inverted screen (they Xlook best against the standard white Macintosh background). The cursor Xmadness can be controlled from the "Set Options" dialog (see below). X XAlerts XOccasionally a mac alert will appear in response to some action of yours. XThese mac alerts typically require a "yes" or "no" (or alternate) response. XYou can accept the default response button (indicated by a surrounding Xhilite) by clicking on that button, hitting return or typing the first Xletter of that button (i.e. y for yes). The alternate response(s) can be Xchosen by clicking on them or typing their first letter, appropriately. X XMacintosh-specific Options XMultiFinder AutoZoom: when enabled shrinks the NetHack window to icon size Xwhen the game is context-swapped out and restores the window upon return. X XAlternative Cursors: when enabled allows the standard NetHack arrow cursor Xset to be replaced by "hands" while blind a/o "strange" cursors while Xhallucinating, if not blind, and so on. This does not affect the randomly Xoriented cursors that appear when you're confused or stunned. A fatal Xskull-n-crossbones cursor set will appear if you become deathly sick. X XThe other NetHack options are described elsewhere under the "?" command. XThe names may be slightly different on the options dialog. X XMiscellaneous XThe option key is the meta-key. For option-n, press option-shift-n and Xfor option-u, press option-shift-u. X XBug Reports XComments, questions, problems, etc. should be directed to (InterNet): Xnethack-bugs@linc.cis.upenn.edu X X END_OF_FILE if test 3856 -ne `wc -c <'auxil/MacHelp'`; then echo shar: \"'auxil/MacHelp'\" unpacked with wrong size! fi # end of 'auxil/MacHelp' fi if test -f 'others/Makefile.os2' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'others/Makefile.os2'\" else echo shar: Extracting \"'others/Makefile.os2'\" \(17844 characters\) sed "s/^X//" >'others/Makefile.os2' <<'END_OF_FILE' X# SCCS Id: @(#)Makefile.os2 3.0 90/02/22 X# OS/2 NetHack 3.0 Makefile for Microsoft(tm) C 5.1 -- Timo Hakulinen X# X# NDMAKE ver 4.5 or MS-NMAKE is required, MS-MAKE will not work. X# To enable either make utility, uncomment the respective X# make-specific macros. If you plan to cross-compile in DOS, your X# best bet is NDMAKE, since it requires less memory than NMAKE. X# To compile in OS/2 use NMAKE or compatible. Remember to set X# $(RLIBS) to real mode libraries if compiling in DOS, and to X# protected mode libraries for compilation in OS/2. X# X# Copy pctty.c, pcunix.c, pcmain.c, msdos.c and this file X# (+ termcap library if used) into $(SRC) directory, rename X# this file to "makefile" (important, some targets rely on it), X# compile and link inside $(SRC). Termcap library can be built X# from termcap sources using makefile.lib in "others" directory. X# X# When using CodeView versions earlier than ver. 2.3, define X# OS2_CODEVIEW in pcconf.h and set HACKDIR (+ TERM and TERMCAP X# if used) in OS/2 config.sys. Otherwise path searches may fail. X# X# Note that $(GAMEDIR) must exist prior to compilation. X# XCC = cl XLINK = link XLIB = lib X X# Enable the upper three lines for NDMAKE and lower three for MS-NMAKE. X# ($(MAKE) macro is often predefined, so we use $(MAKEBIN) instead). XMAKEBIN = make XAB = $*.c XCB = $*.c X#MAKEBIN = nmake X#AB = $(@B).c X#CB = $$(@B).c X X# For those of us who have these on PC. X#YACC = yacc X#LEX = lex XYACC = bison -y XLEX = flex X# Standard file names may vary in PC installations. XYTABC = y_tab.c XYTABH = y_tab.h XLEXYYC = lexyy.c X X# Directories (makedefs hardcodes these, don't change them). XINCL = ..\include XAUX = ..\auxil XSRC = ..\src XOBJ = $(SRC)\o2 X X# The game name and description. XGAME = nethack XGAMEDES = NetHack 3.0 X X# The game directory. XGAMEDIR = \games\$(GAME) X X# Memory model, compile only, disable optimization, remove stack probes, X# 80286 instruction set, dedicated datasegment for items >= 5 bytes, X# pack structures on 1 byte boundaries, generate code for 8087 X# coprocessor, compiler warning level, include file path. XCFLAGS = /AL /c /Od /Gs /G2 /Gt5 /Zp1 /FPi87 /W1 /I$(INCL) $(CDFLAGS) X X# + prepare for CodeView symbolic debugger. XCDFLAGS = X#CDFLAGS = /Zi X X# Don't ignore case in symbols, no default lib search, stack 4096 bytes. X# (actually a bit of overkill), allow max 1024 segments in program. XLFLAGS = /noig /nod /stack:4096 /seg:1024 $(LDFLAGS) X X# + prepare for CodeView symbolic debugger. XLDFLAGS = X#LDFLAGS = /CO X X# Protected mode C libraries for 8087 (change if necessary), X# OS/2 API entry points. XPLIBS = llibc7p doscalls X X# C libraries used by makedefs and lev_comp (change if necessary). X# If compilation is done in DOS, enable the upper line, if in OS/2, X# the lower (protected mode libraries). XRLIBS = llibc7r X#RLIBS = $(PLIBS) X X# Module definition file for OS/2. XOS2DEFS = $(GAME).def X X# The default make target (so just typing 'make' is useful). Xdefault: $(GAME) X X# If you have yacc and lex programs and make any changes, comment out the X# upper two lines and uncomment the lower two. Xdo_yacc: yacc_msg Xdo_lex: lex_msg X#do_yacc: yacc_act X#do_lex: lex_act X X# Optional high-quality BSD random number generation routines (see pcconf.h). X# Set to nothing if not used. XRANDOM = $(OBJ)\random.o X#RANDOM = X X# If TERMLIB defined in pcconf.h, comment out the upper line and X# uncomment the lower. If the termcap-library doesn't exist, use X# others\makefile.lib to build it. XTERMLIB = X#TERMLIB = termlib.lib X X###################################################################### X# X# Nothing below this line should have to be changed. X# X# Other things that have to be reconfigured are in X# config.h, pcconf.h and possibly system.h. X# X X# The game filename. XGAMEFILE = $(GAMEDIR)\$(GAME).exe X X# Object files for makedefs. XMAKEOBJS = $(OBJ)\makedefs.o $(OBJ)\monst.o $(OBJ)\objects.o X X# Object files for special levels compiler. XSOBJ01 = $(OBJ)\lev_comp.o $(OBJ)\lev_lex.o $(OBJ)\lev_main.o $(OBJ)\alloc.o XSOBJ02 = $(OBJ)\monst.o $(OBJ)\objects.o $(OBJ)\panic.o X XSPLEVOBJS = $(SOBJ01) $(SOBJ02) X XVOBJ01 = $(OBJ)\allmain.o $(OBJ)\alloc.o $(OBJ)\apply.o $(OBJ)\artifact.o XVOBJ02 = $(OBJ)\attrib.o $(OBJ)\bones.o $(OBJ)\cmd.o $(OBJ)\dbridge.o XVOBJ03 = $(OBJ)\decl.o $(OBJ)\demon.o $(OBJ)\do.o $(OBJ)\do_name.o XVOBJ04 = $(OBJ)\do_wear.o $(OBJ)\dog.o $(OBJ)\dogmove.o $(OBJ)\dokick.o XVOBJ05 = $(OBJ)\dothrow.o $(OBJ)\eat.o $(OBJ)\end.o XVOBJ06 = $(OBJ)\engrave.o $(OBJ)\exper.o $(OBJ)\extralev.o $(OBJ)\fountain.o XVOBJ07 = $(OBJ)\getline.o $(OBJ)\hack.o $(OBJ)\invent.o $(OBJ)\lock.o XVOBJ08 = $(OBJ)\mail.o $(OBJ)\main.o $(OBJ)\makemon.o $(OBJ)\mcastu.o XVOBJ09 = $(OBJ)\mhitm.o $(OBJ)\mhitu.o $(OBJ)\mklev.o $(OBJ)\mkmaze.o XVOBJ10 = $(OBJ)\mkobj.o $(OBJ)\mkroom.o $(OBJ)\mon.o $(OBJ)\mondata.o XVOBJ11 = $(OBJ)\msdos.o $(OBJ)\monmove.o $(OBJ)\monst.o $(OBJ)\mthrowu.o XVOBJ12 = $(OBJ)\music.o $(OBJ)\o_init.o $(OBJ)\objects.o XVOBJ13 = $(OBJ)\objnam.o $(OBJ)\options.o $(OBJ)\pager.o $(OBJ)\pickup.o XVOBJ14 = $(OBJ)\polyself.o $(OBJ)\potion.o $(OBJ)\pray.o $(OBJ)\pri.o XVOBJ15 = $(OBJ)\priest.o $(OBJ)\prisym.o $(RANDOM) $(OBJ)\read.o XVOBJ16 = $(OBJ)\restore.o $(OBJ)\rip.o $(OBJ)\rnd.o $(OBJ)\rumors.o XVOBJ17 = $(OBJ)\save.o $(OBJ)\search.o $(OBJ)\shk.o $(OBJ)\shknam.o XVOBJ18 = $(OBJ)\sit.o $(OBJ)\sounds.o $(OBJ)\sp_lev.o $(OBJ)\spell.o XVOBJ20 = $(OBJ)\steal.o $(OBJ)\termcap.o $(OBJ)\timeout.o $(OBJ)\topl.o XVOBJ21 = $(OBJ)\topten.o $(OBJ)\track.o $(OBJ)\trap.o $(OBJ)\tty.o XVOBJ22 = $(OBJ)\u_init.o $(OBJ)\uhitm.o $(OBJ)\unix.o $(OBJ)\vault.o XVOBJ23 = $(OBJ)\weapon.o $(OBJ)\were.o $(OBJ)\wield.o XVOBJ24 = $(OBJ)\wizard.o $(OBJ)\worm.o $(OBJ)\worn.o $(OBJ)\write.o XVOBJ25 = $(OBJ)\zap.o XHHOBJ = $(OBJ)\version.o X XVOBJ = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) $(VOBJ06) $(VOBJ07) \ X $(VOBJ08) $(VOBJ09) $(VOBJ10) $(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) \ X $(VOBJ15) $(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ20) $(VOBJ21) $(VOBJ22) \ X $(VOBJ23) $(VOBJ24) $(VOBJ25) XHOBJ = $(VOBJ) $(HHOBJ) X XPCCONF_H = $(INCL)\pcconf.h $(INCL)\msdos.h $(INCL)\system.h \ X $(INCL)\extern.h $(INCL)\def_os2.h XGLOBAL_H = $(INCL)\global.h $(INCL)\coord.h $(PCCONF_H) XCONFIG_H = $(INCL)\config.h $(INCL)\tradstdc.h $(GLOBAL_H) XTRAP_H = $(INCL)\trap.h XPERMONST_H = $(INCL)\permonst.h $(INCL)\monattk.h $(INCL)\monflag.h XYOU_H = $(INCL)\you.h $(INCL)\attrib.h $(PERMONST_H) $(INCL)\mondata.h \ X $(INCL)\monst.h $(INCL)\youprop.h $(INCL)\prop.h $(INCL)\pm.h XDECL_H = $(INCL)\decl.h $(INCL)\spell.h $(INCL)\obj.h $(YOU_H) \ X $(INCL)\onames.h $(INCL)\color.h XHACK_H = $(CONFIG_H) $(DECL_H) $(INCL)\monsym.h $(INCL)\mkroom.h \ X $(INCL)\objclass.h $(INCL)\gold.h $(TRAP_H) $(INCL)\flag.h \ X $(INCL)\rm.h $(INCL)\hack.h X X# The default target X Xall: makedefs lev_comp $(GAME) auxil X @echo Done. X X# The main target X X$(GAME): $(OBJ) $(GAMEDIR)\$(GAME).exe X$(GAME).exe: $(GAMEDIR)\$(GAME).exe X$(GAMEDIR)\$(GAME).exe: $(GAME).res X $(LINK) @$(GAME).res X X$(GAME).res: $(HOBJ) $(OS2DEFS) X @echo $(VOBJ01) +> $@ X @echo $(VOBJ02) +>> $@ X @echo $(VOBJ03) +>> $@ X @echo $(VOBJ04) +>> $@ X @echo $(VOBJ05) +>> $@ X @echo $(VOBJ06) +>> $@ X @echo $(VOBJ07) +>> $@ X @echo $(VOBJ08) +>> $@ X @echo $(VOBJ09) +>> $@ X @echo $(VOBJ10) +>> $@ X @echo $(VOBJ11) +>> $@ X @echo $(VOBJ12) +>> $@ X @echo $(VOBJ13) +>> $@ X @echo $(VOBJ14) +>> $@ X @echo $(VOBJ15) +>> $@ X @echo $(VOBJ16) +>> $@ X @echo $(VOBJ17) +>> $@ X @echo $(VOBJ18) +>> $@ X @echo $(VOBJ20) +>> $@ X @echo $(VOBJ21) +>> $@ X @echo $(VOBJ22) +>> $@ X @echo $(VOBJ23) +>> $@ X @echo $(VOBJ24) +>> $@ X @echo $(VOBJ25) +>> $@ X @echo $(HHOBJ)>> $@ X @echo $(GAMEDIR)\$(GAME)>> $@ X @echo $(GAME)>> $@ X @echo $(PLIBS) $(TERMLIB)>> $@ X @echo $(OS2DEFS) $(LFLAGS);>> $@ X X$(OBJ): X -mkdir $(OBJ) X X# Targets for makedefs. X Xmakedefs: $(OBJ) makedefs.exe Xmakedefs.exe: makedefs.res X $(LINK) @makedefs.res X Xmakedefs.res: $(MAKEOBJS) X @echo $(MAKEOBJS)> $@ X @echo makedefs>> $@ X @echo nul>> $@ X @echo $(RLIBS)>> $@ X @echo $(LFLAGS);>> $@ X X$(OBJ)\makedefs.o : $(CB) $(INCL)\config.h $(INCL)\permonst.h $(INCL)\objclass.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X X# Targets for the special levels compiler. X Xlev_comp: $(OBJ) lev_comp.exe Xlev_comp.exe: lev_comp.res X $(LINK) @lev_comp.res X Xlev_comp.res: $(SPLEVOBJS) X @echo $(SOBJ01) +> $@ X @echo $(SOBJ02)>> $@ X @echo lev_comp>> $@ X @echo nul>> $@ X @echo $(RLIBS)>> $@ X @echo $(LFLAGS);>> $@ X X$(OBJ)\lev_comp.o : $(CB) $(HACK_H) $(INCL)\sp_lev.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\lev_lex.o : $(CB) $(HACK_H) $(INCL)\sp_lev.h $(INCL)\lev_comp.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\lev_main.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X Xlev_comp.c : lev_comp.y X $(MAKEBIN) do_yacc X Xlev_lex.c : lev_comp.l X $(MAKEBIN) do_lex X Xyacc_msg: X @echo lev_comp.y has changed. To update lev_comp.c and lev_comp.h run YACC. X Xyacc_act: X $(YACC) -d lev_comp.y X copy $(YTABC) lev_comp.c X copy $(YTABH) $(INCL)\lev_comp.h X del $(YTABC) X del $(YTABH) X Xlex_msg: X @echo lev_comp.l has changed. To update lev_lex.c run LEX. X Xlex_act: X $(LEX) lev_comp.l X copy $(LEXYYC) lev_lex.c X del $(LEXYYC) X X# X# The following include files depend on makedefs to be created. X# X# date.h should be remade any time any of the source or include code X# is modified. X# X$(INCL)\date.h: $(VOBJ) makedefs.exe X makedefs -v X X$(INCL)\trap.h: makedefs.exe X makedefs -t X X$(INCL)\onames.h: makedefs.exe X makedefs -o X X$(INCL)\pm.h: makedefs.exe X makedefs -p X Xdata: $(AUX)\data.bas makedefs.exe X makedefs -d X Xrumors: $(AUX)\rumors.tru $(AUX)\rumors.fal makedefs.exe X makedefs -r X X# X# The following programs vary depending on what OS you are using. X# X$(OBJ)\main.o: pc$(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ pc$(AB) X X$(OBJ)\tty.o: pc$(CB) $(HACK_H) $(INCL)\func_tab.h X $(CC) $(CFLAGS) /Fo$@ pc$(AB) X X$(OBJ)\unix.o: pc$(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ pc$(AB) X X# X# Secondary targets X# X Xauxil: spec_lev data rumors X xcopy $(AUX)\cmdhelp $(GAMEDIR) X xcopy $(AUX)\help $(GAMEDIR) X xcopy $(AUX)\hh $(GAMEDIR) X xcopy $(AUX)\history $(GAMEDIR) X xcopy $(AUX)\license $(GAMEDIR) X xcopy $(AUX)\opthelp $(GAMEDIR) X xcopy $(AUX)\oracles $(GAMEDIR) X xcopy $(AUX)\data $(GAMEDIR) X xcopy $(AUX)\rumors $(GAMEDIR) X Xspec_lev: $(AUX)\castle.des $(AUX)\endgame.des $(AUX)\tower.des X lev_comp $(AUX)\castle.des X lev_comp $(AUX)\endgame.des X lev_comp $(AUX)\tower.des X xcopy castle $(GAMEDIR) X xcopy endgame $(GAMEDIR) X xcopy tower? $(GAMEDIR) X del castle X del endgame X del tower? X X$(OS2DEFS): X @echo NAME $(GAME) WINDOWCOMPAT> $(OS2DEFS) X @echo DESCRIPTION '$(GAMEDES)'>> $(OS2DEFS) X @echo PROTMODE>> $(OS2DEFS) X @echo EXETYPE OS2>> $(OS2DEFS) X Xclean: X -del $(OBJ)\*.o X -rmdir $(OBJ) X Xspotless: clean X -del $(INCL)\date.h X -del $(INCL)\onames.h X -del $(INCL)\pm.h X -del makedefs.exe X -del lev_comp.exe X -del *.res X -del *.def X -del *.map X -del $(AUX)\data X -del $(AUX)\rumors X -del castle X -del endgame X -del tower? X X# X# Other dependencies. X# X# MS-NMAKE doesn't give a damn about default rules here, so until X# that is fixed, we do this the hard way. X# X X$(OBJ)\allmain.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\alloc.o : $(CB) $(CONFIG_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\apply.o : $(CB) $(HACK_H) $(INCL)\edog.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\artifact.o : $(CB) $(HACK_H) $(INCL)\artifact.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\attrib.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\bones.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\cmd.o : $(CB) $(HACK_H) $(INCL)\func_tab.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\dbridge.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\decl.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\demon.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\do.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\do_name.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\do_wear.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\dog.o : $(CB) $(HACK_H) $(INCL)\edog.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\dogmove.o : $(CB) $(HACK_H) $(INCL)\mfndpos.h $(INCL)\edog.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\dokick.o : $(CB) $(HACK_H) $(INCL)\eshk.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\dothrow.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\eat.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\end.o : $(CB) $(HACK_H) $(INCL)\eshk.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\engrave.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\exper.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\extralev.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\fountain.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\getline.o : $(CB) $(HACK_H) $(INCL)\func_tab.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\hack.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\invent.o : $(CB) $(HACK_H) $(INCL)\lev.h $(INCL)\wseg.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\ioctl.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\lock.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\makemon.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mail.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mcastu.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mhitm.o : $(CB) $(HACK_H) $(INCL)\artifact.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mhitu.o : $(CB) $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mklev.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mkmaze.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mkobj.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mkroom.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mon.o : $(CB) $(HACK_H) $(INCL)\mfndpos.h $(INCL)\wseg.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mondata.o : $(CB) $(HACK_H) $(INCL)\eshk.h $(INCL)\epri.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\monmove.o : $(CB) $(HACK_H) $(INCL)\mfndpos.h $(INCL)\artifact.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\monst.o : $(CB) $(CONFIG_H) $(PERMONST_H) $(INCL)\monsym.h $(INCL)\eshk.h \ X $(INCL)\vault.h $(INCL)\epri.h $(INCL)\color.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\msdos.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\mthrowu.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\music.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\o_init.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\objects.o : $(CB) $(CONFIG_H) $(INCL)\obj.h $(INCL)\objclass.h $(INCL)\prop.h \ X $(INCL)\color.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\objnam.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\options.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\pager.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\panic.o : $(CB) $(CONFIG_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\pickup.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\polyself.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\potion.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\pray.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\pri.o : $(CB) $(HACK_H) $(INCL)\epri.h $(INCL)\termcap.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\priest.o : $(CB) $(HACK_H) $(INCL)\mfndpos.h $(INCL)\eshk.h $(INCL)\epri.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\prisym.o : $(CB) $(HACK_H) $(INCL)\lev.h $(INCL)\wseg.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\random.o : $(CB) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\read.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\restore.o : $(CB) $(HACK_H) $(INCL)\lev.h $(INCL)\wseg.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\rip.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\rnd.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\rumors.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\save.o : $(CB) $(HACK_H) $(INCL)\lev.h $(INCL)\wseg.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\search.o : $(CB) $(HACK_H) $(INCL)\artifact.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\shk.o : $(CB) $(HACK_H) $(INCL)\eshk.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\shknam.o : $(CB) $(HACK_H) $(INCL)\eshk.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\sit.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\sounds.o : $(CB) $(HACK_H) $(INCL)\edog.h $(INCL)\eshk.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\sp_lev.o : $(CB) $(HACK_H) $(INCL)\sp_lev.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\spell.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\steal.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\termcap.o : $(CB) $(HACK_H) $(INCL)\termcap.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\timeout.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\topl.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\topten.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\track.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\trap.o : $(CB) $(HACK_H) $(INCL)\edog.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\u_init.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\uhitm.o : $(CB) $(HACK_H) $(INCL)\artifact.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\vault.o : $(CB) $(HACK_H) $(INCL)\vault.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\version.o : $(CB) $(HACK_H) $(INCL)\date.h $(INCL)\patchlev.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\weapon.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\were.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\wield.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\wizard.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\worm.o : $(CB) $(HACK_H) $(INCL)\wseg.h X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\worn.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\write.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) X$(OBJ)\zap.o : $(CB) $(HACK_H) X $(CC) $(CFLAGS) /Fo$@ $(AB) END_OF_FILE if test 17844 -ne `wc -c <'others/Makefile.os2'`; then echo shar: \"'others/Makefile.os2'\" unpacked with wrong size! fi # end of 'others/Makefile.os2' fi if test -f 'others/maintain.ovl' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'others/maintain.ovl'\" else echo shar: Extracting \"'others/maintain.ovl'\" \(17778 characters\) sed "s/^X//" >'others/maintain.ovl' <<'END_OF_FILE' X Maintaining PC NetHack X ======================== X Last revision: 1990may27 X XThe installation of the system of overlay management that currently Xbrings full-featured NetHack to the IBM PC and compatibles has Xintroduced a number of arcanities into the source code of the Xprogramme, and unfortunately running afoul of these intricacies can Xresult (as we ourselves have discovered) in the most bizarre and Xstrangely inexplicable dysfunctional manifestations, aka sick bugs. X XThis document is required reading for anyone making substantive Xchanges to NetHack for the PC or embarking upon a revision of its Xoverlay structure. X X X1. The overlay manager X---------------------- XNetHack is by now a fairly large programme (in excess of 800 Xkilobytes), and in order to compile it for the PC (which typically Xhas little more than 500k of available memory) it was necessary to Xrely on the technique of _overlaying_, whereby not all the Xprogramme is resident in memory at the same time, segments of the Xprogramme being loaded and discarded as they are needed. Unlike Xtraditional candidates for the overlaying strategy, however, NetHack Xdoes not exhibit strongly phased behaviour; although much of the code Xis not being used at any one moment, there is comparatively little Xcode that can be confidently said not to be related to or potentially Xnecessary for the immediate progress of the game. X Furthermore we wished to develop an overlaying strategy that Xdid _not_ involve intimate knowledge of the operation of the Xprogramme (since NetHack is an international team effort, and few Xpeople have a good feeling for the totality of the code structure), Xand which would not require substantive changes to the source code, Ximpacting on its maintainability and portability. X It turned out to be impossible to satisfy these goals with Xtools that are widely available at the time of writing, and so we Xundertook to write our own overlay manager (compatible with XMicrosoft's, but more in concert with NetHack's particular needs). XThe result is called ovlmgr.asm and is documented in the file Xovlmgr.doc. You would probably be well advised to read at least the Xless technical parts of that file now. X X X2. The trampoli mechanism X------------------------- XOne of the difficulties with using overlays for C (particularly XMicrosoft C) is that while common C programming practise places heavy Xreliance on function pointers, Microsoft's overlay linker is unable Xto resolve calls through pointers to functions that are in remote Xoverlays. Nor, unfortunately, does it choose to report such failures; Xrather, it generates calls into (what often turns out to be in the Xcase of our nonstandard overlay manager) the deepest of space. This Xcan result in truly strange behaviour on the part of your programme - Xincluding bugs that come and go in as close to a random pattern as Xyou are ever likely to see. X Other than the creative use of pattern-matching utilities Xsuch as grep to locate the offending calls, there is unfortunately no Xadvice we can offer in tracking down these bugs. Once they have been Xisolated, however, they can be remedied straightforwardly. X XIn order for the linker not to screw up on a pointered function call Xit is (to simplify an actually rather complicated situation) Xnecessary that the function called be located in the ROOT "overlay", Xand thus not be subject to swapping. Rather than linking the full Xtext of every pointered function into the root, however, it suffices Xto place a "trampoline" function there which performs a direct call Xto the "real" function that does the work, in whatever overlay it Xmight naturally reside in. Due to a not-quite-accident of the Xbehaviour of the C preprocessor (it was originally intended to make Xpossible functions whose address can be taken but which expand inline Xas macros where possible, a not unrelated function), it turns out to Xbe possible to arrange for this without major change to the C source Xcode - and without serious impact on the performance of "regular" Xcalls to the same functions. X XThe C preprocessor's expansion of a macro with parameters is triggered Xby an encounter with the macro name immediately followed by an open Xparenthesis. If the name is found, but it is not followed by a Xparenthesis, the macro is not matched and no expansion takes place. XAt the same time it may be noted that (unless someone has been oddly Xstrange and enclosed a function name in quite unneeded parentheses!), Xa function name is typically followed by an open parenthesis if, and Xonly if, it is being declared, defined or invoked; if its address is Xbeing taken it will necessarily be followed by some other token. XFurthermore (except in the unfortunate case of the ill-conceived Xnew-style ANSI declaration of a function that takes no parameters) it Xwill be observed that the number of parameters to a call of the Xfunction (assuming that this number is fixed; if not, I grant, we Xhave a problem) is the same in all these contexts. This implies that Xif all the modules of a programme are uniformly processed in the Xcontext of a macro definition such as X X #define zook(a,b) plenk(a,b) X Xand assuming that all functions named zook() take exactly two Xarguments, then the resulting programme will be completely identical Xto the original (without this definition) except that the link Xmap will report the existence of the function plenk() in place of Xzook() -- UNLESS there was a place in the programme where the address Xof zook was taken. In that case, the linker would report an Xunresolved external reference for that symbol. X That unresolved reference is, of course, precisely what we Xneed; if in another source file (one that did not see the macro Xdefinition) we placed the function declaration X X some_t zook(this_t a, that_t b) X { extern some_t plenk(this_t, that_t); X return plenk(a, b); X } X Xthis would both satisfy the unresolved reference and restore the Xoriginal semantics of the programme (even including pointer Xcomparison!) -- while providing us with precisely the kind of X"trampoline" module that we need to circumvent the problem with the Xlinker. X This is the basis of the approach we have taken in PC XNetHack; rather than using the somewhat idiosyncratic identifier X"plenk", however, we have systematically employed (in the files Xtrampoli.h and trampoli.c) identifiers generated by appending Xunderscores to the ends of the names of the functions we have needed Xto so indirect(1). X XThere are a few small complications. The first is ensuring that both Xthe versions of the trampoli'd function (foo() and foo_()) are Xsimilarly typed by the appropriate extern declarations (which Xthemselves must be written); this can be accomplished by placing all Xof these declarations in a header file that is processed _twice_, Xonce before and once after the inclusion of the file containing the Xtrampoli macro definitions, thereby ensuring that both variants of Xthe name have been seen in connection with the appropriate types. The Xsecond is that some care must be exercised not to employ other macros Xthat interfere with the normal recognition of function syntax: it is Xthe presence of the open parenthesis after the name of the function Xthat triggers name substitution, and not the fact that the function Xis called; and so (particularly in the case of declarations) it is Xnecessary that if a macro is used to supply the _arguments_ of a Xtrampoli'd function, it must also supply the name (this necessity in Xfact triggered a change in the style of the macros that provide Xdialect-independent function declaration in NetHack; the new style Xwould have you write FDECL(functionName, (argTypes...)). X Finally, there is the case of functions declared to take no Xarguments whatsoever; in Standard C this is notated: X X some_t aFunction(void); X Xfor no theoretically well-motivated reason I can discern. Such a Xdeclaration will _not_ match a macro definition such as X X #define aFunction() aFunction_() X X-- in fact the compiler will detect an error when processing that Xdeclaration in the scope of this macro. The only solution is to Xeschew the use of this strange syntax and unfrabjously forgo the Xconcomitant security of well- and thoroughly- checked typage. To Xwhich end we have provided an ecchy macro, NDECL(functionName), which Xuses the new syntax _unless_ the compiler is not Standard or OVERLAY Xis enabled. X XThere is one further consideration: that this technique only applies, Xof course, to functions that are published to the linker. For this Xreason, wherever such trampoli'd functions were originally declared Xstatic, that declaration has been changed to "STATIC_PTR", a macro Xthat expands to "static" unless the OVERLAY flag has been selected in Xthe configuration file, enabling the trampoli mechanism. Thus such Xfunctions lose their privacy in this one case. X X X3. OVLx X------- XThe strategies described above work fine, but they only stretch so Xfar. In particular, they do not admit of an overlay structure in Xwhich functions are linked into different overlays even though they Xoriginate in the same source file. X Classically, this is not considered a real limitation, Xbecause one has the freedom to regroup the functions into different Xsource files as needed; however, in the case of NetHack this was not Xa realistic option, since what structure this unwieldy programme has Xis precisely in the current grouping of functions together. XNonetheless, the ability to perform some functional grouping is an Xabsolute requirement for acceptable performance, since many NetHack Xsource modules (were.c, for example) contain one or two tiny Xfunctions that are called with great frequency (several millions of Xtimes per game is not unheard of) and whose return value determines Xwhether the remaining large, slow functions of the file will be Xrequired at all in the near future. Obviously these small checking Xfunctions should be linked into the same overlays with their callers, Xwhile the remainder of the source module should not. X XIn order to make this possible we ran a dynamic profile on the game Xto determine exactly which functions in which modules required such Xdistinguished treatment, and we have flagged each function for Xconditional compilation (with #if ... #endif) in groups according Xapproximately to their frequency of invocation and functionality. XThese groups have been arbitrarily named in each source file (in Xdecreasing order of frequency), OVL0, OVL1, OVL2, OVL3 and OVLB (B Xfor "base functions", those that deserve no special treatment at Xall). It is thus possible to compile only a small number of the Xfunctions in a file by defining but one or two of these symbols on Xthe compiler's command line (with the switch /DOVL2, for example); Xthe compiler will ignore the remainder as if they did not exist. X(There is an "escape clause" in hack.h that ensures that if none of Xthese flags is defined on the command line, then all of them will be Xduring compilation; this makes the non-use of this mechanism Xstraightforward!) X By repeated invocation of the compiler on the _same_ source Xfile it is possible to accumulate disjoint object modules that Xbetween them contain the images of all the functions in the original Xsource, but partitioned as is most convenient. Care must, of course, Xbe taken over conflicts of name in both the object file put out (all Xslices will by default be called SRCFILE.OBJ, and this default must Xbe overridden with distinct file names for each output slice) and in Xthe names of the text segments the compiler is to generate; you can Xsee this at work in Makefile.ovl. (You may wonder, as we did at Xfirst, why the text segment name would have to be made distinct in Xeach object file slice (the default segment name is a function of the Xsource file name and the compilation model only). The reason for this Xis, quite daftly to my mind, that the linker considers the identity Xof segment names and combine classes better reason to combine Xsegments than the programmer's explicit instructions in the requested Xoverlay pattern are reason to keep them apart. Programmer, ask not Xwhy...). X XOnce again, that works fine except for the small matter of Xdeclarations (where have we heard this before?). For objects that Xonce were static must now be made visible to the linker that they may Xbe resolved across the reaches of inter-overlay space. To this end we Xhave provided three macros, all of which expand simply to "static" if Xno OVLx flags are defined on the compilation command line. They are: X XSTATIC_DCL which introduces a declaration (as distinct from a X definition) of an object that would be static were it X not for the requirements of the OVLx mechanism. Its X expansion is "static", normally, but it becomes X "extern" in the event that this source file has been X split into slices with the OVLx mechanism. X XSTATIC_OVL is used when _defining_ a function (giving its text, X that is) that is logically static but may be called X across slices; it expands to "static" unless OVLx is X active; in the latter case it expands to null, X leaving the function with "previous linkage" as the X standard says. Note that this behaviour is quite X similar to, but very different from, that of X STATIC_PTR (described above), which has the same two X expansions but which is triggered not by OVLx but by X the OVERLAY flag which enables the trampoli mechanism. X STATIC_OVL also differs from the STATIC_DCL X and STATIC_VAR in that it is employed _within_ OVLx X slices, while the others are used to generate X declarations and are deployed in areas common to all X slices. X XSTATIC_VAR is used to introduce uninitialised would-be-static X variables. Its expansion is complex, since it must X read as "static" in the usual case, but as "extern" X if OVLx is in use -- in all overlays but one, where X it must expand to the null sequence -- giving it X "previous linkage" and "tentative definition" (to X ensure that the variable gets defined at all). X This one took a while to get right, and X believe me, using the macro is a lot easier than X trying to keep the #ifdefs straight yourself! X XAn initialised variable that is file-level static unless OVLx is in Xuse must now be written with a STATIC_DCL declaration, and a Xdefinition (and static initialiser) enclosed within the bracketing Xtag of one of the OVLx slices (any will do; we use OVLB). X Type definitions, macro definitions and extern declarations Xshould, of course remain outside any OVLx slice. X XFinally, of course, objects whose visibility need not be extended may Xsafely continue to be declared static. And in this case, at least, Xthe compiler will provide diagnostics that inform you when an object Xhas slipped through the cracks and requires the application of Magic XMacro Salve. X XIt is perhaps less than obvious that when a function is _both_ called Xacross an OVLx split and referenced through a pointer, it should be Xtreated as a pointered function (that is, it should get trampoli Xentries and should be defined STATIC_PTR). The reason for this is that Xthe STATIC_xxx macros associated with OVLx _only_ change the Xdeclaration patterns of the objects, while trampoli results in the Xgeneration of necessary code. X It is correct to do this, because the declarations produced by XSTATIC_PTR are triggered by OVERLAY's being defined, and the selection Xof OVERLAY is an absolute precondition for the activation of OVLx. X X X4. Hacking X---------- XBefore undertaking any serious modifications to the overlay structure Xor support mechanisms, you should know that a _lot_ of work has gone Xinto the current scheme. If performance seems poor, remember: the Xoverlay manager itself can be invoked up to ten thousand times in a Xsecond, and although the space available for loading overlays (once Xthe data and stack spaces have been accounted for) is less than half Xthe total size of the overlays that are swapped through it, a disk Xaccess occurs well under 0.1% of the time(2). Furthermore, this Xperformance (such as it is) has been achieved without substantive Xchange or restructuring of the NetHack source code, which must remain Xportable to many platforms other than the PC. X XIf these observations do not daunt you, you are a true Bit Warrior Xindeed (or aspiration anyway), and we await your comments with bait. X X------------------------------------------------------------------------ X XNOTES: X------ X X(1) In fact, we have applied this technique throughout NetHack, even X in cases where it is not strictly necessary (since the pointered X calls are not across overlay splits, for example - though note X that there are more splits than might be initially apparent, due X to the effects of the OVLx hackage as described in section 3). X There is, however, one exception; and beware: it is an exception X with fangs. The file termcap.c contains a few pointered functions X that we decided _not_ to trampoli for performance reasons (screen X output is one of the problem areas on the PC port at the moment, X in terms of performance). It is therefore vital to the health of X PC NetHack as it currently stands that the OVLx slice termcap.0 be X linked into the ROOT "overlay". X X(2) These figures are for a 4.77 MHz PC-XT running in low memory with X an older version of both the overlay manager and the NetHack X overlay arrangement. On a more capable computer and with the X current software, the figures are probably more like a 100kHz peak X service rate and a hit rate (since we fixed the bug in the LRU X clock logic!) in excess of 99.99% -- hopefully not both at the X same time. X X------------------------------------------------------------------------ XStephen P Spackman stephen@tira.uchicago.edu X------------------------------------------------------------------------ X * Hack On! * END_OF_FILE if test 17778 -ne `wc -c <'others/maintain.ovl'`; then echo shar: \"'others/maintain.ovl'\" unpacked with wrong size! fi # end of 'others/maintain.ovl' fi echo shar: End of archive 39 \(of 56\). cp /dev/null ark39isdone 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