This is amidos.c in view mode; [Download] [Up]
/* SCCS Id: @(#)amidos.c msdos.c - Amiga version 3.0 89/05/01 /* NetHack may be freely redistributed. See license for details. */ /* An assortment of imitations of cheap plastic MSDOS functions. */ #define NEED_VARARGS #include "hack.h" #undef TRUE #undef FALSE #undef COUNT #undef NULL #include <libraries/dos.h> #ifdef LATTICE #include <proto/exec.h> #include <proto/dos.h> #endif /* Prototypes for functions defined in amidos.c */ void NDECL (flushout); int NDECL (getpid); int FDECL (abs, (int x)); int NDECL (tgetch); int NDECL (dosh); long FDECL (freediskspace, (char *path)); long FDECL (filesize, (char *file)); void FDECL (eraseall, (char *path, char *files)); char *FDECL (CopyFile, (char *from, char *to)); void FDECL (copybones, (int mode)); void NDECL (playwoRAMdisk); int FDECL (saveDiskPrompt, (int start)); void NDECL (gameDiskPrompt); void NDECL (read_config_file); void NDECL (set_lock_and_bones); void FDECL (append_slash, (char *name)); void FDECL (getreturn, (char *str)); void VDECL (msmsg, (char *fmt, ...)); FILE * FDECL (fopenp, (char *name, char *mode)); int FDECL (chdir, (char *dir)); void FDECL (msexit, (int code)); static boolean NDECL (record_exists); static int FDECL (strcmpi, (register char *a, register char *b)); extern char Initialized; #ifdef AZTEC_C struct DateStamp *FDECL(DateStamp, (struct DateStamp *)); BPTR FDECL(Lock, (char *, long)); BPTR FDECL(CurrentDir, (BPTR)); BPTR FDECL(Open, (char *, long)); long FDECL(Read, (BPTR, char *, long)); long FDECL(Write, (BPTR, char *, long)); long NDECL(IoErr); long FDECL(AvailMem, (long)); void *FDECL(malloc, (unsigned int)); char *FDECL(rindex, (char *, int)); char *FDECL(index, (char *, int)); #endif int Enable_Abort = 0; /* for stdio package */ /* Initial path, so we can find NetHack.cnf */ char PATH[PATHLEN] = "Ram:;df0:;NetHack:"; void flushout() { (void) fflush(stdout); } #ifndef getuid getuid() { return 1; } #endif /* * Actually make up a process id. * Makes sure one can mess less with saved levels... */ int getpid() { static short pid; while (pid == 0) { struct DateStamp dateStamp; pid = rnd(30000); pid += (short) DateStamp(&dateStamp); /* More or less random */ pid ^= (short) (dateStamp.ds_Days >> 16) ^ (short) (dateStamp.ds_Days) ^ (short) (dateStamp.ds_Minute) + (short) (dateStamp.ds_Tick); pid %= 30000; } return (int)pid; } #ifndef getlogin char * getlogin() { return ((char *) NULL); } #endif int abs(x) int x; { return x < 0? -x: x; } int tgetch() { char ch; ch = WindowGetchar(); return ((ch == '\r') ? '\n' : ch); } #ifdef DGK # include <ctype.h> /* # include <fcntl.h> */ # define Sprintf (void) sprintf # ifdef SHELL int dosh() { pline("No mysterious force prevented you from using multitasking."); return 0; } # endif /* SHELL */ #define ID_DOS1_DISK 'DOS\1' #define EXTENSION 72 /* * This routine uses an approximation of the free bytes on a disk. * How large a file you can actually write depends on the number of * extension blocks you need for it. * In each extenstion block there are maximum 72 pointers to blocks, * so every 73 disk blocks have only 72 available for data. * The (necessary) file header is also good for 72 data block pointers. */ long freediskspace(path) char *path; { register long freeBytes = 0; register struct InfoData *infoData; /* Remember... longword aligned */ char fileName[32]; /* * Find a valid path on the device of which we want the free space. * If there is a colon in the name, it is an absolute path * and all up to the colon is everything we need. * Remember slashes in a volume name are allowed! * If there is no colon, it is relative to the current directory, * so must be on the current device, so "" is enough... */ { register char *colon; strncpy(fileName, path, sizeof(fileName)-1); fileName[31] = 0; if (colon = index(fileName, ':')) colon[1] = '\0'; else fileName[0] = '\0'; } if (infoData = malloc(sizeof(struct InfoData))) { BPTR fileLock; if (fileLock = Lock(fileName, SHARED_LOCK)) { if (Info(fileLock, infoData)) { /* We got a kind of DOS volume, since we can Lock it. */ /* Calculate number of blocks available for new file */ /* Kludge for the ever-full VOID: (oops RAM:) device */ if (infoData->id_UnitNumber == -1 && infoData->id_NumBlocks == infoData->id_NumBlocksUsed) { freeBytes = AvailMem(0L) - 64 * 1024L; /* Just a stupid guess at the */ /* Ram-Handler overhead per block: */ freeBytes -= freeBytes/16; } else { /* Normal kind of DOS file system device/volume */ freeBytes = infoData->id_NumBlocks - infoData->id_NumBlocksUsed; freeBytes -= (freeBytes + EXTENSION) / (EXTENSION + 1); freeBytes *= infoData->id_BytesPerBlock; } if (freeBytes < 0) freeBytes = 0; } UnLock(fileLock); } free(infoData); } return freeBytes; } long filesize(file) char *file; { register BPTR fileLock; register struct FileInfoBlock *fileInfoBlock; register long size = 0; if (fileInfoBlock = malloc(sizeof(struct FileInfoBlock))) { if (fileLock = Lock(file, SHARED_LOCK)) { if (Examine(fileLock, fileInfoBlock)) { size = fileInfoBlock->fib_Size; } UnLock(fileLock); } free(fileInfoBlock); } return size; } /* * On the Amiga, looking if a specific file exists is much faster * than sequentially reading a directory. */ void eraseall(path, files) char *path, *files; { char buf[FILENAME]; short i; BPTR fileLock, dirLock; if (dirLock = Lock(path ,SHARED_LOCK)) { dirLock = CurrentDir(dirLock); strcpy(buf, files); for (i = 0; i <= MAXLEVEL; i++) { name_file(buf, i); if (fileLock = Lock(buf, SHARED_LOCK)) { UnLock(fileLock); DeleteFile(buf); } else if (IoErr() == ERROR_DEVICE_NOT_MOUNTED) break; } UnLock(CurrentDir(dirLock)); } } /* This size makes that most files can be copied with two Read()/Write()s */ #define COPYSIZE 4096 char *CopyFile(from, to) char *from, *to; { register BPTR fromFile, toFile; register char *buffer; register long size; char *error = NULL; if (buffer = malloc(COPYSIZE)) { if (fromFile = Open(from, MODE_OLDFILE)) { if (toFile = Open(to, MODE_NEWFILE)) { while (size = Read(fromFile, buffer, (long)COPYSIZE)) { if (size != Write(toFile, buffer, size)) { error = "Write error"; break; } } Close(toFile); } else /* Can't open destination file */ error = "Cannot open destination"; Close(fromFile); } else /* Cannot open source file. Should not happen. */ error = "Huh?? Cannot open source??"; free(buffer); return error; } else /* Cannot obtain buffer for copying */ return "No Memory !"; } void copybones(mode) int mode; { BPTR fileLock; char from[FILENAME], to[FILENAME]; char *frompath, *topath, *status; short i; extern int saveprompt; if (!ramdisk) return; frompath = (mode != TOPERM) ? permbones : levels; topath = (mode == TOPERM) ? permbones : levels; /* Remove any bones files in `to' directory. */ eraseall(topath, allbones); /* Copy `from' to `to' */ strcpy(from, frompath); strcat(from, allbones); strcpy(to, topath); strcat(to, allbones); for (i = 1; i < MAXLEVEL; i++) { name_file(from, i); name_file(to, i); if (fileLock = Lock(from, SHARED_LOCK)) { UnLock(fileLock); if (status = CopyFile(from, to)) goto failed; } else if (IoErr() == ERROR_DEVICE_NOT_MOUNTED) { status = "disk not present"; goto failed; } } /* * The last file got there. Remove the ramdisk bones files. */ if (mode == TOPERM) eraseall(frompath, allbones); return; /* Last file didn't get there. */ failed: msmsg("Cannot copy `%s' to `%s'\n(%s)\n", from, to, status); if (mode == TOPERM) { msmsg("Bones will be left in `%s'\n", *frompath ? frompath : hackdir); return; } else { /* Remove all bones files on the RAMdisk */ eraseall(levels, allbones); playwoRAMdisk(); } } void playwoRAMdisk() { msmsg("Do you wish to play without a RAMdisk (y/n) ? "); /* Set ramdisk false *before* exit'ing (because msexit calls * copybones) */ ramdisk = FALSE; if (Getchar() != 'y') { settty("Be seeing you ...\n"); exit(0); } set_lock_and_bones(); return; } int saveDiskPrompt(start) { extern int saveprompt; char buf[BUFSIZ], *bp; BPTR fileLock; if (saveprompt) { /* Don't prompt if you can find the save file */ if (fileLock = Lock(SAVEF, SHARED_LOCK)) { UnLock(fileLock); return 1; } remember_topl(); home(); cl_end(); msmsg("If save file is on a SAVE disk, put that disk in now.\n"); cl_end(); msmsg("File name (default `%s'%s) ? ", SAVEF, start ? "" : ", <Esc> cancels save"); getlin(buf); home(); cl_end(); curs(1, 2); cl_end(); if (!start && *buf == '\033') return 0; /* Strip any whitespace. Also, if nothing was entered except * whitespace, do not change the value of SAVEF. */ for (bp = buf; *bp; bp++) if (!isspace(*bp)) { strncpy(SAVEF, bp, PATHLEN); break; } } return 1; } /* Return 1 if the record file was found */ static boolean record_exists() { FILE *file; if (file = fopenp(RECORD, "r")) { fclose(file); return TRUE; } return FALSE; } /* Prompt for game disk, then check for record file. */ void gameDiskPrompt() { extern int saveprompt; if (record_exists()) return; if (saveprompt) { (void) putchar('\n'); getreturn("when the GAME disk has been put in"); } if (!record_exists()) { msmsg("\n\nWARNING: can't find record file `%s'!\n", RECORD); msmsg("If the GAME disk is not in, put it in now.\n"); getreturn("to continue"); } } /* Read configuration */ void read_config_file() { char tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN]; char buf[BUFSZ], *bufp; FILE *fp; extern char plname[]; extern int saveprompt; tmp_ramdisk[0] = 0; tmp_levels[0] = 0; if ((fp = fopenp(configfile, "r")) == NULL) { msmsg("Warning: no configuration file!\n"); getreturn("to continue"); return; } while (fgets(buf, BUFSZ, fp)) { if (*buf == '#') continue; /* remove trailing whitespace */ bufp = index(buf, '\n'); while (bufp > buf && isspace(*bufp)) bufp--; if (bufp == buf) continue; /* skip all-blank lines */ else *(bufp + 1) = 0; /* 0 terminate line */ /* find the '=' */ if (!(bufp = index(buf, '='))) { msmsg("Bad option line: '%s'\n", buf); getreturn("to continue"); continue; } /* skip whitespace between '=' and value */ while (isspace(*++bufp)) ; /* Go through possible variables */ if (!strncmp(buf, "HACKDIR", 4)) { strncpy(hackdir, bufp, PATHLEN); } else if (!strncmp(buf, "RAMDISK", 3)) { strncpy(tmp_ramdisk, bufp, PATHLEN); } else if (!strncmp(buf, "LEVELS", 4)) { strncpy(tmp_levels, bufp, PATHLEN); } else if (!strncmp(buf, "OPTIONS", 4)) { parseoptions(bufp, (boolean)TRUE); if (plname[0]) /* If a name was given */ plnamesuffix(); /* set the character class */ } else if (!strncmp(buf, "SAVE", 4)) { char *ptr; if (ptr = index(bufp, ';')) { *ptr = '\0'; if (*(ptr+1) == 'n' || *(ptr+1) == 'N') saveprompt = FALSE; } (void) strncpy(SAVEF, bufp, PATHLEN); append_slash(SAVEF); } else if (!strncmp(buf, "GRAPHICS", 4)) { unsigned int translate[MAXPCHARS+1]; /* for safety */ int lth; if ((lth = sscanf(bufp, "%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", &translate[0], &translate[1], &translate[2], &translate[3], &translate[4], &translate[5], &translate[6], &translate[7], &translate[8], &translate[9], &translate[10], &translate[11], &translate[12], &translate[13], &translate[14], &translate[15], &translate[16], &translate[17], &translate[18], &translate[19], &translate[20], &translate[21], &translate[22], &translate[23], &translate[24], &translate[25], &translate[26], &translate[27], &translate[28], &translate[29], &translate[30], &translate[31], &translate[32], &translate[33], &translate[34])) < 0) { msmsg ("Syntax error in GRAPHICS\n"); getreturn("to continue"); } /* Yuck! Worked only with low-byte first!!! */ assign_graphics(translate, lth); } else if (!strncmp(buf, "PATH", 4)) { strncpy(PATH, bufp, PATHLEN); } else { msmsg("Bad option line: '%s'\n", buf); getreturn("to continue"); } } fclose(fp); strcpy(permbones, tmp_levels); if (tmp_ramdisk[0]) { strcpy(levels, tmp_ramdisk); if (strcmpi(permbones, levels)) /* if not identical */ ramdisk = TRUE; } else strcpy(levels, tmp_levels); strcpy(bones, levels); } /* Set names for bones[] and lock[] */ void set_lock_and_bones() { if (!ramdisk) { strcpy(levels, permbones); strcpy(bones, permbones); } append_slash(permbones); append_slash(levels); append_slash(bones); strcat(bones, allbones); strcpy(lock, levels); strcat(lock, alllevels); } /* * Add a slash to any name not ending in / or :. There must * be room for the /. */ void append_slash(name) char *name; { char *ptr; if (!*name) return; ptr = name + (strlen(name) - 1); if (*ptr != '/' && *ptr != ':') { *++ptr = '/'; *++ptr = '\0'; } } void getreturn(str) char *str; { int ch; msmsg("Hit <RETURN> %s.", str); while ((ch = Getchar()) != '\n') ; } void msmsg VA_DECL(char *, fmt) VA_START(fmt); VA_INIT(fmt, char *); #ifdef LATTICE { extern struct Screen *HackScreen; char buf[100]; vsprintf(buf,fmt,VA_ARGS); if(HackScreen){ WindowFPuts(buf); WindowFlush(); } else { fprintf(stdout,buf); fflush(stdout); } } #else vprintf(fmt, VA_ARGS); (void) fflush(stdout); #endif VA_END(); } /* Follow the PATH, trying to fopen the file. */ #define PATHSEP ';' #undef fopen FILE * fopenp(name, mode) register char *name, *mode; { char buf[BUFSIZ], *bp, *pp, lastch; FILE *fp; register BPTR theLock; /* Try the default directory first. Then look along PATH. */ strcpy(buf, name); if (theLock = Lock(buf, SHARED_LOCK)) { UnLock(theLock); if (fp = fopen(buf, mode)) return fp; } pp = PATH; while (pp && *pp) { bp = buf; while (*pp && *pp != PATHSEP) lastch = *bp++ = *pp++; if (lastch != ':' && lastch != '/' && bp != buf) *bp++ = '/'; strcpy(bp, name); if (theLock = Lock(buf, SHARED_LOCK)) { UnLock(theLock); if (fp = fopen(buf, mode)) return fp; } if (*pp) pp++; } return NULL; } #endif /* DGK */ #ifdef CHDIR /* * A not general-purpose directory changing routine. * Assumes you want to return to the original directory eventually, * by chdir()ing to orgdir. * Assumes -1 is not a valid lock, since 0 is valid. */ #define NO_LOCK ((BPTR) -1) char orgdir[1]; static BPTR OrgDirLock = NO_LOCK; chdir(dir) char *dir; { if (dir == orgdir) { /* We want to go back to where we came from. */ if (OrgDirLock != NO_LOCK) { UnLock(CurrentDir(OrgDirLock)); OrgDirLock = NO_LOCK; } } else { /* * Go to some new place. If still at the original * directory, save the FileLock. */ BPTR newDir; if (newDir = Lock(dir, SHARED_LOCK)) { if (OrgDirLock == NO_LOCK) { OrgDirLock = CurrentDir(newDir); } else { UnLock(CurrentDir(newDir)); } } else { return -1; /* Failed */ } } /* CurrentDir always succeeds if you have a lock */ return 0; } #endif /* Chdir back to original directory */ #undef exit void msexit(code) { #ifdef CHDIR extern char orgdir[]; #endif #ifdef DGK (void) fflush(stdout); if (ramdisk) copybones(TOPERM); #endif #ifdef CHDIR chdir(orgdir); /* chdir, not chdirx */ #endif CleanUp(); exit(code); } /* * Strcmp while ignoring case. Not general-purpose, so static. */ static int strcmpi(a, b) register char *a, *b; { while (tolower(*a) == tolower(*b)) { if (!*a) /* *a == *b, so at end of both strings */ return 0; /* equal. */ a++; b++; } return 1; } /* * memcmp - used to compare two struct symbols, in lev.c */ #if defined(AZTEC_C) && !defined(memcmp) memcmp(a, b, size) register unsigned char *a, *b; register int size; { while (size--) { if (*a++ != *b++) return 1; /* not equal */ } return 0; /* equal */ } #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.