This is msdos.c in view mode; [Download] [Up]
/* SCCS Id: @(#)msdos.c 3.0 89/12/26
/* NetHack may be freely redistributed. See license for details. */
/* An assortment of MSDOS functions.
*/
#define NEED_VARARGS
#include "hack.h"
#ifdef MSDOS
# ifdef TOS
# include <osbind.h>
# ifndef WORD
# define WORD short /* 16 bits -- redefine if necessary */
# endif
# else
# ifdef __TURBOC__ /* avoid incompatible redeclaration */
# undef getdate
# endif
# include <dos.h>
# endif
# ifdef OS2
# include "def_os2.h" /* OS2 definitions (Timo Hakulinen) */
# endif
#include <ctype.h>
#include <fcntl.h>
#include <process.h>
static char DOSgetch();
# ifdef DGK
static char BIOSgetch();
# endif
# ifdef TOS
static void init_aline();
char *_a_line; /* for Line A variables */
# else
static unsigned int ioctl();
# endif
void
flushout()
{
(void) fflush(stdout);
return;
}
int
tgetch() {
char ch;
# ifdef DGK
/* BIOSgetch can use the numeric key pad on IBM compatibles. */
if (flags.IBMBIOS)
ch = BIOSgetch();
else
# endif
ch = DOSgetch();
return ((ch == '\r') ? '\n' : ch);
}
# if !defined(OS2) && !defined(TOS)
/*
* MS-DOS functions
*/
#define DIRECT_INPUT 0x07 /* Unfiltered Character Input Without Echo */
#define FATINFO 0x1B /* Get Default Drive Data */
/* MS-DOS 2.0+: */
#define GETDTA 0x2F /* Get DTA Address */
#define FREESPACE 0x36 /* Get Drive Allocation Info */
#define GETSWITCHAR 0x3700 /* Get Switch Character */
#define FINDFIRST 0x4E /* Find First File */
#define FINDNEXT 0x4F /* Find Next File */
#define SETFILETIME 0x5701 /* Set File Date & Time */
/*
* BIOS interrupts
*/
#define KEYBRD_BIOS 0x16
#define VIDEO_BIOS 0x10
/*
* Keyboard BIOS functions
*/
#define READCHAR 0x00 /* Read Character from Keyboard */
#define GETKEYFLAGS 0x02 /* Get Keyboard Flags */
/*
* Video BIOS functions
*/
#define SETCURPOS 0x02 /* Set Cursor Position */
#define GETMODE 0x0f /* Get Video Mode */
#define FONTINFO 0x1130 /* Get Font Info */
# endif
/*
* Keyboard translation tables.
*/
# ifdef TOS
#define KEYPADLO 0x61
#define KEYPADHI 0x71
# else
#define KEYPADLO 0x47
#define KEYPADHI 0x53
# endif
#define PADKEYS (KEYPADHI - KEYPADLO + 1)
#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI)
/*
* Keypad keys are translated to the normal values below.
* When IBM_BIOS is active, shifted keypad keys are translated to the
* shift values below.
*/
static const struct pad {
char normal, shift;
} keypad[PADKEYS] = {
# ifdef TOS
{C('['), 'Q'}, /* UNDO */
{'?', '/'}, /* HELP */
{'(', 'a'}, /* ( */
{')', 'w'}, /* ) */
{'/', '/'}, /* / */
{C('p'), '$'}, /* * */
# endif
{'y', 'Y'}, /* 7 */
{'k', 'K'}, /* 8 */
{'u', 'U'}, /* 9 */
# ifndef TOS
{'m', C('p')}, /* - */
# endif
{'h', 'H'}, /* 4 */
# ifdef TOS
{'.', '.'},
# else
{'g', 'g'}, /* 5 */
# endif
{'l', 'L'}, /* 6 */
# ifndef TOS
{'p', 'P'}, /* + */
# endif
{'b', 'B'}, /* 1 */
{'j', 'J'}, /* 2 */
{'n', 'N'}, /* 3 */
{'i', 'I'}, /* Ins */
{'.', ':'} /* Del */
}, numpad[PADKEYS] = {
# ifdef TOS
{C('['), 'Q'} , /* UNDO */
{'?', '/'}, /* HELP */
{'(', 'a'}, /* ( */
{')', 'w'}, /* ) */
{'/', '/'}, /* / */
{C('p'), '$'}, /* * */
# endif
{'7', M('7')}, /* 7 */
{'8', M('8')}, /* 8 */
{'9', M('9')}, /* 9 */
# ifndef TOS
{'m', C('p')}, /* - */
# endif
{'4', M('4')}, /* 4 */
# ifdef TOS
{'.', '.'}, /* 5 */
# else
{'g', 'G'}, /* 5 */
# endif
{'6', M('6')}, /* 6 */
# ifndef TOS
{'p', 'P'}, /* + */
# endif
{'1', M('1')}, /* 1 */
{'2', M('2')}, /* 2 */
{'3', M('3')}, /* 3 */
{'i', 'I'}, /* Ins */
{'.', ':'} /* Del */
};
/*
* Unlike Ctrl-letter, the Alt-letter keystrokes have no specific ASCII
* meaning unless assigned one by a keyboard conversion table, so the
* keyboard BIOS normally does not return a character code when Alt-letter
* is pressed. So, to interpret unassigned Alt-letters, we must use a
* scan code table to translate the scan code into a letter, then set the
* "meta" bit for it. -3.
*/
#define SCANLO 0x10
#define SCANHI 0x32
#define SCANKEYS (SCANHI - SCANLO + 1)
#define inmap(x) (SCANLO <= (x) && (x) <= SCANHI)
static const char scanmap[SCANKEYS] = { /* ... */
'q','w','e','r','t','y','u','i','o','p','[',']', '\n',
0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
0, '\\', 'z','x','c','v','b','N','m' /* ... */
};
# ifdef DGK
/*
* BIOSgetch gets keys directly with a BIOS call.
*/
#define SHIFT (0x1 | 0x2)
#define CTRL 0x4
#define ALT 0x8
static char
BIOSgetch() {
unsigned char scan, shift, ch;
const struct pad *kpad;
# ifdef OS2
KBDKEYINFO CharData;
USHORT IOWait = 0;
HKBD KbdHandle = 0;
KbdCharIn(&CharData,IOWait,KbdHandle);
ch = CharData.chChar;
scan = CharData.chScan;
shift = CharData.fsState;
# else /* OS2 */
# ifdef TOS
long x;
# else
union REGS regs;
# endif
/* Get scan code.
*/
# ifdef TOS
x = Crawcin();
ch = x & 0x0ff;
scan = (x & 0x00ff0000L) >> 16;
# else
regs.h.ah = READCHAR;
int86(KEYBRD_BIOS, ®s, ®s);
ch = regs.h.al;
scan = regs.h.ah;
# endif
/* Get shift status.
*/
# ifdef TOS
shift = Kbshift(-1);
# else
regs.h.ah = GETKEYFLAGS;
int86(KEYBRD_BIOS, ®s, ®s);
shift = regs.h.al;
# endif
# endif /* OS2 */
/* Translate keypad keys */
if (iskeypad(scan)) {
kpad = flags.num_pad ? numpad : keypad;
if (shift & SHIFT)
ch = kpad[scan - KEYPADLO].shift;
else
ch = kpad[scan - KEYPADLO].normal;
}
/* Translate unassigned Alt-letters */
if ((shift & ALT) && !ch) {
if (inmap(scan))
ch = scanmap[scan - SCANLO];
return (isprint(ch) ? M(ch) : ch);
}
return ch;
}
static char
DOSgetch() {
# ifdef TOS
return (Crawcin() & 0x007f);
# else
# ifdef OS2
KBDKEYINFO CharData;
USHORT IOWait = 0;
HKBD KbdHandle = 0;
KbdCharIn(&CharData,IOWait,KbdHandle);
if (CharData.chChar == 0) { /* an extended code -- not yet supported */
KbdCharIn(&CharData,IOWait,KbdHandle); /* eat the next character */
CharData.chChar = 0; /* and return a 0 */
}
return (CharData.chChar);
# else
union REGS regs;
char ch;
struct pad (*kpad)[PADKEYS];
regs.h.ah = DIRECT_INPUT;
intdos(®s, ®s);
ch = regs.h.al;
/*
* The extended codes for Alt-shifted letters, and unshifted keypad
* and function keys, correspond to the scan codes. So we can still
* translate the unshifted cursor keys and Alt-letters. -3.
*/
if (ch == 0) { /* an extended key */
regs.h.ah = DIRECT_INPUT;
intdos(®s, ®s); /* get the extended key code */
ch = regs.h.al;
if (iskeypad(ch)) { /* unshifted keypad keys */
kpad = (void *)(flags.num_pad ? numpad : keypad);
ch = (*kpad)[ch - KEYPADLO].normal;
} else if (inmap(ch)) { /* Alt-letters */
ch = scanmap[ch - SCANLO];
if (isprint(ch)) ch = M(ch);
} else ch = 0; /* munch it */
}
return (ch);
# endif /* OS2 */
# endif /* TOS */
}
# ifndef TOS
# ifdef __TURBOC__
#define switchar() (char)getswitchar()
# else
# ifndef OS2
static char
switchar()
{
union REGS regs;
regs.x.ax = GETSWITCHAR;
intdos(®s, ®s);
return regs.h.dl;
}
# endif /* OS2 */
# endif /* __TURBOC__ */
# endif /* TOS */
static const char *COMSPEC =
# ifdef TOS
"SHELL";
# else
"COMSPEC";
# endif
#define getcomspec() getenv(COMSPEC)
# ifdef SHELL
int
dosh() {
extern char orgdir[];
char *comspec;
if (comspec = getcomspec()) {
# if defined(DGK) && !defined(TOS) /* TOS has a variety of shells */
settty("To return to NetHack, enter \"exit\" at the DOS prompt.\n");
# else
settty((char *)0);
# endif /* DGK */
chdirx(orgdir, 0);
if (spawnl(P_WAIT, comspec, comspec, NULL) < 0) {
Printf("\nCan't spawn \"%s\"!\n", comspec);
flags.toplin = 0;
more();
}
#ifdef TOS
/* Some shells (e.g. Gulam) turn the cursor off when they exit */
if (flags.IBMBIOS)
(void)Cursconf(1, -1);
#endif
gettty(); /* ctrl-P might get turned back on (TH) */
chdirx(hackdir, 0);
start_screen();
docrt();
} else
# ifdef OS2
pline("Can't execute CMD.EXE");
# else
# ifdef TOS
pline("Can't find SHELL.");
# else
pline("Can't find COMSPEC.");
# endif
# endif /* OS2 */
return 0;
}
# endif /* SHELL */
#ifndef TOS
long
freediskspace(path)
char *path;
{
# ifdef OS2
struct {
ULONG idFileSystem;
ULONG cSectorUnit;
ULONG cUnit;
ULONG cUnitAvail;
USHORT cbSector;
} FSInfoBuf;
USHORT DriveNumber, FSInfoLevel = 1, res;
if (path[0] && path[1] == ':')
DriveNumber = (toupper(path[0]) - 'A') + 1;
else
DriveNumber = 0;
res = DosQFSInfo(DriveNumber,FSInfoLevel,(PBYTE)&FSInfoBuf,sizeof(FSInfoBuf));
if (res)
return -1L; /* error */
else
return ((long) FSInfoBuf.cSectorUnit * FSInfoBuf.cUnitAvail *
FSInfoBuf.cbSector);
# else /* OS2 */
union REGS regs;
regs.h.ah = FREESPACE;
if (path[0] && path[1] == ':')
regs.h.dl = (toupper(path[0]) - 'A') + 1;
else
regs.h.dl = 0;
intdos(®s, ®s);
if (regs.x.ax == 0xFFFF)
return -1L; /* bad drive number */
else
return ((long) regs.x.bx * regs.x.cx * regs.x.ax);
# endif /* OS2 */
}
# ifdef OS2
FILEFINDBUF ResultBuf;
HDIR DirHandle;
# endif
/* Functions to get filenames using wildcards
*/
static int
findfirst(path)
char *path;
{
# ifdef OS2
USHORT res, SearchCount = 1;
DirHandle = 1;
res = DosFindFirst((PSZ)path,&DirHandle,0,&ResultBuf,sizeof(FILEFINDBUF),&SearchCount,0L);
return(!res);
# else
union REGS regs;
struct SREGS sregs;
regs.h.ah = FINDFIRST;
regs.x.cx = 0; /* attribute: normal files */
regs.x.dx = FP_OFF(path);
sregs.ds = FP_SEG(path);
intdosx(®s, ®s, &sregs);
return !regs.x.cflag;
# endif /* OS2 */
}
static int
findnext() {
# ifdef OS2
USHORT res, SearchCount = 1;
res = DosFindNext(DirHandle,&ResultBuf,sizeof(FILEFINDBUF),&SearchCount);
return(!res);
# else
union REGS regs;
regs.h.ah = FINDNEXT;
intdos(®s, ®s);
return !regs.x.cflag;
# endif /* OS2 */
}
# ifndef OS2
/* Get disk transfer area, Turbo C already has getdta */
static char *
getdta() {
union REGS regs;
struct SREGS sregs;
char *ret;
regs.h.ah = GETDTA;
intdosx(®s, ®s, &sregs);
# ifdef MK_FP
ret = MK_FP(sregs.es, regs.x.bx);
# else
FP_OFF(ret) = regs.x.bx;
FP_SEG(ret) = sregs.es;
# endif
return ret;
}
# endif /* OS2 */
# else /* TOS */
long
freediskspace(path)
char *path;
{
int drive = 0;
struct {
long freal; /*free allocation units*/
long total; /*total number of allocation units*/
long bps; /*bytes per sector*/
long pspal; /*physical sectors per allocation unit*/
} freespace;
if (path[0] && path[1] == ':')
drive = (toupper(path[0]) - 'A') + 1;
if (Dfree(&freespace,drive)<0) return -1;
return freespace.freal*freespace.bps*freespace.pspal;
}
static int
findfirst(path)
char *path;
{
return (Fsfirst(path, 0) == 0);
}
static int findnext() {
return (Fsnext() == 0);
}
static char *
getdta() {
return (char *) Fgetdta();
}
# endif /* TOS */
long
filesize(file)
char *file;
{
# ifndef OS2
char *dta;
# endif
if (findfirst(file)) {
# ifdef OS2
return (* (long *) (ResultBuf.cbFileAlloc));
# else
dta = getdta();
return (* (long *) (dta + 26));
# endif
} else
return -1L;
}
void
eraseall(path, files)
const char *path, *files;
{
# ifndef OS2
char *dta;
# endif
char buf[PATHLEN];
# ifndef OS2
dta = getdta();
# endif
Sprintf(buf, "%s%s", path, files);
if (findfirst(buf))
do {
Sprintf(buf, "%s%s", path,
# ifdef OS2
ResultBuf.achName
# else
dta + 30
# endif
);
(void) unlink(buf);
} while (findnext());
return;
}
/* Rewritten for version 3.3 to be faster
*/
void
copybones(mode)
int mode;
{
char from[PATHLEN], to[PATHLEN], last[13];
char *frompath, *topath;
# ifndef OS2
char *dta;
# endif
# ifndef TOS
int status;
char copy[8], *comspec;
extern saveprompt;
# endif
if (!ramdisk)
return;
/* Find the name of the last file to be transferred
*/
frompath = (mode != TOPERM) ? permbones : levels;
# ifndef OS2
dta = getdta();
# endif
last[0] = '\0';
Sprintf(from, "%s%s", frompath, allbones);
topath = (mode == TOPERM) ? permbones : levels;
# ifdef TOS
eraseall(topath, allbones);
# endif
if (findfirst(from))
do {
# ifdef TOS
Sprintf(from, "%s%s", frompath, dta+30);
Sprintf(to, "%s%s", topath, dta+30);
if (_copyfile(from, to))
goto error_copying;
# endif
Strcpy(last,
# ifdef OS2
ResultBuf.achName
# else
dta + 30
# endif
);
} while (findnext());
# ifdef TOS
else
return;
# else
if (last[0]) {
Sprintf(copy, "%cC copy",
# ifdef OS2
'/'
# else
switchar()
# endif
);
/* Remove any bones files in `to' directory.
*/
eraseall(topath, allbones);
/* Copy `from' to `to' */
Sprintf(to, "%s%s", topath, allbones);
comspec = getcomspec();
status =spawnl(P_WAIT, comspec, comspec, copy, from,
to, "> nul", NULL);
} else
return;
# endif /* TOS */
/* See if the last file got there. If so, remove the ramdisk bones
* files.
*/
Sprintf(to, "%s%s", topath, last);
if (findfirst(to)) {
if (mode == TOPERM)
eraseall(frompath, allbones);
return;
}
error_copying:
/* Last file didn't get there.
*/
Sprintf(to, "%s%s", topath, allbones);
msmsg("Can't copy \"%s\" to \"%s\" -- ", from, to);
# ifndef TOS
if (status < 0)
msmsg("can't spawn \"%s\"!", comspec);
else
# endif
msmsg((freediskspace(topath) < filesize(from)) ?
"insufficient disk space." : "bad path(s)?");
if (mode == TOPERM) {
msmsg("Bones will be left in \"%s\"\n",
*levels ? levels : hackdir);
} else {
/* Remove all bones files on the RAMdisk */
eraseall(levels, allbones);
playwoRAMdisk();
}
return;
}
#if 0 /* defined(MSDOS) && !defined(TOS) && !defined(OS2) */
boolean
removeable_drive(drive)
char drive;
/* check whether current drive is a fixed disk,
so we don't ask the player to insert one */
{
union REGS regs;
char *fat_id;
regs.h.ah = FATINFO;
intdos(®s, ®s);
/* also returns size info, as
AL (sectors/cluster) * CX (bytes/sector) * DX (clusters/disk) */
# ifdef MK_FP
fat_id = MK_FP(sregs.ds, regs.x.bx);
# else
FP_OFF(fat_id) = regs.x.bx;
FP_SEG(fat_id) = sregs.ds;
# endif
return (*fat_id != 0xF8);
}
#endif /* 0 */
void
playwoRAMdisk() {
msmsg("Do you wish to play without a RAMdisk? ");
/* Set ramdisk false *before* exit-ing (because msexit calls
* copybones)
*/
ramdisk = FALSE;
if (yn() != 'y') {
settty("Be seeing you...\n");
exit(0);
}
set_lock_and_bones();
return;
}
int
saveDiskPrompt(start)
int start;
{
extern saveprompt;
char buf[BUFSIZ], *bp;
int fd;
if (saveprompt) {
/* Don't prompt if you can find the save file */
if ((fd = open(SAVEF, 0)) >= 0) {
(void) close(fd);
return 1;
}
remember_topl();
home();
cl_end();
msmsg("If save file is on a save disk, insert that disk 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() {
int fd;
# ifdef OS2_CODEVIEW
char tmp[PATHLEN];
Strcpy(tmp,hackdir);
append_slash(tmp);
Strcat(tmp,RECORD);
if ((fd = open(tmp, 0)) >= 0) {
# else
if ((fd = open(RECORD, 0)) >= 0) {
# endif
(void) close(fd);
return TRUE;
}
return FALSE;
}
# ifdef TOS
#define comspec_exists() 1
# else
/* Return 1 if the comspec was found */
static boolean
comspec_exists() {
int fd;
char *comspec;
if (comspec = getcomspec())
if ((fd = open(comspec, 0)) >= 0) {
(void) close(fd);
return TRUE;
}
return FALSE;
}
# endif
/* Prompt for game disk, then check for record file.
*/
void
gameDiskPrompt() {
extern int saveprompt;
if (saveprompt) {
if (record_exists() && comspec_exists())
return;
(void) putchar('\n');
getreturn("when the game disk has been inserted");
}
if (comspec_exists() && record_exists())
return;
if (!comspec_exists())
msmsg("\n\nWARNING: can't find command processor \"%s\"!\n", getcomspec());
if (!record_exists())
msmsg("\n\nWARNING: can't find record file \"%s\"!\n", RECORD);
msmsg("If the game disk is not in, insert it now.\n");
getreturn("to continue");
return;
}
# endif /* DGK */
/* Read configuration */
void
read_config_file() {
# ifdef DGK
char tmp_ramdisk[PATHLEN];
extern int saveprompt;
# else
#define fopenp fopen
# endif
char tmp_levels[PATHLEN];
char buf[BUFSZ], *bufp;
FILE *fp;
extern char plname[];
# ifdef DGK
tmp_ramdisk[0] = 0;
# endif
tmp_levels[0] = 0;
if ((fp = fopenp(configfile, "r")) == (FILE *)0) {
msmsg("Warning: no configuration file!\n");
getreturn("to continue");
return;
}
while (fgets(buf, BUFSZ, fp)) {
if (*buf == '#')
continue;
/* remove trailing whitespace
*/
bufp = index(buf, '\n');
while (bufp > buf && isspace(*bufp))
bufp--;
if (bufp == buf)
continue; /* skip all-blank lines */
else
*(bufp + 1) = 0; /* 0 terminate line */
/* find the '=' */
if (!(bufp = strchr(buf, '='))) {
msmsg("Bad option line: \"%s\"\n", buf);
getreturn("to continue");
continue;
}
/* skip whitespace between '=' and value */
while (isspace(*++bufp))
;
/* Go through possible variables */
if (!strncmp(buf, "HACKDIR", 4)) {
strncpy(hackdir, bufp, PATHLEN);
# ifdef DGK
} else if (!strncmp(buf, "RAMDISK", 3)) {
strncpy(tmp_ramdisk, bufp, PATHLEN);
# endif
} else if (!strncmp(buf, "LEVELS", 4)) {
strncpy(tmp_levels, bufp, PATHLEN);
} else if (!strncmp(buf, "OPTIONS", 4)) {
parseoptions(bufp, TRUE);
if (plname[0]) /* If a name was given */
plnamesuffix(); /* set the character class */
} else if (!strncmp(buf, "SAVE", 4)) {
# ifdef DGK
char *ptr;
if (ptr = index(bufp, ';')) {
*ptr = '\0';
if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
saveprompt = FALSE;
}
# endif /* DGK */
(void) strncpy(SAVEF, bufp, PATHLEN);
(void) strncpy(SAVEP, bufp, PATHLEN);
append_slash(SAVEF);
append_slash(SAVEP);
} else if (!strncmp(buf, "GRAPHICS", 4)) {
unsigned int translate[MAXPCHARS+1];
int lth;
#ifdef OVERLAY
/* THIS is what I call a stupid hack, but MSC cannot survive
the overlays without it (TH) */
lth = sscanf(bufp,
"%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]);
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",
&translate[12], &translate[13], &translate[14],
&translate[15], &translate[16], &translate[17],
&translate[18], &translate[19], &translate[20],
&translate[21], &translate[22], &translate[23]);
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[24], &translate[25], &translate[26],
&translate[27], &translate[28], &translate[29],
&translate[30], &translate[31], &translate[32],
&translate[33], &translate[34]);
#else
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]);
#endif /* OVERLAY */
if (lth <= 0) {
msmsg ("Syntax error in GRAPHICS\n");
getreturn("to continue");
}
assign_graphics(translate, lth);
} else {
msmsg("Bad option line: \"%s\"\n", buf);
getreturn("to continue");
}
}
(void) fclose(fp);
# ifdef DGK
Strcpy(permbones, tmp_levels);
if (tmp_ramdisk[0]) {
Strcpy(levels, tmp_ramdisk);
if (strcmp(permbones, levels)) /* if not identical */
ramdisk = TRUE;
} else
# endif /* DGK */
Strcpy(levels, tmp_levels);
Strcpy(bones, levels);
return;
}
# ifdef DGK
/* 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);
return;
}
# endif /* DGK */
/* Add a backslash to any name not ending in /, \ or : There must
* be room for the \
*/
void
append_slash(name)
char *name;
{
char *ptr;
if (!*name)
return;
ptr = name + (strlen(name) - 1);
if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
*++ptr = '\\';
*++ptr = '\0';
}
return;
}
void
getreturn(str)
const char *str;
{
# ifdef TOS
msmsg("Hit <Return> %s.", str);
# else
msmsg("Hit <Enter> %s.", str);
# endif
while (Getchar() != '\n') ;
return;
}
void
msmsg VA_DECL(const char *, fmt)
VA_START(fmt);
VA_INIT(fmt, const char *);
Vprintf(fmt, VA_ARGS);
flushout();
VA_END();
return;
}
/* Chdrive() changes the default drive.
*/
# ifndef __TURBOC__
# ifndef OS2
#define SELECTDISK 0x0E
# endif
void
chdrive(str)
char *str;
{
char *ptr;
# ifndef TOS
# ifndef OS2
union REGS inregs;
# endif
# endif
char drive;
if ((ptr = index(str, ':')) != NULL) {
drive = toupper(*(ptr - 1));
# ifdef TOS
(void)Dsetdrv(drive - 'A');
# else
# ifdef OS2
DosSelectDisk((USHORT)(drive - 'A' + 1));
# else
inregs.h.ah = SELECTDISK;
inregs.h.dl = drive - 'A';
intdos(&inregs, &inregs);
# endif
# endif
}
return;
}
# else
extern int setdisk(int);
void
chdrive(str)
char *str;
{
if (str[1] == ':')
(void)setdisk((int)(toupper(str[0]) - 'A'));
return;
}
# endif
# ifndef TOS
/* Use the IOCTL DOS function call to change stdin and stdout to raw
* mode. For stdin, this prevents MSDOS from trapping ^P, thus
* freeing us of ^P toggling 'echo to printer'.
* Thanks to Mark Zbikowski (markz@microsoft.UUCP).
*/
# ifndef OS2
#define DEVICE 0x80
#define RAW 0x20
#define IOCTL 0x44
#define STDIN fileno(stdin)
#define STDOUT fileno(stdout)
#define GETBITS 0
#define SETBITS 1
# endif
static unsigned int old_stdin, old_stdout;
void
disable_ctrlP() {
# ifdef OS2
KBDINFO KbdInfo;
HKBD KbdHandle = 0;
# endif
# ifdef DGK
if (!flags.rawio) return;
# endif
# ifdef OS2
KbdInfo.cb = sizeof(KbdInfo);
KbdGetStatus(&KbdInfo,KbdHandle);
KbdInfo.fsMask &= 0xFFF7; /* ASCII off */
KbdInfo.fsMask |= 0x0004; /* BINARY on */
KbdSetStatus(&KbdInfo,KbdHandle);
# else
old_stdin = ioctl(STDIN, GETBITS, 0);
old_stdout = ioctl(STDOUT, GETBITS, 0);
if (old_stdin & DEVICE)
ioctl(STDIN, SETBITS, old_stdin | RAW);
if (old_stdout & DEVICE)
ioctl(STDOUT, SETBITS, old_stdout | RAW);
# endif /* OS2 */
return;
}
void
enable_ctrlP() {
# ifdef OS2
KBDINFO KbdInfo;
HKBD KbdHandle = 0;
# endif
# ifdef DGK
if (!flags.rawio) return;
# endif
# ifdef OS2
KbdInfo.cb = sizeof(KbdInfo);
KbdGetStatus(&KbdInfo,KbdHandle);
KbdInfo.fsMask &= 0xFFFB; /* BINARY off */
KbdInfo.fsMask |= 0x0008; /* ASCII on */
KbdSetStatus(&KbdInfo,KbdHandle);
# else
if (old_stdin)
(void) ioctl(STDIN, SETBITS, old_stdin);
if (old_stdout)
(void) ioctl(STDOUT, SETBITS, old_stdout);
# endif
return;
}
# ifndef OS2
static unsigned int
ioctl(handle, mode, setvalue)
int handle, mode;
unsigned setvalue;
{
union REGS regs;
regs.h.ah = IOCTL;
regs.h.al = mode;
regs.x.bx = handle;
regs.h.dl = setvalue;
regs.h.dh = 0; /* Zero out dh */
intdos(®s, ®s);
return (regs.x.dx);
}
# endif /* OS2 */
# endif /* TOS */
# ifdef DGK
/* Follow the PATH, trying to fopen the file.
*/
# ifdef TOS
#define PATHSEP ','
# else
#define PATHSEP ';'
# endif
FILE *
fopenp(name, mode)
const char *name, *mode;
{
char buf[BUFSIZ], *bp, *pp, lastch = 0;
FILE *fp;
/* Try the default directory first. Then look along PATH.
*/
Strcpy(buf, name);
if (fp = fopen(buf, mode))
return fp;
else {
pp = getenv("PATH");
while (pp && *pp) {
bp = buf;
while (*pp && *pp != PATHSEP)
lastch = *bp++ = *pp++;
if (lastch != '\\' && lastch != '/')
*bp++ = '\\';
Strcpy(bp, name);
if (fp = fopen(buf, mode))
return fp;
if (*pp)
pp++;
}
}
# ifdef OS2_CODEVIEW /* one more try for hackdir */
Strcpy(buf,hackdir);
append_slash(buf);
Strcat(buf,name);
if(fp = fopen(buf,mode))
return fp;
# endif
return (FILE *)0;
}
# endif /* DGK */
/* Chdir back to original directory
*/
#undef exit
# ifdef TOS
extern boolean run_from_desktop; /* set in pcmain.c */
# endif
void exit(int);
void
msexit(code)
int code;
{
# ifdef CHDIR
extern char orgdir[];
# endif
flushout();
# ifndef TOS
enable_ctrlP(); /* in case this wasn't done */
# endif
# ifdef DGK
if (ramdisk) copybones(TOPERM);
# endif
# ifdef CHDIR
chdir(orgdir); /* chdir, not chdirx */
chdrive(orgdir);
# endif
# ifdef TOS
if (run_from_desktop)
getreturn("to continue"); /* so the user can read the score list */
# ifdef TEXTCOLOR
if (flags.IBMBIOS && flags.use_color)
restore_colors();
# endif
# endif
exit(code);
return;
}
# ifdef DGK /* for flags.IBMBIOS */
void
get_scr_size()
{
# ifdef OS2
VIOMODEINFO ModeInfo;
HVIO VideoHandle = 0;
ModeInfo.cb = sizeof(ModeInfo);
(void) VioGetMode(&ModeInfo,VideoHandle);
CO = ModeInfo.col;
LI = ModeInfo.row;
# else
# ifndef TOS
union REGS regs;
if (!flags.IBMBIOS) { /* assume standard screen size */
CO = 80;
LI = 24;
return;
}
regs.x.ax = FONTINFO;
regs.x.bx = 0; /* current ROM BIOS font */
regs.h.dl = 24; /* default row count */
/* in case no EGA/MCGA/VGA */
int86(VIDEO_BIOS, ®s, ®s); /* Get Font Information */
/* MDA/CGA/PCjr ignore INT 10h, Function 11h, but since we
* cleverly loaded up DL with the default, everything's fine.
*
* Otherwise, DL now contains rows - 1. Also, CX contains the
* points (bytes per character) and ES:BP points to the font
* table. -3.
*/
regs.h.ah = GETMODE;
int86(VIDEO_BIOS, ®s, ®s); /* Get Video Mode */
/* This goes back all the way to the original PC. Completely
* safe. AH contains # of columns, AL contains display mode,
* and BH contains the active display page.
*/
LI = regs.h.dl + 1;
CO = regs.h.ah;
# else /* TOS */
init_aline();
LI = (*((WORD *)(_a_line + -42L))) + 1;
CO = (*((WORD *)(_a_line + -44L))) + 1;
# endif /* TOS */
# endif /* OS2 */
}
# ifndef TOS
void
gotoxy(x,y)
int x,y;
{
# ifdef OS2
HVIO VideoHandle = 0;
x--; y--; /* (0,0) is upper right corner */
(void) VioSetCurPos(x, y, VideoHandle);
# else
union REGS regs;
x--; y--; /* (0,0) is upper right corner */
regs.h.ah = SETCURPOS;
regs.h.bh = 0; /* display page */
regs.h.dh = y; /* row */
regs.h.dl = x; /* column */
int86(VIDEO_BIOS, ®s, ®s); /* Set Cursor Position */
/* This, too, goes back all the way to the original PC. If
* we ever get so fancy as to swap display pages (i doubt it),
* then we'll need to set BH appropriately. This function
* returns nothing. -3.
*/
# endif /* OS2 */
}
# endif /* TOS */
# endif /* DGK */
#endif /* MSDOS */
#ifdef TOS
# define BIGBUF 8192
int
_copyfile(from, to)
char *from, *to;
{
int fromfd, tofd, r;
char *buf;
if ((fromfd = open(from, O_RDONLY|O_BINARY, 0)) < 0)
return -1;
if ((tofd = open(to, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, FCMASK)) < 0)
return -1;
if (!(buf = (char *)malloc((size_t)BIGBUF)))
return -1;
while ( (r = read(fromfd, buf, BIGBUF)) > 0)
write(tofd, buf, r);
close(fromfd);
close(tofd);
free(buf);
return 0; /* successful */
}
int kbhit()
{
return Cconis();
}
static void
init_aline()
{
# ifdef __GNUC__
asm(" .word 0xa000; movel d0, __a_line");
# else
asm(" .dc.w 0xa000"); /* tweak as necessary for your compiler */
asm(" move.l d0, __a_line");
# endif
}
# ifdef TEXTCOLOR
static unsigned orig_color[4] = {-1, -1, -1, -1};
static unsigned new_color[4] = { 0x0, 0x730, 0x047, 0x555 };
static int numcolors = 2;
void set_colors()
{
int i;
char *s;
static char newhe[] = "\033q\033b\017\033c0";
init_aline();
numcolors = 1 << (((unsigned char *) _a_line)[1]);
if (numcolors == 2) { /* mono */
flags.use_color = FALSE;
return;
}
else if (numcolors == 4) {
for (i = 0; i < 4; i++)
orig_color[i] = Setcolor(i, new_color[i]);
}
else {
orig_color[0] = Setcolor(0, new_color[0]);
orig_color[1] = Setcolor(15, 0x777);
hilites[0] = "";
for (i = 1; i < 16; i++) {
s = (char *) alloc(sizeof("\033b0"));
sprintf(s, "\033b%c", '0'+i);
hilites[i] = s;
}
HE = newhe;
}
}
void restore_colors()
{
int i;
if (numcolors == 2)
return;
else if (numcolors == 4)
for (i = 0; i < 4; i++)
(void) Setcolor(i, orig_color[i]);
else {
(void) Setcolor(0, orig_color[0]);
(void) Setcolor(15, orig_color[1]);
}
}
# endif /* TEXTCOLOR */
#endif /* TOS */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.