]> 4ch.mooo.com Git - 16.git/blobdiff - src/lib/16_in.c
[16_ca needs huge amounts of work and I should remember what needs to be done soon...
[16.git] / src / lib / 16_in.c
old mode 100644 (file)
new mode 100755 (executable)
index b27c1cc..14086bd
@@ -1,89 +1,98 @@
-/* Catacomb Apocalypse Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
  *\r
- * This program is free software; you can redistribute it and/or modify\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
  * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
+ * the Free Software Foundation; either version 3 of the License, or\r
  * (at your option) any later version.\r
  *\r
- * This program is distributed in the hope that it will be useful,\r
+ * Project 16 is distributed in the hope that it will be useful,\r
  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
  * GNU General Public License for more details.\r
  *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */
-
-//
-//     ID Engine
-//     ID_IN.c - Input Manager
-//     v1.0d1w
-//     By Jason Blochowiak
-//     Open Watcom port by sparky4
-//
-
-//
-//     This module handles dealing with the various input devices
-//
-//     Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
-//                             User Mgr (for command line parms)
-//
-//     Globals:
-//             LastScan - The keyboard scan code of the last key pressed
-//             LastASCII - The ASCII value of the last key pressed
-//     DEBUG - there are more globals
-//
-
-#include "src/lib/16_in.h"
-
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+//\r
+//     ID Engine\r
+//     ID_IN.c - Input Manager\r
+//     v1.0d1w\r
+//     By Jason Blochowiak\r
+//     Open Watcom port by sparky4\r
+//\r
+\r
+//\r
+//     This module handles dealing with the various input devices\r
+//\r
+//     Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),\r
+//                             User Mgr (for command line parms)\r
+//\r
+//     Globals:\r
+//             LastScan - The keyboard scan code of the last key pressed\r
+//             LastASCII - The ASCII value of the last key pressed\r
+//     DEBUG - there are more globals\r
+//\r
+\r
+#include "src/lib/16_in.h"\r
+#pragma        hdrstop\r
+\r
+static word far* clockw= (word far*) 0x046C; /* 18.2hz clock */\r
+\r
 /*\r
 =============================================================================\r
 \r
                                        GLOBAL VARIABLES\r
 \r
 =============================================================================\r
-*/
-struct inconfig
-{
-       boolean                 MousePresent;\r
-       boolean                 JoysPresent[MaxJoys];\r
-       boolean                 JoyPadPresent[MaxPads];
+*/\r
+/*struct inconfig\r
+{\r
+       boolean         MousePresent;\r
+       boolean         JoysPresent[MaxJoys];\r
        boolean         Keyboard[NumCodes];\r
        boolean         Paused;\r
        char            LastASCII;\r
-       ScanCode        LastScan;
-
-       KeyboardDef     KbdDefs[MaxKbds];
-       JoystickDef     JoyDefs[MaxJoys];
-       JoypadDef       JoypadDefs[MaxPads];
-} inpu;
-
-//extern inconfig inpu;
-//inpu.KbdDefs = {0x1d,0x38,/*0x47,*/0x48,/*0x49,*/0x4b,0x4d,/*0x4f,*/0x50/*,0x51*/};
-
+       ScanCode        LastScan;\r
+\r
+       KeyboardDef     KbdDefs[MaxKbds];\r
+       JoystickDef     JoyDefs[MaxJoys];\r
+} inpu;*/\r
+\r
+//gvar->in.KbdDefs = {0x1d,0x38,/*0x47,*/0x48,/*0x49,*/0x4b,0x4d,/*0x4f,*/0x50/*,0x51*/};\r
+\r
 /*\r
 =============================================================================\r
 \r
                                        LOCAL VARIABLES\r
 \r
 =============================================================================\r
-*/
-
-#ifdef __cplusplus             /* Function must be declared C style */
-extern "C" {
-#endif
-\r
-static struct instat {
-       boolean         IN_Started;\r
-       boolean         CapsLock;\r
-       ScanCode        CurCode,LastCode;
-} inst;
-\r
-static void                    (*INL_KeyHook)(void);
-static void interrupt  (*OldKeyVect)(void);
-static char                    *ParmStringsIN[] = {"nojoys","nomouse",nil};
+*/\r
+\r
+#ifdef __cplusplus             /* Function must be declared C style */\r
+extern "C" {\r
+#endif\r
+\r
+/*static struct instat {\r
+       boolean         CapsLock;\r
+       ScanCode        CurCode,LastCode;\r
+\r
+       boolean         Keyboard[NumCodes];\r
+       boolean         Paused;\r
+       char            LastASCII;\r
+       ScanCode        LastScan;\r
+} inst;*/\r
+\r
+//the def stuff is need fix warnings\r
+#ifndef INSTDEFED\r
+#define INSTDEFED\r
+static inst_t inst;\r
+#endif\r
 \r
 static byte        far ASCIINames[] =          // Unshifted ASCII for scan codes\r
                                        {\r
@@ -145,1056 +154,1203 @@ static        byte        far ASCIINames[] =          // Unshifted ASCII for scan codes
        "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",\r
        "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",\r
        "Down","Left","Right",""\r
-                                       };
+                                       };\r
 \r
 static Direction       DirTable[] =            // Quick lookup for total direction\r
                                        {\r
-                                               //dir_Nortinest,\r
-                                               dir_North,\r
-                                               //dir_NorthEast,\r
+                                               /*dir_NorthWest,        */dir_North,/*  dir_NorthEast,*/\r
                                                dir_West,               dir_None,       dir_East,\r
-                                               //dir_Soutinest,\r
-                                               dir_South//,dir_SouthEast\r
-                                       };
-#ifdef __cplusplus
-}
-#endif
-
-//     Internal routines
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_KeyService() - Handles a keyboard interrupt (key up/down)
-//
-///////////////////////////////////////////////////////////////////////////
-void interrupt
-INL_KeyService()
-{
-static boolean special;
-               byte    k,c;
-               register byte temp;
-
-       k = inp(0x60);  // Get the scan code
-
-       // Tell the XT keyboard controller to clear the key
-       outp(0x61,(temp = inp(0x61)) | 0x80);
-       outp(0x61,temp);
-
-       if (k == 0xe0)          // Special key prefix
-               special = true;
-       else if (k == 0xe1)     // Handle Pause key
-               inpu.Paused = true;
-       else
-       {
-               if (k & 0x80)   // Break code
-               {
-                       k &= 0x7f;
-
-// DEBUG - handle special keys: ctl-alt-delete, print scrn
-
-                       inpu.Keyboard[k] = false;
-               }
-               else                    // Make code
-               {
-                       inst.LastCode = inst.CurCode;
-                       inst.CurCode = inpu.LastScan = k;
-                       inpu.Keyboard[k] = true;
-
-                       if (special)
-                               c = SpecialNames[k];
-                       else
-                       {
-                               if (k == sc_CapsLock)
-                               {
-                                       inst.CapsLock ^= true;
-                                       // DEBUG - make caps lock light work
-                               }
-
-                               if (inpu.Keyboard[sc_LShift] || inpu.Keyboard[sc_RShift])       // If shifted
-                               {
-                                       c = ShiftNames[k];
-                                       if ((c >= 'A') && (c <= 'Z') && inst.CapsLock)
-                                               c += 'a' - 'A';
-                               }
-                               else
-                               {
-                                       c = ASCIINames[k];
-                                       if ((c >= 'a') && (c <= 'z') && inst.CapsLock)
-                                               c -= 'a' - 'A';
-                               }
-                       }
-                       if (c)
-                               inpu.LastASCII = c;
-               }
-
-               special = false;
-       }
-
-       if (INL_KeyHook && !special)
-               INL_KeyHook();
-       #ifdef TESTKEYIN
-       printf("%c %x %u\n", c, k, inpu.Keyboard[k]);
-       #endif
-       outp(0x20,0x20);
-}
-
-void
-Mouse(int x)
-{
-       union REGS CPURegs;
-       x = CPURegs.x.ax;
-       int86(MouseInt,&CPURegs,&CPURegs);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_GetMouseDelta() - Gets the amount that the mouse has moved from the
-//             mouse driver
-//
-///////////////////////////////////////////////////////////////////////////
-static void
-INL_GetMouseDelta(int *x,int *y)
-{
-       union REGS CPURegs;
-       Mouse(MDelta);
-       *x = CPURegs.x.cx;
-       *y = CPURegs.x.dx;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_GetMouseButtons() - Gets the status of the mouse buttons from the
-//             mouse driver
-//
-///////////////////////////////////////////////////////////////////////////
-static word
-INL_GetMouseButtons(void)
-{
-       union REGS CPURegs;
-       word    buttons;
-
-       Mouse(MButtons);
-       buttons = CPURegs.x.bx;
-       return(buttons);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_GetJoyAbs() - Reads the absolute position of the specified joystick
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_GetJoyAbs(word joy,word *xp,word *yp)
-{
-       byte    xb,yb,
-                       xs,ys;
-       word    x,y;
-
-       x = y = 0;
-       xs = joy? 2 : 0;                // Find shift value for x axis
-       xb = 1 << xs;                   // Use shift value to get x bit mask
-       ys = joy? 3 : 1;                // Do the same for y axis
-       yb = 1 << ys;
-
-// Read the absolute joystick values
-       __asm
-       {
-               pushf                           // Save some registers
-               push    si
-               push    di
-               cli                                     // Make sure an interrupt doesn't screw the timings
-
-
-               mov             dx,0x201
-               in              al,dx
-               out             dx,al           // Clear the resistors
-
-               mov             ah,[xb]         // Get masks into registers
-               mov             ch,[yb]
-
-               xor             si,si           // Clear count registers
-               xor             di,di
-               xor             bh,bh           // Clear high byte of bx for later
-
-               push    bp                      // Don't mess up stack frame
-               mov             bp,MaxJoyValue
-
-loo:
-               in              al,dx           // Get bits indicating whether all are finished
-
-               dec             bp                      // Check bounding register
-               jz              done            // We have a silly value - abort
-
-               mov             bl,al           // Duplicate the bits
-               and             bl,ah           // Mask off useless bits (in [xb])
-               add             si,bx           // Possibly increment count register
-               mov             cl,bl           // Save for testing later
-
-               mov             bl,al
-               and             bl,ch           // [yb]
-               add             di,bx
-
-               add             cl,bl
-               jnz             loo             // If both bits were 0, drop out
-
-done:
-               pop             bp
-
-               mov             cl,[xs]         // Get the number of bits to shift
-               shr             si,cl           //  and shift the count that many times
-
-               mov             cl,[ys]
-               shr             di,cl
-
-               mov             [x],si          // Store the values into the variables
-               mov             [y],di
-
-               pop             di
-               pop             si
-               popf                            // Restore the registers
-       }
-
-       *xp = x;
-       *yp = y;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_GetJoyDelta() - Returns the relative movement of the specified
-//             joystick (from +/-127, scaled adaptively)
-//
-///////////////////////////////////////////////////////////////////////////
-static void
-INL_GetJoyDelta(word joy,int *dx,int *dy,boolean adaptive)
-{
-       word            x,y;
-       dword   time;
-       dword TimeCount = *clockdw;
-       JoystickDef     *def;
-static dword   lasttime;
-
-       IN_GetJoyAbs(joy,&x,&y);
-       def = inpu.JoyDefs + joy;
-
-       if (x < def->threshMinX)
-       {
-               if (x < def->joyMinX)
-                       x = def->joyMinX;
-
-               x = -(x - def->threshMinX);
-               x *= def->joyMultXL;
-               x >>= JoyScaleShift;
-               *dx = (x > 127)? -127 : -x;
-       }
-       else if (x > def->threshMaxX)
-       {
-               if (x > def->joyMaxX)
-                       x = def->joyMaxX;
-
-               x = x - def->threshMaxX;
-               x *= def->joyMultXH;
-               x >>= JoyScaleShift;
-               *dx = (x > 127)? 127 : x;
-       }
-       else
-               *dx = 0;
-
-       if (y < def->threshMinY)
-       {
-               if (y < def->joyMinY)
-                       y = def->joyMinY;
-
-               y = -(y - def->threshMinY);
-               y *= def->joyMultYL;
-               y >>= JoyScaleShift;
-               *dy = (y > 127)? -127 : -y;
-       }
-       else if (y > def->threshMaxY)
-       {
-               if (y > def->joyMaxY)
-                       y = def->joyMaxY;
-
-               y = y - def->threshMaxY;
-               y *= def->joyMultYH;
-               y >>= JoyScaleShift;
-               *dy = (y > 127)? 127 : y;
-       }
-       else
-               *dy = 0;
-
-       if (adaptive)
-       {
-               time = (TimeCount - lasttime) / 2;
-               if (time)
-               {
-                       if (time > 8)
-                               time = 8;
-                       *dx *= time;
-                       *dy *= time;
-               }
-       }
-       lasttime = TimeCount;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_GetJoyButtons() - Returns the button status of the specified
-//             joystick
-//
-///////////////////////////////////////////////////////////////////////////
-static word
-INL_GetJoyButtons(word joy)
-{
-register       word    result;
-
-       result = inp(0x201);    // Get all the joystick buttons
-       result >>= joy? 6 : 4;  // Shift into bits 0-1
-       result &= 3;                            // Mask off the useless bits
-       result ^= 3;
-       return(result);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_GetJoyButtonsDB() - Returns the de-bounced button status of the
-//             specified joystick
-//
-///////////////////////////////////////////////////////////////////////////
-word
-IN_GetJoyButtonsDB(word joy)
-{
-       dword TimeCount = *clockdw;
-       dword   lasttime;
-       word            result1,result2;
-
-       do
-       {
-               result1 = INL_GetJoyButtons(joy);
-               lasttime = TimeCount;
-               while(TimeCount == lasttime)
-               result2 = INL_GetJoyButtons(joy);
-       } while(result1 != result2);
-       return(result1);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_StartKbd() - Sets up my keyboard stuff for use
-//
-///////////////////////////////////////////////////////////////////////////
-static void
-INL_StartKbd()
-{
-       INL_KeyHook = 0;        // Clear key hook
-
-       IN_ClearKeysDown();
-
-       OldKeyVect = _dos_getvect(KeyInt);
-       _dos_setvect(KeyInt,INL_KeyService);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_ShutKbd() - Restores keyboard control to the BIOS
-//
-///////////////////////////////////////////////////////////////////////////
-static void
-INL_ShutKbd(void)
-{
-       pokeb(0x40,0x17,peekb(0x40,0x17) & 0xfaf0);     // Clear ctrl/alt/shift flags
-
-       _dos_setvect(KeyInt,OldKeyVect);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_StartMouse() - Detects and sets up the mouse
-//
-///////////////////////////////////////////////////////////////////////////
-static boolean
-INL_StartMouse(void)
-{
-       union REGS CPURegs;
-       if(_dos_getvect(MouseInt))
-       {
-               Mouse(MReset);
-               if(CPURegs.x.ax == 0xffff)
-                       return(true);
-       }
-       return(false);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_ShutMouse() - Cleans up after the mouse
-//
-///////////////////////////////////////////////////////////////////////////
-static void
-INL_ShutMouse(void)
-{
-}
-
-//
-//     INL_SetJoyScale() - Sets up scaling values for the specified joystick
-//
-static void
-INL_SetJoyScale(word joy)
-{
-       JoystickDef     *def;
-
-       def = &(inpu.JoyDefs[joy]);
-       def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);
-       def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);
-       def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);
-       def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()
-//             to set up scaling values
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)
-{
-       word            d,r;
-       JoystickDef     *def;
-
-       def = &(inpu.JoyDefs[joy]);
-
-       def->joyMinX = minx;
-       def->joyMaxX = maxx;
-       r = maxx - minx;
-       d = r / 3;
-       def->threshMinX = ((r / 2) - d) + minx;
-       def->threshMaxX = ((r / 2) + d) + minx;
-
-       def->joyMinY = miny;
-       def->joyMaxY = maxy;
-       r = maxy - miny;
-       d = r / 3;
-       def->threshMinY = ((r / 2) - d) + miny;
-       def->threshMaxY = ((r / 2) + d) + miny;
-
-       INL_SetJoyScale(joy);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_StartJoy() - Detects & auto-configures the specified joystick
-//                                     The auto-config assumes the joystick is centered
-//
-///////////////////////////////////////////////////////////////////////////
-static boolean
-INL_StartJoy(word joy)
-{
-       word            x,y;
-
-       IN_GetJoyAbs(joy,&x,&y);
-
-       if
-       (
-               ((x == 0) || (x > MaxJoyValue - 10))
-       ||      ((y == 0) || (y > MaxJoyValue - 10))
-       )
-               return(false);
-       else
-       {
-               IN_SetupJoy(joy,0,x * 2,0,y * 2);
-               return(true);
-       }
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_ShutJoy() - Cleans up the joystick stuff
-//
-///////////////////////////////////////////////////////////////////////////
-static void
-INL_ShutJoy(word joy)
-{
-       inpu.JoysPresent[joy] = false;
-}
-
-//     Public routines
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_Startup() - Starts up the Input Mgr
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_Startup()
-{
-       boolean checkjoys,checkmouse;
-       word    i;
-
-       if (inst.IN_Started)
-               return;
-
-       checkjoys = true;
-       checkmouse = true;
-       for (i = 1;i < __argc;i++)
-       {
-               switch (US_CheckParm(__argv[i],ParmStringsIN))
-               {
-               case 0:
-                       checkjoys = false;
-                       break;
-               case 1:
-                       checkmouse = false;
-                       break;
-               }
-       }
-
-       INL_StartKbd();
-       inpu.MousePresent = checkmouse? INL_StartMouse() : false;
-
-       for (i = 0;i < MaxJoys;i++)
-               inpu.JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;
-
-       inst.IN_Started = true;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_Default() - Sets up default conditions for the Input Mgr
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_Default(boolean gotit,player_t *player,ControlType nt)
-{
-       if
-       (
-               (!gotit)
-       ||      ((nt == ctrl_Joystick1) && !inpu.JoysPresent[0])
-       ||      ((nt == ctrl_Joystick2) && !inpu.JoysPresent[1])
-       ||      ((nt == ctrl_Mouse) && !inpu.MousePresent)
-       ||      ((nt == ctrl_Joypad1) && !inpu.JoyPadPresent[0])
-       ||      ((nt == ctrl_Joypad2) && !inpu.JoyPadPresent[1])
-       )
-               nt = ctrl_Keyboard1;
-       inpu.KbdDefs[0].button0 = 0x1d;
-       inpu.KbdDefs[0].button1 = 0x38;
-       //in.KbdDefs[0].upleft = 0x47;
-       inpu.KbdDefs[0].up = 0x48;
-       //in.KbdDefs[0].upright = 0x49;
-       inpu.KbdDefs[0].left = 0x4b;
-       inpu.KbdDefs[0].right = 0x4d;
-       //in.KbdDefs[0].downleft = 0x4f;
-       inpu.KbdDefs[0].down = 0x50;
-       //in.KbdDefs[0].downright = 0x51;
-       IN_SetControlType(0,player,nt);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_Shutdown() - Shuts down the Input Mgr
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_Shutdown()
-{
-       word    i;
-
-       if (!inst.IN_Started)
-               return;
-
-       INL_ShutMouse();
-       for (i = 0;i < MaxJoys;i++)
-               INL_ShutJoy(i);
-       INL_ShutKbd();
-
-       inst.IN_Started = false;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()
-//                     everytime a real make/break code gets hit
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_SetKeyHook(void (*hook)())
-{
-       INL_KeyHook = hook;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_ClearKeyDown() - Clears the keyboard array
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_ClearKeysDown()
-{
-       int     i;
-
-       inpu.LastScan = sc_None;
-       inpu.LastASCII = key_None;
-       memset (inpu.Keyboard,0,sizeof(inpu.Keyboard));
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()
-//
-///////////////////////////////////////////////////////////////////////////
-static void
-INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)
-{
-       if (buttons & (1 << 0))
-               info->button0 = true;
-       if (buttons & (1 << 1))
-               info->button1 = true;
-
-       info->x += dx;
-       info->y += dy;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_ReadCursor() - Reads the input devices and fills in the cursor info
-//             struct
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_ReadCursor(CursorInfo *info)
-{
-       word    i,
-                       buttons;
-       int             dx,dy;
-
-       info->x = info->y = 0;
-       info->button0 = info->button1 = false;
-
-       if (inpu.MousePresent)
-       {
-               buttons = INL_GetMouseButtons();
-               INL_GetMouseDelta(&dx,&dy);
-               INL_AdjustCursor(info,buttons,dx,dy);
-       }
-
-       for (i = 0;i < MaxJoys;i++)
-       {
-               if (!inpu.JoysPresent[i])
-                       continue;
-
-               buttons = INL_GetJoyButtons(i);
-               INL_GetJoyDelta(i,&dx,&dy,true);
-               dx /= 64;
-               dy /= 64;
-               INL_AdjustCursor(info,buttons,dx,dy);
-       }
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_ReadControl() - Reads the device associated with the specified
-//             player and fills in the control info struct
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_ReadControl(int playnum,player_t *player)
-{
-                       boolean         realdelta;
-                       byte            dbyte;
-                       word            buttons;
-                       int                     dx,dy;
-                       Motion          mx,my;
-                       ControlType     type;
-register       KeyboardDef     *def;
-
-       dx = dy = 0;
-       mx = my = motion_None;
-       buttons = 0;
-
-#if DEMO0
-       if (DemoMode == demo_Playback)
-       {
-               dbyte = DemoBuffer[DemoOffset + 1];
-               my = (dbyte & 3) - 1;
-               mx = ((dbyte >> 2) & 3) - 1;
-               buttons = (dbyte >> 4) & 3;
-
-               if (!(--DemoBuffer[DemoOffset]))
-               {
-                       DemoOffset += 2;
-                       if (DemoOffset >= DemoSize)
-                               DemoMode = demo_PlayDone;
-               }
-
-               realdelta = false;
-       }
-       else if (DemoMode == demo_PlayDone)
-               Quit("Demo playback exceeded");
-       else
-       {
-#endif
-               switch (type = player[playnum].Controls)
-               {
-               case ctrl_Keyboard1:
-               case ctrl_Keyboard2:
-                       def = &(inpu.KbdDefs[type - ctrl_Keyboard]);
-
-/*                     if (Keyboard[def->upleft])
-                               mx = motion_Left,my = motion_Up;
-                       else if (Keyboard[def->upright])
-                               mx = motion_Right,my = motion_Up;
-                       else if (Keyboard[def->downleft])
-                               mx = motion_Left,my = motion_Down;
-                       else if (Keyboard[def->downright])
-                               mx = motion_Right,my = motion_Down;*/
-
-                       if (inpu.Keyboard[def->up])
-                               my = motion_Up;
-                       else if (inpu.Keyboard[def->down])
-                               my = motion_Down;
-
-                       if (inpu.Keyboard[def->left])
-                               mx = motion_Left;
-                       else if (inpu.Keyboard[def->right])
-                               mx = motion_Right;
-
-                       if (inpu.Keyboard[def->button0])
-                               buttons += 1 << 0;
-                       if (inpu.Keyboard[def->button1])
-                               buttons += 1 << 1;
-                       realdelta = false;
-                       break;
-               case ctrl_Joystick1:
-               case ctrl_Joystick2:
-                       INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
-                       buttons = INL_GetJoyButtons(type - ctrl_Joystick);
-                       realdelta = true;
-                       break;
-               case ctrl_Mouse:
-                       INL_GetMouseDelta(&dx,&dy);
-                       buttons = INL_GetMouseButtons();
-                       realdelta = true;
-                       break;
-               case ctrl_Joypad1:
-               case ctrl_Joypad2:
-                       printf("wwww");
-                       break;
-               }
-#ifdef DEMO0
-       }
-#endif
-
-       if (realdelta)
-       {
-               mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
-               my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
-       }
-       else
-       {
-               dx = mx * 127;
-               dy = my * 127;
-       }
-
-       player[playnum].info.x = dx;
-       player[playnum].info.xaxis = mx;
-       player[playnum].info.y = dy;
-       player[playnum].info.yaxis = my;
-       player[playnum].info.button0 = buttons & (1 << 0);
-       player[playnum].info.button1 = buttons & (1 << 1);
-       player[playnum].info.button2 = buttons & (1 << 2);
-       player[playnum].info.button3 = buttons & (1 << 3);
-       player[playnum].info.dir = DirTable[((my + 1) * 3) + (mx + 1)];
-
-#if DEMO0
-       if (DemoMode == demo_Record)
-       {
-               // Pack the control info into a byte
-               dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
-
-               if
-               (
-                       (DemoBuffer[DemoOffset + 1] == dbyte)
-               &&      (DemoBuffer[DemoOffset] < 255)
-               )
-                       (DemoBuffer[DemoOffset])++;
-               else
-               {
-                       if (DemoOffset || DemoBuffer[DemoOffset])
-                               DemoOffset += 2;
-
-                       if (DemoOffset >= DemoSize)
-                               Quit("Demo buffer overflow");
-
-                       DemoBuffer[DemoOffset] = 1;
-                       DemoBuffer[DemoOffset + 1] = dbyte;
-               }
-       }
-#endif
-#ifdef TESTCONTROLNOISY
-printf("dir=%d\n", player[playnum].info.dir);
-#endif
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_SetControlType() - Sets the control type to be used by the specified
-//             player
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_SetControlType(word playnum,player_t *player,ControlType type)
-{
-       // DEBUG - check that requested type is present?
-       player[playnum].Controls = type;
-}
-
-#if DEMO0
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_StartDemoRecord() - Starts the demo recording, using a buffer the
-//             size passed. Returns if the buffer allocation was successful
-//
-///////////////////////////////////////////////////////////////////////////
-boolean
-IN_StartDemoRecord(word bufsize)
-{
-       if (!bufsize)
-               return(false);
-
-       MM_GetPtr((memptr *)&DemoBuffer,bufsize);
-       DemoMode = demo_Record;
-       DemoSize = bufsize & ~1;
-       DemoOffset = 0;
-       DemoBuffer[0] = DemoBuffer[1] = 0;
-
-       return(true);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_StartDemoPlayback() - Plays back the demo pointed to of the given size
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_StartDemoPlayback(byte /*__segment*/ *buffer,word bufsize)
-{
-       DemoBuffer = buffer;
-       DemoMode = demo_Playback;
-       DemoSize = bufsize & ~1;
-       DemoOffset = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_StopDemo() - Turns off demo mode
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_StopDemo(void)
-{
-       if ((DemoMode == demo_Record) && DemoOffset)
-               DemoOffset += 2;
-
-       DemoMode = demo_Off;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_FreeDemoBuffer(void)
-{
-       if (DemoBuffer)
-               MM_FreePtr((memptr *)&DemoBuffer);
-}
-#endif
-
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_GetScanName() - Returns a string containing the name of the
-//             specified scan code
-//
-///////////////////////////////////////////////////////////////////////////
-byte *
-IN_GetScanName(ScanCode scan)
-{
-       byte            **p;
-       ScanCode        far *s;
-
-       for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)
-               if (*s == scan)
-                       return(*p);
-
-       return(ScanNames[scan]);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_WaitForKey() - Waits for a scan code, then clears LastScan and
-//             returns the scan code
-//
-///////////////////////////////////////////////////////////////////////////
-ScanCode
-IN_WaitForKey()
-{
-       ScanCode        result;
-
-       while (!(result = inpu.LastScan))
-               ;
-       inpu.LastScan = 0;
-       return(result);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
-//             returns the ASCII value
-//
-///////////////////////////////////////////////////////////////////////////
-char
-IN_WaitForASCII()
-{
-       char            result;
-
-       while (!(result = inpu.LastASCII))
-               ;
-       inpu.LastASCII = '\0';
-       return(result);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_AckBack() - Waits for either an ASCII keypress or a button press
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_AckBack()
-{
-       word    i;
-
-       while (!inpu.LastScan)
-       {
-               if (inpu.MousePresent)
-               {
-                       if (INL_GetMouseButtons())
-                       {
-                               while (INL_GetMouseButtons())
-                                       ;
-                               return;
-                       }
-               }
-
-               for (i = 0;i < MaxJoys;i++)
-               {
-                       if (inpu.JoysPresent[i])
-                       {
-                               if (IN_GetJoyButtonsDB(i))
-                               {
-                                       while (IN_GetJoyButtonsDB(i))
-                                               ;
-                                       return;
-                               }
-                       }
-               }
-       }
-
-       IN_ClearKey(inpu.LastScan);
-       inpu.LastScan = sc_None;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_Ack() - Clears user input & then calls IN_AckBack()
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_Ack()
-{
-       word    i;
-
-       IN_ClearKey(inpu.LastScan);
-       inpu.LastScan = sc_None;
-
-       if (inpu.MousePresent)
-               while (INL_GetMouseButtons())
-                                       ;
-       for (i = 0;i < MaxJoys;i++)
-               if (inpu.JoysPresent[i])
-                       while (IN_GetJoyButtonsDB(i))
-                               ;
-
-       IN_AckBack();
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_IsUserInput() - Returns true if a key has been pressed or a button
-//             is down
-//
-///////////////////////////////////////////////////////////////////////////
-boolean
-IN_IsUserInput()
-{
-       boolean result;
-       word    i;
-
-       result = inpu.LastScan;
-
-       if (inpu.MousePresent)
-               if (INL_GetMouseButtons())
-                       result = true;
-
-       for (i = 0;i < MaxJoys;i++)
-               if (inpu.JoysPresent[i])
-                       if (INL_GetJoyButtons(i))
-                               result = true;
-
-       return(result);
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-//     IN_UserInput() - Waits for the specified delay time (in ticks) or the
-//             user pressing a key or a mouse button. If the clear flag is set, it
-//             then either clears the key or waits for the user to let the mouse
-//             button up.
-//
-///////////////////////////////////////////////////////////////////////////
-boolean
-IN_UserInput(dword delay,boolean clear)
-{
-       dword TimeCount = *clockdw;
-       dword   lasttime;
-
-       lasttime = TimeCount;
-       do
-       {
-               if (IN_IsUserInput())
-               {
-                       if (clear)
-                               IN_AckBack();
-                       return(true);
-               }
-       } while (TimeCount - lasttime < delay);
-       return(false);
-}
-
-boolean IN_KeyDown(byte code)
-{
-       return inpu.Keyboard[code];
-}
-\r
-void IN_ClearKey(byte code)
-{
-       inpu.Keyboard[code] = false;
-       if(code == inpu.LastScan)
-               inpu.LastScan = sc_None;
-       }
-
-boolean IN_qb(byte kee)
-{
-       printf("%u\n", inpu.Keyboard[kee]);
-       if(inpu.Keyboard[kee]==true) return 1;
-       else return 0;
-}
+                                               /*dir_SouthWest,        */dir_South/*,  dir_SouthEast*/\r
+                                       };\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+static void                    (*INL_KeyHook)(void);\r
+static void interrupt  (*OldKeyVect)(void);\r
+static char                    *ParmStringsIN[] = {"nojoys","nomouse",nil};\r
+\r
+//     Internal routines\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_KeyService() - Handles a keyboard interrupt (key up/down)\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+/*static */void interrupt\r
+INL_KeyService(void)\r
+{\r
+static boolean special;\r
+               byte    k,c,\r
+                               temp;\r
+\r
+       k = inportb(0x60);      // Get the scan code\r
+\r
+       // Tell the XT keyboard controller to clear the key\r
+       outportb(0x61,(temp = inportb(0x61)) | 0x80);\r
+       outportb(0x61,temp);\r
+\r
+       if (k == 0xe0)          // Special key prefix\r
+               special = true;\r
+       else if (k == 0xe1)     // Handle Pause key\r
+               inst.Paused = true;\r
+       else\r
+       {\r
+               if (k & 0x80)   // Break code\r
+               {\r
+                       k &= 0x7f;\r
+\r
+// DEBUG - handle special keys: ctl-alt-delete, print scrn\r
+\r
+                       inst.Keyboard[k] = false;\r
+               }\r
+               else                    // Make code\r
+               {\r
+                       inst.LastCode = inst.CurCode;\r
+                       inst.CurCode = inst.LastScan = k;\r
+                       inst.Keyboard[k] = true;\r
+\r
+                       if (special)\r
+                               c = SpecialNames[k];\r
+                       else\r
+                       {\r
+                               if (k == sc_CapsLock)\r
+                               {\r
+                                       inst.CapsLock ^= true;\r
+                                       // DEBUG - make caps lock light work\r
+                               }\r
+\r
+                               if (inst.Keyboard[sc_LShift] || inst.Keyboard[sc_RShift])       // If shifted\r
+                               {\r
+                                       c = ShiftNames[k];\r
+                                       if ((c >= 'A') && (c <= 'Z') && inst.CapsLock)\r
+                                               c += 'a' - 'A';\r
+                               }\r
+                               else\r
+                               {\r
+                                       c = ASCIINames[k];\r
+                                       if ((c >= 'a') && (c <= 'z') && inst.CapsLock)\r
+                                               c -= 'a' - 'A';\r
+                               }\r
+                       }\r
+                       if (c)\r
+                               inst.LastASCII = c;\r
+               }\r
+\r
+               special = false;\r
+       }\r
+\r
+       if (INL_KeyHook && !special)\r
+               INL_KeyHook();\r
+#ifdef __DEBUG_InputMgr__\r
+       if(dbg_testkeyin > 0) printf("%c        %u      [0x%x %u]       %u\n", c, c, k, k, inst.Keyboard[k]);\r
+#endif\r
+       outportb(0x20,0x20);\r
+}\r
+\r
+void INL_Mouse(int x)\r
+{\r
+       //union REGS CPURegs;\r
+       //x = CPURegs.x.ax;\r
+       __asm {\r
+               mov     ax,x\r
+               int     MouseInt\r
+       }\r
+       //int86(MouseInt,&CPURegs,&CPURegs);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_GetMouseDelta() - Gets the amount that the mouse has moved from the\r
+//             mouse driver\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+INL_GetMouseDelta(int *x,int *y)\r
+{\r
+       union REGS CPURegs;\r
+       Mouse(MDelta);\r
+       *x = CPURegs.x.cx;\r
+       *y = CPURegs.x.dx;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_GetMouseButtons() - Gets the status of the mouse buttons from the\r
+//             mouse driver\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static word\r
+INL_GetMouseButtons(void)\r
+{\r
+       union REGS CPURegs;\r
+       word    buttons;\r
+\r
+       Mouse(MButtons);\r
+       buttons = CPURegs.x.bx;\r
+       return(buttons);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_GetJoyAbs() - Reads the absolute position of the specified joystick\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_GetJoyAbs(word joy,word *xp,word *yp)\r
+{\r
+       byte    xb,yb,\r
+                       xs,ys;\r
+       word    x,y;\r
+\r
+       x = y = 0;\r
+       xs = joy? 2 : 0;                // Find shift value for x axis\r
+       xb = 1 << xs;                   // Use shift value to get x bit mask\r
+       ys = joy? 3 : 1;                // Do the same for y axis\r
+       yb = 1 << ys;\r
+\r
+// Read the absolute joystick values\r
+       __asm {\r
+               pushf                           // Save some registers\r
+               push    si\r
+               push    di\r
+               cli                                     // Make sure an interrupt doesn't screw the timings\r
+\r
+\r
+               mov             dx,0x201\r
+               in              al,dx\r
+               out             dx,al           // Clear the resistors\r
+\r
+               mov             ah,[xb]         // Get masks into registers\r
+               mov             ch,[yb]\r
+\r
+               xor             si,si           // Clear count registers\r
+               xor             di,di\r
+               xor             bh,bh           // Clear high byte of bx for later\r
+\r
+               push    bp                      // Don't mess up stack frame\r
+               mov             bp,MaxJoyValue\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+loo:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               in              al,dx           // Get bits indicating whether all are finished\r
+\r
+               dec             bp                      // Check bounding register\r
+               jz              done            // We have a silly value - abort\r
+\r
+               mov             bl,al           // Duplicate the bits\r
+               and             bl,ah           // Mask off useless bits (in [xb])\r
+               add             si,bx           // Possibly increment count register\r
+               mov             cl,bl           // Save for testing later\r
+\r
+               mov             bl,al\r
+               and             bl,ch           // [yb]\r
+               add             di,bx\r
+\r
+               add             cl,bl\r
+               jnz             loo             // If both bits were 0, drop out\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+done:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               pop             bp\r
+\r
+               mov             cl,[xs]         // Get the number of bits to shift\r
+               shr             si,cl           //  and shift the count that many times\r
+\r
+               mov             cl,[ys]\r
+               shr             di,cl\r
+\r
+               mov             [x],si          // Store the values into the variables\r
+               mov             [y],di\r
+\r
+               pop             di\r
+               pop             si\r
+               popf                            // Restore the registers\r
+       }\r
+\r
+       *xp = x;\r
+       *yp = y;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_GetJoyDelta() - Returns the relative movement of the specified\r
+//             joystick (from +/-127)\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void INL_GetJoyDelta(word joy,int *dx,int *dy/*,boolean adaptive*/, global_game_variables_t *gvar)\r
+{\r
+       word            x,y;\r
+       word TimeCount = *clockw;\r
+       JoystickDef     *def;\r
+static word    lasttime;\r
+\r
+       IN_GetJoyAbs(joy,&x,&y);\r
+       def = gvar->in.JoyDefs + joy;\r
+\r
+       if (x < def->threshMinX)\r
+       {\r
+               if (x < def->joyMinX)\r
+                       x = def->joyMinX;\r
+\r
+               x = -(x - def->threshMinX);\r
+               x *= def->joyMultXL;\r
+               x >>= JoyScaleShift;\r
+               *dx = (x > 127)? -127 : -x;\r
+       }\r
+       else if (x > def->threshMaxX)\r
+       {\r
+               if (x > def->joyMaxX)\r
+                       x = def->joyMaxX;\r
+\r
+               x = x - def->threshMaxX;\r
+               x *= def->joyMultXH;\r
+               x >>= JoyScaleShift;\r
+               *dx = (x > 127)? 127 : x;\r
+       }\r
+       else\r
+               *dx = 0;\r
+\r
+       if (y < def->threshMinY)\r
+       {\r
+               if (y < def->joyMinY)\r
+                       y = def->joyMinY;\r
+\r
+               y = -(y - def->threshMinY);\r
+               y *= def->joyMultYL;\r
+               y >>= JoyScaleShift;\r
+               *dy = (y > 127)? -127 : -y;\r
+       }\r
+       else if (y > def->threshMaxY)\r
+       {\r
+               if (y > def->joyMaxY)\r
+                       y = def->joyMaxY;\r
+\r
+               y = y - def->threshMaxY;\r
+               y *= def->joyMultYH;\r
+               y >>= JoyScaleShift;\r
+               *dy = (y > 127)? 127 : y;\r
+       }\r
+       else\r
+               *dy = 0;\r
+//     if (adaptive)\r
+//     {\r
+//             time = (TimeCount - lasttime) / 2;\r
+//             if (time)\r
+//             {\r
+//                     if (time > 8)\r
+//                             time = 8;\r
+//                     *dx *= time;\r
+//                     *dy *= time;\r
+//             }\r
+//     }\r
+       lasttime = TimeCount;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_GetJoyButtons() - Returns the button status of the specified\r
+//             joystick\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static word\r
+INL_GetJoyButtons(word joy)\r
+{\r
+register       word    result;\r
+\r
+       result = inportb(0x201);        // Get all the joystick buttons\r
+       result >>= joy? 6 : 4;  // Shift into bits 0-1\r
+       result &= 3;                            // Mask off the useless bits\r
+       result ^= 3;\r
+       return(result);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_GetJoyButtonsDB() - Returns the de-bounced button status of the\r
+//             specified joystick\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+word\r
+IN_GetJoyButtonsDB(word joy)\r
+{\r
+       word TimeCount = *clockw;\r
+       word    lasttime;\r
+       word            result1,result2;\r
+\r
+       do\r
+       {\r
+               result1 = INL_GetJoyButtons(joy);\r
+               lasttime = TimeCount;\r
+               while(TimeCount == lasttime)\r
+                       //;\r
+               result2 = INL_GetJoyButtons(joy);\r
+       } while(result1 != result2);\r
+       return(result1);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_StartKbd() - Sets up my keyboard stuff for use\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+INL_StartKbd(global_game_variables_t *gvar)\r
+{\r
+       INL_KeyHook = NULL;     // Clear key hook\r
+\r
+       IN_ClearKeysDown();\r
+\r
+       OldKeyVect = getvect(KeyInt);//IN_KbdLED();\r
+       setvect(KeyInt,INL_KeyService);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_ShutKbd() - Restores keyboard control to the BIOS\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+INL_ShutKbd(void)\r
+{\r
+       pokeb(0x40,0x17,peekb(0x40,0x17) & 0xfaf0);     // Clear ctrl/alt/shift flags\r
+\r
+       setvect(KeyInt,OldKeyVect);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_StartMouse() - Detects and sets up the mouse\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static boolean\r
+INL_StartMouse(void)\r
+{\r
+#if 0\r
+       if (getvect(MouseInt))\r
+       {\r
+               Mouse(MReset);\r
+               if (_AX == 0xffff)\r
+                       return(true);\r
+       }\r
+       return(false);\r
+#endif\r
+       byte far *vector;\r
+\r
+\r
+       if ((vector=MK_FP(peek(0,0x33*4+2),peek(0,0x33*4)))==NULL)\r
+       return false;\r
+\r
+       if (*vector == 207)\r
+               return false;\r
+\r
+       Mouse(MReset);\r
+       return true;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_ShutMouse() - Cleans up after the mouse\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+INL_ShutMouse(void)\r
+{\r
+}\r
+\r
+//\r
+//     INL_SetJoyScale() - Sets up scaling values for the specified joystick\r
+//\r
+static void\r
+INL_SetJoyScale(word joy, global_game_variables_t *gvar)\r
+{\r
+       JoystickDef     *def;\r
+\r
+       def = &(gvar->in.JoyDefs[joy]);\r
+       def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);\r
+       def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);\r
+       def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);\r
+       def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()\r
+//             to set up scaling values\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy, global_game_variables_t *gvar)\r
+{\r
+       word            d,r;\r
+       JoystickDef     *def;\r
+\r
+       def = &(gvar->in.JoyDefs[joy]);\r
+\r
+       def->joyMinX = minx;\r
+       def->joyMaxX = maxx;\r
+       r = maxx - minx;\r
+       d = r / 3;\r
+       def->threshMinX = ((r / 2) - d) + minx;\r
+       def->threshMaxX = ((r / 2) + d) + minx;\r
+\r
+       def->joyMinY = miny;\r
+       def->joyMaxY = maxy;\r
+       r = maxy - miny;\r
+       d = r / 3;\r
+       def->threshMinY = ((r / 2) - d) + miny;\r
+       def->threshMaxY = ((r / 2) + d) + miny;\r
+\r
+       INL_SetJoyScale(joy, gvar);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_StartJoy() - Detects & auto-configures the specified joystick\r
+//                                     The auto-config assumes the joystick is centered\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static boolean\r
+INL_StartJoy(word joy, global_game_variables_t *gvar)\r
+{\r
+       word            x,y;\r
+\r
+       IN_GetJoyAbs(joy,&x,&y);\r
+\r
+       if\r
+       (\r
+               ((x == 0) || (x > MaxJoyValue - 10))\r
+       ||      ((y == 0) || (y > MaxJoyValue - 10))\r
+       )\r
+               return(false);\r
+       else\r
+       {\r
+               IN_SetupJoy(joy,0,x * 2,0,y * 2, gvar);\r
+               return(true);\r
+       }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_ShutJoy() - Cleans up the joystick stuff\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+INL_ShutJoy(word joy, global_game_variables_t *gvar)\r
+{\r
+       gvar->in.JoysPresent[joy] = false;\r
+}\r
+\r
+//     Public routines\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_Startup() - Starts up the Input Mgr\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_Startup(global_game_variables_t *gvar)\r
+{\r
+       boolean checkjoys,checkmouse;\r
+       word    i;\r
+\r
+       if (gvar->in.IN_Started)\r
+               return;\r
+\r
+       checkjoys = true;\r
+       checkmouse = true;\r
+       for (i = 1;i < _argc;i++)\r
+       {\r
+               switch (US_CheckParm(_argv[i],ParmStringsIN))\r
+               {\r
+               case 0:\r
+                       checkjoys = false;\r
+                       break;\r
+               case 1:\r
+                       checkmouse = false;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       INL_StartKbd(gvar);\r
+       gvar->in.MousePresent = checkmouse? INL_StartMouse() : false;\r
+\r
+       for (i = 0;i < MaxJoys;i++)\r
+               gvar->in.JoysPresent[i] = checkjoys? INL_StartJoy(i, gvar) : false;\r
+\r
+       gvar->in.inst = &inst;\r
+\r
+       gvar->in.IN_Started = true;\r
+\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_Default() - Sets up default conditions for the Input Mgr\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_Default(boolean gotit,player_t *player,ControlType nt, global_game_variables_t *gvar)\r
+{\r
+       int i;\r
+       if\r
+       (\r
+               (!gotit)\r
+       ||      ((nt == ctrl_Joystick1) && !gvar->in.JoysPresent[0])\r
+       ||      ((nt == ctrl_Joystick2) && !gvar->in.JoysPresent[1])\r
+       ||      ((nt == ctrl_Mouse) && !gvar->in.MousePresent)\r
+       )\r
+               nt = ctrl_Keyboard1;\r
+       gvar->in.KbdDefs[0].button0 = 0x1c;\r
+       gvar->in.KbdDefs[0].button1 = 0x38;\r
+       //in.KbdDefs[0].upleft = 0x47;\r
+       gvar->in.KbdDefs[0].up = 0x48;\r
+       //in.KbdDefs[0].upright = 0x49;\r
+       gvar->in.KbdDefs[0].left = 0x4b;\r
+       gvar->in.KbdDefs[0].right = 0x4d;\r
+       //in.KbdDefs[0].downleft = 0x4f;\r
+       gvar->in.KbdDefs[0].down = 0x50;\r
+       //in.KbdDefs[0].downright = 0x51;\r
+       IN_SetControlType(player,nt);\r
+       for(i=0; i>MaxPlayers;i++)\r
+               player[i].enti.d =2;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_Shutdown() - Shuts down the Input Mgr\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_Shutdown(global_game_variables_t *gvar)\r
+{\r
+       word    i;\r
+\r
+       if (!gvar->in.IN_Started)\r
+               return;\r
+\r
+       INL_ShutMouse();\r
+       for (i = 0;i < MaxJoys;i++)\r
+               INL_ShutJoy(i, gvar);\r
+       INL_ShutKbd();\r
+\r
+       gvar->in.IN_Started = false;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()\r
+//                     everytime a real make/break code gets hit\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_SetKeyHook(void (*hook)())\r
+{\r
+       INL_KeyHook = hook;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_ClearKeysDown() - Clears the keyboard array\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_ClearKeysDown(void)\r
+{\r
+       //int   i;\r
+\r
+       inst.LastScan = sc_None;\r
+       inst.LastASCII = key_None;\r
+       memset (inst.Keyboard,0,sizeof(inst.Keyboard));\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)\r
+{\r
+       if (buttons & (1 << 0))\r
+               info->button0 = true;\r
+       if (buttons & (1 << 1))\r
+               info->button1 = true;\r
+\r
+       info->x += dx;\r
+       info->y += dy;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_ReadCursor() - Reads the input devices and fills in the cursor info\r
+//             struct\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_ReadCursor(CursorInfo *info, global_game_variables_t *gvar)\r
+{\r
+       word    i,\r
+                       buttons;\r
+       int             dx,dy;\r
+\r
+       info->x = info->y = 0;\r
+       info->button0 = info->button1 = false;\r
+\r
+       if (gvar->in.MousePresent)\r
+       {\r
+               buttons = INL_GetMouseButtons();\r
+               INL_GetMouseDelta(&dx,&dy);\r
+               INL_AdjustCursor(info,buttons,dx,dy);\r
+       }\r
+\r
+       for (i = 0;i < MaxJoys;i++)\r
+       {\r
+               if (!gvar->in.JoysPresent[i])\r
+                       continue;\r
+\r
+               buttons = INL_GetJoyButtons(i);\r
+               INL_GetJoyDelta(i,&dx,&dy/*,true*/, gvar);\r
+               dx /= 64;\r
+               dy /= 64;\r
+               INL_AdjustCursor(info,buttons,dx,dy);\r
+       }\r
+}\r
+\r
+//if else for gfxtesting and direction\r
+#define DIRECTIONIFELSE        (player->info.dir == 2)\r
+//#define NDIRECTIONIFELSE     (player->info.dir != 2)\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_ReadControl() - Reads the device associated with the specified\r
+//             player and fills in the control info struct\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_ReadControl(player_t *player, global_game_variables_t *gvar)\r
+{\r
+                       boolean         realdelta;\r
+#if DEMO0\r
+                       byte            dbyte;\r
+#endif\r
+                       word            buttons;\r
+                       int                     dx,dy;\r
+                       Motion          mx,my;\r
+                       ControlType     type;\r
+                       sword conpee;\r
+                       byte dir=DirTable[2];\r
+register       KeyboardDef     *def;\r
+\r
+       dx = dy = 0;\r
+       mx = my = motion_None;\r
+       buttons = 0;\r
+\r
+#if DEMO0\r
+       if (DemoMode == demo_Playback)\r
+       {\r
+               dbyte = DemoBuffer[DemoOffset + 1];\r
+               my = (dbyte & 3) - 1;\r
+               mx = ((dbyte >> 2) & 3) - 1;\r
+               buttons = (dbyte >> 4) & 3;\r
+\r
+               if (!(--DemoBuffer[DemoOffset]))\r
+               {\r
+                       DemoOffset += 2;\r
+                       if (DemoOffset >= DemoSize)\r
+                               DemoMode = demo_PlayDone;\r
+               }\r
+\r
+               realdelta = false;\r
+       }\r
+       else if (DemoMode == demo_PlayDone)\r
+               Quit ("Demo playback exceeded");\r
+       else\r
+       {\r
+#endif\r
+               switch (type = player->Controls)\r
+               {\r
+               case ctrl_Keyboard1:\r
+               case ctrl_Keyboard2:\r
+                       def = &(gvar->in.KbdDefs[type - ctrl_Keyboard]);\r
+\r
+/*                     if (Keyboard[def->upleft])\r
+                               mx = motion_Left,my = motion_Up;\r
+                       else if (Keyboard[def->upright])\r
+                               mx = motion_Right,my = motion_Up;\r
+                       else if (Keyboard[def->downleft])\r
+                               mx = motion_Left,my = motion_Down;\r
+                       else if (Keyboard[def->downright])\r
+                               mx = motion_Right,my = motion_Down;*/\r
+//TODO: make this into a function that the joystick AND keyboard can use wwww\r
+                       if(DIRECTIONIFELSE)//(player->info.dir == 2)\r
+                       {\r
+                       if(!inst.Keyboard[def->left] && !inst.Keyboard[def->right]){\r
+                               if((inst.Keyboard[def->up] && !inst.Keyboard[def->down]))\r
+                                       my = motion_Up;\r
+                               if((inst.Keyboard[def->down] && !inst.Keyboard[def->up]))\r
+                                       my = motion_Down;\r
+                       }else if(!inst.Keyboard[def->up] && !inst.Keyboard[def->down]){\r
+                               if((inst.Keyboard[def->left] && !inst.Keyboard[def->right]))\r
+                                       mx = motion_Left;\r
+                               if((inst.Keyboard[def->right] && !inst.Keyboard[def->left]))\r
+                                       mx = motion_Right;\r
+                       }else{  //2 keys pressed\r
+                                       switch (player->pdir)\r
+                                       {\r
+                                               case 0:\r
+                                               case 4:\r
+                                                       if((inst.Keyboard[def->left] && !inst.Keyboard[def->right])){ dir = DirTable[1]; }//mx = motion_Left; }\r
+                                                       else if((inst.Keyboard[def->right] && !inst.Keyboard[def->left])){ dir = DirTable[3]; }//mx = motion_Right; }\r
+                                               break;\r
+                                               case 1:\r
+                                               case 3:\r
+                                                       if((inst.Keyboard[def->up] && !inst.Keyboard[def->down])){ dir = DirTable[0]; }//my = motion_Up; }\r
+                                                       else if((inst.Keyboard[def->down] && !inst.Keyboard[def->up])){ dir = DirTable[4]; }//my = motion_Down; }\r
+                                               break;\r
+                                               default:\r
+                                               break;\r
+                                       }\r
+#ifdef __DEBUG_InputMgr__\r
+                                       //if(dbg_testcontrolnoisy > 0){ printf("dir=%c ", dirchar(dir)); printf("pdir=%c        ", dirchar(player->pdir)); }\r
+#endif\r
+                               }\r
+                       }\r
+                       //input from player\r
+                       if (inst.Keyboard[def->button0])\r
+                               buttons += 1 << 0;\r
+                       if (inst.Keyboard[def->button1])\r
+                               buttons += 1 << 1;\r
+                       realdelta = false;\r
+                       break;\r
+               case ctrl_Joystick1:\r
+               case ctrl_Joystick2:\r
+                       INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy/*,false*/, gvar);\r
+                       buttons = INL_GetJoyButtons(type - ctrl_Joystick);\r
+                       realdelta = true;\r
+                       break;\r
+               case ctrl_Mouse:\r
+                       INL_GetMouseDelta(&dx,&dy);\r
+                       buttons = INL_GetMouseButtons();\r
+                       realdelta = true;\r
+                       break;\r
+               }\r
+#ifdef DEMO0\r
+       }\r
+#endif\r
+\r
+       if (realdelta)\r
+       {\r
+               mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);\r
+               my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);\r
+       }\r
+       else\r
+       {\r
+               dx = mx;// * 127;\r
+               dy = my;// * 127;\r
+       }\r
+\r
+       player->info.x = dx;\r
+       player->info.xaxis = mx;\r
+       player->info.y = dy;\r
+       player->info.yaxis = my;\r
+       player->info.button0 = buttons & (1 << 0);\r
+       player->info.button1 = buttons & (1 << 1);\r
+       player->info.button2 = buttons & (1 << 2);\r
+       player->info.button3 = buttons & (1 << 3);\r
+//     player->info.dir = DirTable[((my + 1) * 3) + (mx + 1)];\r
+       conpee=(((my + 1) * 2) + (mx + 1))-1;\r
+       player->info.dir = DirTable[conpee];\r
+\r
+       if(DirTable[conpee]!=2) player->pdir=DirTable[conpee];\r
+       if(player->enti.q==1 &&( dir!=2 || (mx!=motion_None || my!=motion_None)))\r
+       {\r
+               if(dir==2) player->enti.d = player->info.dir;\r
+               else player->enti.d = DirTable[dir];\r
+       }\r
+\r
+#if DEMO0\r
+       if (DemoMode == demo_Record)\r
+       {\r
+               // Pack the control info into a byte\r
+               dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);\r
+\r
+               if\r
+               (\r
+                       (DemoBuffer[DemoOffset + 1] == dbyte)\r
+               &&      (DemoBuffer[DemoOffset] < 255)\r
+               )\r
+                       (DemoBuffer[DemoOffset])++;\r
+               else\r
+               {\r
+                       if (DemoOffset || DemoBuffer[DemoOffset])\r
+                               DemoOffset += 2;\r
+\r
+                       if (DemoOffset >= DemoSize)\r
+                               Quit ("Demo buffer overflow");\r
+\r
+                       DemoBuffer[DemoOffset] = 1;\r
+                       DemoBuffer[DemoOffset + 1] = dbyte;\r
+               }\r
+       }\r
+#endif\r
+#ifdef __DEBUG_InputMgr__\r
+if(dbg_testcontrolnoisy > 0)\r
+if(player->info.dir!=2/*(inst.Keyboard[def->up] || inst.Keyboard[def->down] || inst.Keyboard[def->left] || inst.Keyboard[def->right])*/ || player->enti.q>1)\r
+{\r
+       //printf("b1=%u b2=%u b3=%u b4=%u       ", player->info.button0, player->info.button1, player->info.button2, player->info.button3);\r
+       //printf("q=%d ", player->enti.q);\r
+       //printf("cpee=%c ", dirchar(conpee));\r
+       printf("pdir=%c d=%c dir=%c ", dirchar(player->pdir), dirchar(player->enti.d), dirchar(player->info.dir));\r
+       /*if(realdelta) */printf("dx=%d dy=%d   mx=%d   my=%d", player->info.x, player->info.y, player->info.xaxis, player->info.yaxis);\r
+       //else if(!realdelta) printf("%c%d %c%d %c%d %c%d", dirchar(0), inst.Keyboard[def->up], dirchar(4), inst.Keyboard[def->down], dirchar(1), inst.Keyboard[def->left], dirchar(3), inst.Keyboard[def->right]);\r
+       printf("\n");\r
+}\r
+#endif\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_SetControlType() - Sets the control type to be used by the specified\r
+//             player\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_SetControlType(player_t *player,ControlType type)\r
+{\r
+       // DEBUG - check that requested type is present?\r
+       player->Controls = type;\r
+}\r
+\r
+#if DEMO0\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_StartDemoRecord() - Starts the demo recording, using a buffer the\r
+//             size passed. Returns if the buffer allocation was successful\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+boolean\r
+IN_StartDemoRecord(word bufsize)\r
+{\r
+       if (!bufsize)\r
+               return(false);\r
+\r
+       MM_GetPtr((memptr *)&DemoBuffer,bufsize);\r
+       DemoMode = demo_Record;\r
+       DemoSize = bufsize & ~1;\r
+       DemoOffset = 0;\r
+       DemoBuffer[0] = DemoBuffer[1] = 0;\r
+\r
+       return(true);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_StartDemoPlayback() - Plays back the demo pointed to of the given size\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_StartDemoPlayback(byte /*__segment*/ *buffer,word bufsize)\r
+{\r
+       DemoBuffer = buffer;\r
+       DemoMode = demo_Playback;\r
+       DemoSize = bufsize & ~1;\r
+       DemoOffset = 0;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_StopDemo() - Turns off demo mode\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_StopDemo(void)\r
+{\r
+       if ((DemoMode == demo_Record) && DemoOffset)\r
+               DemoOffset += 2;\r
+\r
+       DemoMode = demo_Off;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+IN_FreeDemoBuffer(void)\r
+{\r
+       if (DemoBuffer)\r
+               MM_FreePtr((memptr *)&DemoBuffer);\r
+}\r
+#endif\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_GetScanName() - Returns a string containing the name of the\r
+//             specified scan code\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+byte *\r
+IN_GetScanName(ScanCode scan)\r
+{\r
+       byte            **p;\r
+       ScanCode        far *s;\r
+\r
+       for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)\r
+               if (*s == scan)\r
+                       return(*p);\r
+\r
+       return(ScanNames[scan]);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_WaitForKey() - Waits for a scan code, then clears LastScan and\r
+//             returns the scan code\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+ScanCode\r
+IN_WaitForKey(void)\r
+{\r
+       ScanCode        result;\r
+\r
+       while (!(result = inst.LastScan))\r
+               ;\r
+       inst.LastScan = 0;\r
+       return(result);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and\r
+//             returns the ASCII value\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+char\r
+IN_WaitForASCII(void)\r
+{\r
+       char            result;\r
+\r
+       while (!(result = inst.LastASCII))\r
+               ;\r
+       inst.LastASCII = '\0';\r
+       return(result);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_Ack() - waits for a button or key press.  If a button is down, upon\r
+// calling, it must be released for it to be recognized\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+\r
+boolean        btnstate[8];\r
+\r
+void IN_StartAck(global_game_variables_t *gvar)\r
+{\r
+       unsigned        i,buttons;\r
+\r
+//\r
+// get initial state of everything\r
+//\r
+       IN_ClearKeysDown();\r
+       memset (btnstate,0,sizeof(btnstate));\r
+\r
+       buttons = IN_JoyButtons () << 4;\r
+       if (gvar->in.MousePresent)\r
+               buttons |= IN_MouseButtons (gvar);\r
+\r
+       for (i=0;i<8;i++,buttons>>=1)\r
+               if (buttons&1)\r
+                       btnstate[i] = true;\r
+}\r
+\r
+\r
+boolean IN_CheckAck (global_game_variables_t *gvar)\r
+{\r
+       unsigned        i,buttons;\r
+\r
+//\r
+// see if something has been pressed\r
+//\r
+       if (inst.LastScan)\r
+               return true;\r
+\r
+       buttons = IN_JoyButtons () << 4;\r
+       if (gvar->in.MousePresent)\r
+               buttons |= IN_MouseButtons (gvar);\r
+\r
+       for (i=0;i<8;i++,buttons>>=1)\r
+               if ( buttons&1 )\r
+               {\r
+                       if (!btnstate[i])\r
+                               return true;\r
+               }\r
+               else\r
+                       btnstate[i]=false;\r
+\r
+       return false;\r
+}\r
+\r
+\r
+void IN_Ack (global_game_variables_t *gvar)\r
+{\r
+       IN_StartAck (gvar);\r
+\r
+       while (!IN_CheckAck (gvar))\r
+       ;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_IsUserInput() - Returns true if a key has been pressed or a button\r
+//             is down\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+boolean\r
+IN_IsUserInput(global_game_variables_t *gvar)\r
+{\r
+       boolean result;\r
+       word    i;\r
+\r
+       result = inst.LastScan;\r
+\r
+       if (gvar->in.MousePresent)\r
+               if (INL_GetMouseButtons())\r
+                       result = true;\r
+\r
+       for (i = 0;i < MaxJoys;i++)\r
+               if (gvar->in.JoysPresent[i])\r
+                       if (INL_GetJoyButtons(i))\r
+                               result = true;\r
+\r
+       return(result);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     IN_UserInput() - Waits for the specified delay time (in ticks) or the\r
+//             user pressing a key or a mouse button. If the clear flag is set, it\r
+//             then either clears the key or waits for the user to let the mouse\r
+//             button up.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+boolean IN_UserInput(word delay, global_game_variables_t *gvar)\r
+{\r
+       word TimeCount = *clockw;\r
+       word    lasttime;\r
+\r
+       lasttime = TimeCount;\r
+       IN_StartAck (gvar);\r
+       do\r
+       {\r
+               if (IN_CheckAck(gvar))\r
+                       return true;\r
+       } while (TimeCount - lasttime < delay);\r
+       return(false);\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= IN_MouseButtons\r
+=\r
+===================\r
+*/\r
+\r
+byte   IN_MouseButtons (global_game_variables_t *gvar)\r
+{\r
+       union REGS CPURegs;\r
+       if (gvar->in.MousePresent)\r
+       {\r
+               Mouse(MButtons);\r
+               return CPURegs.x.bx;\r
+       }\r
+       else\r
+               return 0;\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= IN_JoyButtons\r
+=\r
+===================\r
+*/\r
+\r
+byte   IN_JoyButtons (void)\r
+{\r
+       byte joybits;\r
+\r
+       joybits = inportb(0x201);       // Get all the joystick buttons\r
+       joybits >>= 4;                          // only the high bits are useful\r
+       joybits ^= 15;                          // return with 1=pressed\r
+\r
+       return joybits;\r
+}\r
+\r
+boolean IN_KeyDown(byte code)\r
+{\r
+#ifdef __DEBUG_InputMgr__\r
+       if(inst.Keyboard[code])\r
+               printf("IN_KeyDown(%c): %u\n", code, inst.Keyboard[code]);\r
+       if(!dbg_nointest)\r
+#endif\r
+       return inst.Keyboard[code];\r
+#ifdef __DEBUG_InputMgr__\r
+       else\r
+               if(dbg_nointest && kbhit())\r
+                       return 1;\r
+               else\r
+                       return 0;\r
+#endif\r
+}\r
+\r
+void IN_ClearKey(byte code)\r
+{\r
+       inst.Keyboard[code] = false;\r
+       if(code == inst.LastScan)\r
+               inst.LastScan = sc_None;\r
+       }\r
+\r
+boolean IN_qb(byte kee)\r
+{\r
+#ifdef __DEBUG_InputMgr__\r
+       if(dbg_testkeyin) if(inst.Keyboard[kee]) printf("IN_qb():       %u\n", inst.Keyboard[kee]);\r
+#endif\r
+       if(inst.Keyboard[kee]==true) return 1;\r
+       else return 0;\r
+}\r
+\r
+ScanCode IN_GetLastScan()\r
+{\r
+       return inst.LastScan;\r
+}\r
+\r
+ScanCode IN_GetCurCode()\r
+{\r
+       return inst.CurCode;\r
+}\r
+\r
+void IN_KbdLED()\r
+{\r
+       byte far *lock_key;\r
+\r
+       // turn off num-lock via BIOS\r
+       lock_key = MK_FP(0x040, 0x017); // Pointing to the address of the bios shift state keys\r
+       *lock_key&=(~(16 | 32 | 64)); // toggle off the locks by changing the values of the 4th, 5th, and 6th bits of the address byte of 0040:0017\r
+       OldKeyVect();   // call BIOS keyhandler to change keyboard lights\r
+}\r