home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / msdos / msdos.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-18  |  9.7 KB  |  463 lines

  1. /*    SCCS Id: @(#)msdos.c     3.1     93/01/05          */
  2. /* Copyright (c) NetHack PC Development Team 1990, 1991, 1992      */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  *  MSDOS system functions.
  7.  *  Many thanks to Don Kneller who originated the DOS port and
  8.  *  contributed much to the cause.
  9.  */
  10.  
  11. #define NEED_VARARGS
  12. #include "hack.h"
  13. #ifdef MICRO
  14. #include "termcap.h"
  15. #endif
  16.  
  17. #ifdef MSDOS
  18.  
  19. #include <dos.h>
  20. #include <ctype.h>
  21.  
  22. /*
  23.  * MS-DOS functions
  24.  */
  25. #define DIRECT_INPUT    0x07    /* Unfiltered Character Input Without Echo */
  26. #define FATINFO     0x1B    /* Get Default Drive Data */
  27. /* MS-DOS 2.0+: */
  28. #define GETDTA      0x2F    /* Get DTA Address */
  29. #define FREESPACE   0x36    /* Get Drive Allocation Info */
  30. #define GETSWITCHAR 0x3700  /* Get Switch Character */
  31. #define FINDFIRST   0x4E    /* Find First File */
  32. #define FINDNEXT    0x4F    /* Find Next File */
  33. #define SETFILETIME 0x5701  /* Set File Date & Time */
  34. /*
  35.  * BIOS interrupts
  36.  */
  37. #define KEYBRD_BIOS 0x16
  38. #define VIDEO_BIOS  0x10
  39. /*
  40.  * Keyboard BIOS functions
  41.  */
  42. #define READCHAR    0x00    /* Read Character from Keyboard */
  43. #define GETKEYFLAGS 0x02    /* Get Keyboard Flags */
  44. /*
  45.  * Video BIOS functions
  46.  */
  47. #define SETCURPOS   0x02    /* Set Cursor Position */
  48. #define GETMODE     0x0f    /* Get Video Mode */
  49. #define FONTINFO    0x1130  /* Get Font Info */
  50.  
  51.  
  52. #ifdef OVL0
  53.  
  54. /* direct bios calls are used only when flags.BIOS is set */
  55.  
  56. static char NDECL(DOSgetch);
  57. static char NDECL(BIOSgetch);
  58. static char * NDECL(getdta);
  59. static unsigned int FDECL(dos_ioctl, (int,int,unsigned));
  60.  
  61. int
  62. tgetch()
  63. {
  64.     char ch;
  65.  
  66.     /* BIOSgetch can use the numeric key pad on IBM compatibles. */
  67.     if (flags.BIOS)
  68.         ch = BIOSgetch();
  69.     else
  70.         ch = DOSgetch();
  71.     return ((ch == '\r') ? '\n' : ch);
  72. }
  73.  
  74.  
  75.  
  76. /*
  77.  *  Keyboard translation tables.
  78.  */
  79. #define KEYPADLO    0x47
  80. #define KEYPADHI    0x53
  81.  
  82. #define PADKEYS     (KEYPADHI - KEYPADLO + 1)
  83. #define iskeypad(x)    (KEYPADLO <= (x) && (x) <= KEYPADHI)
  84.  
  85. /*
  86.  * Keypad keys are translated to the normal values below.
  87.  * When flags.BIOS is active, shifted keypad keys are translated to the
  88.  *    shift values below.
  89.  */
  90. static const struct pad {
  91.     char normal, shift, cntrl;
  92. } keypad[PADKEYS] = {
  93.             {'y', 'Y', C('y')},        /* 7 */
  94.             {'k', 'K', C('k')},        /* 8 */
  95.             {'u', 'U', C('u')},        /* 9 */
  96.             {'m', C('p'), C('p')},        /* - */
  97.             {'h', 'H', C('h')},        /* 4 */
  98.             {'g', 'g', 'g'},        /* 5 */
  99.             {'l', 'L', C('l')},        /* 6 */
  100.             {'p', 'P', C('p')},        /* + */
  101.             {'b', 'B', C('b')},        /* 1 */
  102.             {'j', 'J', C('j')},        /* 2 */
  103.             {'n', 'N', C('n')},        /* 3 */
  104.             {'i', 'I', C('i')},        /* Ins */
  105.             {'.', ':', ':'}            /* Del */
  106. }, numpad[PADKEYS] = {
  107.             {'7', M('7'), '7'},        /* 7 */
  108.             {'8', M('8'), '8'},        /* 8 */
  109.             {'9', M('9'), '9'},        /* 9 */
  110.             {'m', C('p'), C('p')},        /* - */
  111.             {'4', M('4'), '4'},        /* 4 */
  112.             {'g', 'G', 'g'},        /* 5 */
  113.             {'6', M('6'), '6'},        /* 6 */
  114.             {'p', 'P', C('p')},        /* + */
  115.             {'1', M('1'), '1'},        /* 1 */
  116.             {'2', M('2'), '2'},        /* 2 */
  117.             {'3', M('3'), '3'},        /* 3 */
  118.             {'i', 'I', C('i')},        /* Ins */
  119.             {'.', ':', ':'}            /* Del */
  120. };
  121.  
  122. /*
  123.  * Unlike Ctrl-letter, the Alt-letter keystrokes have no specific ASCII
  124.  * meaning unless assigned one by a keyboard conversion table, so the
  125.  * keyboard BIOS normally does not return a character code when Alt-letter
  126.  * is pressed.    So, to interpret unassigned Alt-letters, we must use a
  127.  * scan code table to translate the scan code into a letter, then set the
  128.  * "meta" bit for it.  -3.
  129.  */
  130. #define SCANLO        0x10
  131. #define SCANHI        0x32
  132. #define SCANKEYS    (SCANHI - SCANLO + 1)
  133. #define inmap(x)    (SCANLO <= (x) && (x) <= SCANHI)
  134.  
  135. static const char scanmap[SCANKEYS] = {     /* ... */
  136.     'q','w','e','r','t','y','u','i','o','p','[',']', '\n',
  137.     0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
  138.     0, '\\', 'z','x','c','v','b','N','m'     /* ... */
  139. };
  140.  
  141. /*
  142.  * BIOSgetch gets keys directly with a BIOS call.
  143.  */
  144. #define SHIFT        (0x1 | 0x2)
  145. #define CTRL        0x4
  146. #define ALT        0x8
  147.  
  148. static char
  149. BIOSgetch()
  150. {
  151.     unsigned char scan, shift, ch;
  152.     const struct pad *kpad;
  153.  
  154.     union REGS regs;
  155.  
  156.     /* Get scan code.
  157.      */
  158.     regs.h.ah = READCHAR;
  159.     int86(KEYBRD_BIOS, ®s, ®s);
  160.     ch = regs.h.al;
  161.     scan = regs.h.ah;
  162.     /* Get shift status.
  163.      */
  164.     regs.h.ah = GETKEYFLAGS;
  165.     int86(KEYBRD_BIOS, ®s, ®s);
  166.     shift = regs.h.al;
  167.  
  168.     /* Translate keypad keys */
  169.     if (iskeypad(scan)) {
  170.         kpad = flags.num_pad ? numpad : keypad;
  171.         if (shift & SHIFT)
  172.             ch = kpad[scan - KEYPADLO].shift;
  173.         else if (shift & CTRL)
  174.             ch = kpad[scan - KEYPADLO].cntrl;
  175.         else
  176.             ch = kpad[scan - KEYPADLO].normal;
  177.     }
  178.     /* Translate unassigned Alt-letters */
  179.     if ((shift & ALT) && !ch) {
  180.         if (inmap(scan))
  181.             ch = scanmap[scan - SCANLO];
  182.         return (isprint(ch) ? M(ch) : ch);
  183.     }
  184.     return ch;
  185. }
  186.  
  187. static char
  188. DOSgetch()
  189. {
  190.     union REGS regs;
  191.     char ch;
  192.     struct pad (*kpad)[PADKEYS];
  193.  
  194.     regs.h.ah = DIRECT_INPUT;
  195.     intdos(®s, ®s);
  196.     ch = regs.h.al;
  197.  
  198.     /*
  199.      * The extended codes for Alt-shifted letters, and unshifted keypad
  200.      * and function keys, correspond to the scan codes.  So we can still
  201.      * translate the unshifted cursor keys and Alt-letters.  -3.
  202.      */
  203.     if (ch == 0) {        /* an extended key */
  204.         regs.h.ah = DIRECT_INPUT;
  205.         intdos(®s, ®s);    /* get the extended key code */
  206.         ch = regs.h.al;
  207.  
  208.         if (iskeypad(ch)) {    /* unshifted keypad keys */
  209.             kpad = (void *)(flags.num_pad ? numpad : keypad);
  210.             ch = (*kpad)[ch - KEYPADLO].normal;
  211.         } else if (inmap(ch)) { /* Alt-letters */
  212.             ch = scanmap[ch - SCANLO];
  213.             if (isprint(ch)) ch = M(ch);
  214.         } else ch = 0;        /* munch it */
  215.     }
  216.     return (ch);
  217. }
  218.  
  219. char
  220. switchar()
  221. {
  222.     union REGS regs;
  223.  
  224.     regs.x.ax = GETSWITCHAR;
  225.     intdos(®s, ®s);
  226.     return regs.h.dl;
  227. }
  228.  
  229. long
  230. freediskspace(path)
  231. char *path;
  232. {
  233.     union REGS regs;
  234.  
  235.     regs.h.ah = FREESPACE;
  236.     if (path[0] && path[1] == ':')
  237.         regs.h.dl = (toupper(path[0]) - 'A') + 1;
  238.     else
  239.         regs.h.dl = 0;
  240.     intdos(®s, ®s);
  241.     if (regs.x.ax == 0xFFFF)
  242.         return -1L;        /* bad drive number */
  243.     else
  244.         return ((long) regs.x.bx * regs.x.cx * regs.x.ax);
  245. }
  246.  
  247. #ifndef __GO32__
  248. /*
  249.  * Functions to get filenames using wildcards
  250.  */
  251. int
  252. findfirst(path)
  253. char *path;
  254. {
  255.     union REGS regs;
  256.     struct SREGS sregs;
  257.  
  258.     regs.h.ah = FINDFIRST;
  259.     regs.x.cx = 0;        /* attribute: normal files */
  260.     regs.x.dx = FP_OFF(path);
  261.     sregs.ds = FP_SEG(path);
  262.     intdosx(®s, ®s, &sregs);
  263.     return !regs.x.cflag;
  264. }
  265.  
  266. int
  267. findnext() {
  268.     union REGS regs;
  269.  
  270.     regs.h.ah = FINDNEXT;
  271.     intdos(®s, ®s);
  272.     return !regs.x.cflag;
  273. }
  274.  
  275. char *
  276. foundfile_buffer()
  277. {
  278.     return (getdta() + 30);
  279. }
  280.  
  281.  
  282. /* Get disk transfer area */
  283. static char *
  284. getdta()
  285. {
  286.     union REGS regs;
  287.     struct SREGS sregs;
  288.     char *ret;
  289.  
  290.     regs.h.ah = GETDTA;
  291.     intdosx(®s, ®s, &sregs);
  292. #   ifdef MK_FP
  293.     ret = MK_FP(sregs.es, regs.x.bx);
  294. #   else
  295.     FP_OFF(ret) = regs.x.bx;
  296.     FP_SEG(ret) = sregs.es;
  297. #   endif
  298.     return ret;
  299. }
  300.  
  301. long
  302. filesize(file)
  303. char *file;
  304. {
  305.     char *dta;
  306.  
  307.     if (findfirst(file)) {
  308.         dta = getdta();
  309.         return  (* (long *) (dta + 26));
  310.     } else
  311.         return -1L;
  312. }
  313.  
  314. #endif /* __GO32__ */
  315.  
  316. /*
  317.  * Chdrive() changes the default drive.
  318.  */
  319. void
  320. chdrive(str)
  321. char *str;
  322. {
  323. #  define SELECTDISK    0x0E
  324.     char *ptr;
  325.     union REGS inregs;
  326.     char drive;
  327.  
  328.     if ((ptr = index(str, ':')) != NULL) {
  329.         drive = toupper(*(ptr - 1));
  330.         inregs.h.ah = SELECTDISK;
  331.         inregs.h.dl = drive - 'A';
  332.         intdos(&inregs, &inregs);
  333.     }
  334.     return;
  335. }
  336.  
  337.  
  338. /* Use the IOCTL DOS function call to change stdin and stdout to raw
  339.  * mode.  For stdin, this prevents MSDOS from trapping ^P, thus
  340.  * freeing us of ^P toggling 'echo to printer'.
  341.  * Thanks to Mark Zbikowski (markz@microsoft.UUCP).
  342.  */
  343.  
  344. #define DEVICE        0x80
  345. #define RAW        0x20
  346. #define IOCTL        0x44
  347. #define STDIN        fileno(stdin)
  348. #define STDOUT        fileno(stdout)
  349. #define GETBITS        0
  350. #define SETBITS        1
  351.  
  352. static unsigned    int old_stdin, old_stdout;
  353.  
  354. void
  355. disable_ctrlP()
  356. {
  357.  
  358.     if (!flags.rawio) return;
  359.  
  360.     old_stdin = dos_ioctl(STDIN, GETBITS, 0);
  361.     old_stdout = dos_ioctl(STDOUT, GETBITS, 0);
  362.     if (old_stdin & DEVICE)
  363.         dos_ioctl(STDIN, SETBITS, old_stdin | RAW);
  364.     if (old_stdout & DEVICE)
  365.         dos_ioctl(STDOUT, SETBITS, old_stdout | RAW);
  366.     return;
  367. }
  368.  
  369. void
  370. enable_ctrlP()
  371. {
  372.     if (!flags.rawio) return;
  373.     if (old_stdin)
  374.         (void) dos_ioctl(STDIN, SETBITS, old_stdin);
  375.     if (old_stdout)
  376.         (void) dos_ioctl(STDOUT, SETBITS, old_stdout);
  377.     return;
  378. }
  379.  
  380. static unsigned int
  381. dos_ioctl(handle, mode, setvalue)
  382. int handle, mode;
  383. unsigned setvalue;
  384. {
  385.     union REGS regs;
  386.  
  387.     regs.h.ah = IOCTL;
  388.     regs.h.al = mode;
  389.     regs.x.bx = handle;
  390.     regs.h.dl = setvalue;
  391.     regs.h.dh = 0;            /* Zero out dh */
  392.     intdos(®s, ®s);
  393.     return (regs.x.dx);
  394. }
  395.  
  396. #endif /* OVL0 */
  397. #ifdef OVLB
  398.  
  399. void
  400. get_scr_size()
  401. {
  402.     union REGS regs;
  403.  
  404.     if (!flags.BIOS) {        /* assume standard screen size */
  405.         CO = 80;
  406.         LI = 24;
  407.         return;
  408.     }
  409.  
  410.     regs.x.ax = FONTINFO;
  411.     regs.x.bx = 0;            /* current ROM BIOS font */
  412.     regs.h.dl = 24;            /* default row count */
  413.                     /* in case no EGA/MCGA/VGA */
  414.     int86(VIDEO_BIOS, ®s, ®s); /* Get Font Information */
  415.  
  416.     /* MDA/CGA/PCjr ignore INT 10h, Function 11h, but since we
  417.      * cleverly loaded up DL with the default, everything's fine.
  418.      *
  419.      * Otherwise, DL now contains rows - 1.  Also, CX contains the
  420.      * points (bytes per character) and ES:BP points to the font
  421.      * table.  -3.
  422.      */
  423.  
  424.     regs.h.ah = GETMODE;
  425.     int86(VIDEO_BIOS, ®s, ®s); /* Get Video Mode */
  426.  
  427.     /* This goes back all the way to the original PC.  Completely
  428.      * safe.  AH contains # of columns, AL contains display mode,
  429.      * and BH contains the active display page.
  430.      */
  431.  
  432.     LI = regs.h.dl + 1;
  433.     CO = regs.h.ah;
  434. }
  435.  
  436. #endif /* OVLB */
  437. #ifdef OVL0
  438.  
  439. void
  440. gotoxy(x,y)
  441. int x,y;
  442. {
  443.     union REGS regs;
  444.  
  445.     x--; y--;            /* (0,0) is upper right corner */
  446.  
  447.     regs.h.ah = SETCURPOS;
  448.     regs.h.bh = 0;            /* display page */
  449.     regs.h.dh = y;            /* row */
  450.     regs.h.dl = x;            /* column */
  451.     int86(VIDEO_BIOS, ®s, ®s); /* Set Cursor Position */
  452.  
  453.     /* This, too, goes back all the way to the original PC.  If
  454.      * we ever get so fancy as to swap display pages (i doubt it),
  455.      * then we'll need to set BH appropriately.  This function
  456.      * returns nothing.  -3.
  457.      */
  458. }
  459.  
  460. #endif /* OVL0 */
  461.  
  462. #endif /* MSDOS */
  463.