-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program 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
- * (at your option) any later version.\r
- *\r
- * This program 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
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_IN.c - Input Manager\r
-// v1.0d1\r
-// By Jason Blochowiak\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 "ID_HEADS.H"\r
-#include "16_in.h"\r
-//#pragma hdrstop\r
-\r
-#define KeyInt 9 // The keyboard ISR number\r
-\r
-// Stuff for the joystick\r
-#define JoyScaleMax 32768\r
-#define JoyScaleShift 8\r
-#define MaxJoyValue 5000\r
-\r
-// Global variables\r
- boolean JoystickCalibrated=false; // MDM (GAMERS EDGE) - added\r
- ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added\r
-\r
- boolean Keyboard[NumCodes],\r
- JoysPresent[MaxJoys],\r
- MousePresent;\r
- boolean Paused;\r
- char LastASCII;\r
- ScanCode LastScan;\r
- KeyboardDef KbdDefs[MaxKbds] = {{0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}};\r
- JoystickDef JoyDefs[MaxJoys];\r
- ControlType Controls[MaxPlayers];\r
-\r
-// Demo DemoMode = demo_Off;\r
-// byte /*_1seg*/ *DemoBuffer;\r
-// word DemoOffset,DemoSize;\r
-\r
-// Internal variables\r
-static boolean IN_Started;\r
-static boolean CapsLock;\r
-static ScanCode CurCode,LastCode;\r
-static byte far ASCIINames[] = // Unshifted ASCII for scan codes\r
- {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
- 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0\r
- 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1\r
- 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2\r
- 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4\r
- '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- },\r
- far ShiftNames[] = // Shifted ASCII for scan codes\r
- {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
- 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0\r
- 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1\r
- 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2\r
- 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4\r
- '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- },\r
- far SpecialNames[] = // ASCII for 0xe0 prefixed codes\r
- {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2\r
- 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- },\r
-\r
-#if 0\r
- *ScanNames[] = // Scan code names with single chars\r
- {\r
- "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",\r
- "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",\r
- "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",\r
- "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",\r
- "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",\r
- "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
- "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
- "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"\r
- }, // DEBUG - consolidate these\r
-#endif\r
-\r
- far ExtScanCodes[] = // Scan codes with >1 char names\r
- {\r
- 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,\r
- 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,\r
- 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,\r
- 0x50,0x4b,0x4d,0x00\r
- };\r
-#if 0\r
- *ExtScanNames[] = // Names corresponding to ExtScanCodes\r
- {\r
- "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",\r
- "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
-#endif\r
-static Direction DirTable[] = // Quick lookup for total direction\r
- {\r
- dir_NorthWest, dir_North, dir_NorthEast,\r
- dir_West, dir_None, dir_East,\r
- dir_SouthWest, dir_South, dir_SouthEast\r
- };\r
-\r
-static void (*INL_KeyHook)(void);\r
-static void interrupt (*OldKeyVect)(void);\r
-\r
-static char *ParmStrings[] = {"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 = inp(0x60); // Get the scan code\r
-\r
- // Tell the XT keyboard controller to clear the key\r
- outp(0x61,(temp = inp(0x61)) | 0x80);\r
- outp(0x61,temp);\r
-\r
- if (k == 0xe0) // Special key prefix\r
- special = true;\r
- else if (k == 0xe1) // Handle Pause key\r
- 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
- Keyboard[k] = false;\r
- }\r
- else // Make code\r
- {\r
- LastCode = CurCode;\r
- CurCode = LastScan = k;\r
- Keyboard[k] = true;\r
-\r
- if (special)\r
- c = SpecialNames[k];\r
- else\r
- {\r
- if (k == sc_CapsLock)\r
- {\r
- CapsLock ^= true;\r
- // DEBUG - make caps lock light work\r
- }\r
-\r
- if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted\r
- {\r
- c = ShiftNames[k];\r
- if ((c >= 'A') && (c <= 'Z') && CapsLock)\r
- c += 'a' - 'A';\r
- }\r
- else\r
- {\r
- c = ASCIINames[k];\r
- if ((c >= 'a') && (c <= 'z') && CapsLock)\r
- c -= 'a' - 'A';\r
- }\r
- }\r
- if (c)\r
- LastASCII = c;\r
- }\r
-\r
- special = false;\r
- }\r
-\r
- if (INL_KeyHook && !special)\r
- INL_KeyHook();\r
- outp(0x20,0x20);\r
-}\r
-\r
-static void\r
-Mouse(int x)\r
-{\r
- x = CPURegs.x.ax;\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
- 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
- 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
- {\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
-\r
-loop:\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 loop // If both bits were 0, drop out\r
-\r
-done:\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, scaled adaptively)\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_GetJoyDelta(word joy,int *dx,int *dy,boolean adaptive)\r
-{\r
- word x,y;\r
- dword time;\r
- JoystickDef *def;\r
-static dword lasttime;\r
-\r
- IN_GetJoyAbs(joy,&x,&y);\r
- def = 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
-\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 = inp(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
- dword 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(void)\r
-{\r
- INL_KeyHook = 0; // Clear key hook\r
-\r
- IN_ClearKeysDown();\r
-\r
- OldKeyVect = _dos_getvect(KeyInt);\r
- _dos_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
- poke(0x40,0x17,peek(0x40,0x17) & 0xfaf0); // Clear ctrl/alt/shift flags\r
-\r
- _dos_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(_dos_getvect(MouseInt))\r
- {\r
- Mouse(MReset);\r
- if(CPURegs.x.ax == 0xffff)\r
- return(true);\r
- }\r
- return(false);\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)\r
-{\r
- JoystickDef *def;\r
-\r
- def = &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)\r
-{\r
- word d,r;\r
- JoystickDef *def;\r
-\r
- def = &JoyDefs[joy];\r
-\r
- def->joyMinX = minx;\r
- def->joyMaxX = maxx;\r
- r = maxx - minx;\r
- d = r / 5;\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 / 5;\r
- def->threshMinY = ((r / 2) - d) + miny;\r
- def->threshMaxY = ((r / 2) + d) + miny;\r
-\r
- INL_SetJoyScale(joy);\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)\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);\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)\r
-{\r
- 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(void)\r
-{\r
- boolean checkjoys,checkmouse;\r
- word i;\r
-\r
- if (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],ParmStrings))\r
- {\r
- case 0:\r
- checkjoys = false;\r
- break;\r
- case 1:\r
- checkmouse = false;\r
- break;\r
- }\r
- }\r
-\r
- INL_StartKbd();\r
- MousePresent = checkmouse? INL_StartMouse() : false;\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;\r
-\r
- IN_Started = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Default() - Sets up default conditions for the Input Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Default(boolean gotit,ControlType in)\r
-{\r
- if\r
- (\r
- (!gotit)\r
- || ((in == ctrl_Joystick1) && !JoysPresent[0])\r
- || ((in == ctrl_Joystick2) && !JoysPresent[1])\r
- || ((in == ctrl_Mouse) && !MousePresent)\r
- )\r
- in = ctrl_Keyboard1;\r
- IN_SetControlType(0,in);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Shutdown() - Shuts down the Input Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Shutdown(void)\r
-{\r
- word i;\r
-\r
- if (!IN_Started)\r
- return;\r
-\r
- INL_ShutMouse();\r
- for (i = 0;i < MaxJoys;i++)\r
- INL_ShutJoy(i);\r
- INL_ShutKbd();\r
-\r
- 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_ClearKeyDown() - Clears the keyboard array\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_ClearKeysDown(void)\r
-{\r
- int i;\r
-\r
- LastScan = sc_None;\r
- LastASCII = key_None;\r
- for (i = 0;i < NumCodes;i++)\r
- Keyboard[i] = false;\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)\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 (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 (!JoysPresent[i])\r
- continue;\r
-\r
- buttons = INL_GetJoyButtons(i);\r
- INL_GetJoyDelta(i,&dx,&dy,true);\r
- dx /= 64;\r
- dy /= 64;\r
- INL_AdjustCursor(info,buttons,dx,dy);\r
- }\r
-}\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(int player,ControlInfo *info)\r
-{\r
- boolean realdelta=false; // MDM (GAMERS EDGE)\r
- byte dbyte;\r
- word buttons;\r
- int dx,dy;\r
- Motion mx,my;\r
- ControlType type;\r
-register KeyboardDef *def;\r
-\r
- dx = dy = 0;\r
- mx = my = motion_None;\r
- buttons = 0;\r
-\r
-#if 0\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
-#endif\r
- {\r
- // MDM begin (GAMERS EDGE) - added this block\r
- ControlTypeUsed = ctrl_None;\r
-\r
- // Handle mouse input...\r
- //\r
- if ((MousePresent) && (ControlTypeUsed == ctrl_None))\r
- {\r
- INL_GetMouseDelta(&dx,&dy);\r
- buttons = INL_GetMouseButtons();\r
- realdelta = true;\r
- if (dx || dy || buttons)\r
- ControlTypeUsed = ctrl_Mouse;\r
- }\r
-\r
- // Handle joystick input...\r
- //\r
- if ((JoystickCalibrated) && (ControlTypeUsed == ctrl_None))\r
- {\r
- type = ctrl_Joystick1;\r
- INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);\r
- buttons = INL_GetJoyButtons(type - ctrl_Joystick);\r
- realdelta = true;\r
- if (dx || dy || buttons)\r
- ControlTypeUsed = ctrl_Joystick;\r
- }\r
-\r
- // Handle keyboard input...\r
- //\r
- if (ControlTypeUsed == ctrl_None)\r
- {\r
- type = ctrl_Keyboard1;\r
- def = &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
-\r
- if (Keyboard[def->up])\r
- my = motion_Up;\r
- else if (Keyboard[def->down])\r
- my = motion_Down;\r
-\r
- if (Keyboard[def->left])\r
- mx = motion_Left;\r
- else if (Keyboard[def->right])\r
- mx = motion_Right;\r
-\r
- if (Keyboard[def->button0])\r
- buttons += 1 << 0;\r
- if (Keyboard[def->button1])\r
- buttons += 1 << 1;\r
- realdelta = false;\r
- if (mx || my || buttons)\r
- ControlTypeUsed = ctrl_Keyboard;\r
- } // MDM end (GAMERS EDGE)\r
- }\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
- info->x = dx;\r
- info->xaxis = mx;\r
- info->y = dy;\r
- info->yaxis = my;\r
- info->button0 = buttons & (1 << 0);\r
- info->button1 = buttons & (1 << 1);\r
- info->dir = DirTable[((my + 1) * 3) + (mx + 1)];\r
-\r
-#if 0\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
-}\r
-\r
-#if 0\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(int player,ControlInfo *info)\r
-{\r
- boolean realdelta;\r
- byte dbyte;\r
- word buttons;\r
- int dx,dy;\r
- Motion mx,my;\r
- ControlType type;\r
-register KeyboardDef *def;\r
-\r
- dx = dy = 0;\r
- mx = my = motion_None;\r
- buttons = 0;\r
-\r
-#if 0\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
-#endif\r
- {\r
- switch (type = Controls[player])\r
- {\r
- case ctrl_Keyboard1:\r
- case ctrl_Keyboard2:\r
- def = &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
-\r
- if (Keyboard[def->up])\r
- my = motion_Up;\r
- else if (Keyboard[def->down])\r
- my = motion_Down;\r
-\r
- if (Keyboard[def->left])\r
- mx = motion_Left;\r
- else if (Keyboard[def->right])\r
- mx = motion_Right;\r
-\r
- if (Keyboard[def->button0])\r
- buttons += 1 << 0;\r
- if (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);\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
- }\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
- info->x = dx;\r
- info->xaxis = mx;\r
- info->y = dy;\r
- info->yaxis = my;\r
- info->button0 = buttons & (1 << 0);\r
- info->button1 = buttons & (1 << 1);\r
- info->dir = DirTable[((my + 1) * 3) + (mx + 1)];\r
-\r
-#if 0\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
-}\r
-#endif\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(int player,ControlType type)\r
-{\r
- // DEBUG - check that requested type is present?\r
- Controls[player] = type;\r
-}\r
-\r
-#if 0\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 /*_1seg*/ *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
-#if 0\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
-#endif\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 = LastScan))\r
- ;\r
- 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 = LastASCII))\r
- ;\r
- LastASCII = '\0';\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_AckBack() - Waits for either an ASCII keypress or a button press\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_AckBack(void)\r
-{\r
- word i;\r
-\r
- while (!LastScan)\r
- {\r
- if (MousePresent)\r
- {\r
- if (INL_GetMouseButtons())\r
- {\r
- while (INL_GetMouseButtons())\r
- ;\r
- return;\r
- }\r
- }\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- {\r
- if (JoysPresent[i])\r
- {\r
- if (IN_GetJoyButtonsDB(i))\r
- {\r
- while (IN_GetJoyButtonsDB(i))\r
- ;\r
- return;\r
- }\r
- }\r
- }\r
- }\r
-\r
- IN_ClearKey(LastScan);\r
- LastScan = sc_None;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Ack() - Clears user input & then calls IN_AckBack()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Ack(void)\r
-{\r
- word i;\r
-\r
- IN_ClearKey(LastScan);\r
- LastScan = sc_None;\r
-\r
- if (MousePresent)\r
- while (INL_GetMouseButtons())\r
- ;\r
- for (i = 0;i < MaxJoys;i++)\r
- if (JoysPresent[i])\r
- while (IN_GetJoyButtonsDB(i))\r
- ;\r
-\r
- IN_AckBack();\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(void)\r
-{\r
- boolean result;\r
- word i;\r
-\r
- result = LastScan;\r
-\r
- if (MousePresent)\r
- if (INL_GetMouseButtons())\r
- result = true;\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- if (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\r
-IN_UserInput(dword delay,boolean clear)\r
-{\r
- dword lasttime;\r
-\r
- lasttime = TimeCount;\r
- do\r
- {\r
- if (IN_IsUserInput())\r
- {\r
- if (clear)\r
- IN_AckBack();\r
- return(true);\r
- }\r
- } while (TimeCount - lasttime < delay);\r
- return(false);\r
-}\r
+/* Catacomb Armageddon Source Code
+ * Copyright (C) 1993-2014 Flat Rock Software
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+//
+// ID Engine
+// ID_IN.c - Input Manager
+// v1.0d1
+// By Jason Blochowiak
+//
+
+//
+// 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 "16_in.h"
+
+// Global variables
+ boolean JoystickCalibrated=false; // MDM (GAMERS EDGE) - added
+ ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added
+
+ boolean Keyboard[NumCodes],
+ JoysPresent[MaxJoys],
+ MousePresent;
+ boolean Paused;
+ char LastASCII;
+ ScanCode LastScan;
+ KeyboardDef KbdDefs[MaxKbds] = {{0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}};
+ JoystickDef JoyDefs[MaxJoys];
+ ControlType Controls[MaxPlayers];
+
+#ifdef DEMO0
+ Demo DemoMode = demo_Off;\r
+ byte __segment *DemoBuffer;\r
+ word DemoOffset,DemoSize;
+#endif
+
+// Internal variables
+static boolean IN_Started;
+static boolean CapsLock;
+static ScanCode CurCode,LastCode;
+static byte far ASCIINames[] = // Unshifted ASCII for scan codes
+ {
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0
+ 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1
+ 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2
+ 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
+ '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
+ },
+ far ShiftNames[] = // Shifted ASCII for scan codes
+ {
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0
+ 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1
+ 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2
+ 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
+ '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
+ },
+ far SpecialNames[] = // ASCII for 0xe0 prefixed codes
+ {
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2
+ 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
+ },
+
+#if 0
+ *ScanNames[] = // Scan code names with single chars
+ {
+ "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",
+ "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",
+ "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",
+ "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",
+ "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",
+ "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"
+ }, // DEBUG - consolidate these
+#endif
+
+ far ExtScanCodes[] = // Scan codes with >1 char names
+ {
+ 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,
+ 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,
+ 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,
+ 0x50,0x4b,0x4d,0x00
+ };
+#if 0
+ *ExtScanNames[] = // Names corresponding to ExtScanCodes
+ {
+ "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",
+ "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",
+ "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",
+ "Down","Left","Right",""
+ };
+#endif
+static Direction DirTable[] = // Quick lookup for total direction
+ {
+ dir_NorthWest, dir_North, dir_NorthEast,
+ dir_West, dir_None, dir_East,
+ dir_SouthWest, dir_South, dir_SouthEast
+ };
+
+static void (*INL_KeyHook)(void);
+static void interrupt (*OldKeyVect)(void);
+
+static char *ParmStrings[] = {"nojoys","nomouse",nil};
+
+// Internal routines
+
+///////////////////////////////////////////////////////////////////////////
+//
+// INL_KeyService() - Handles a keyboard interrupt (key up/down)
+//
+///////////////////////////////////////////////////////////////////////////
+static void interrupt
+INL_KeyService(void)
+{
+static boolean special;
+ byte k,c,
+ 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
+ Paused = true;
+ else
+ {
+ if (k & 0x80) // Break code
+ {
+ k &= 0x7f;
+
+// DEBUG - handle special keys: ctl-alt-delete, print scrn
+
+ Keyboard[k] = false;
+ }
+ else // Make code
+ {
+ LastCode = CurCode;
+ CurCode = LastScan = k;
+ Keyboard[k] = true;
+
+ if (special)
+ c = SpecialNames[k];
+ else
+ {
+ if (k == sc_CapsLock)
+ {
+ CapsLock ^= true;
+ // DEBUG - make caps lock light work
+ }
+
+ if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted
+ {
+ c = ShiftNames[k];
+ if ((c >= 'A') && (c <= 'Z') && CapsLock)
+ c += 'a' - 'A';
+ }
+ else
+ {
+ c = ASCIINames[k];
+ if ((c >= 'a') && (c <= 'z') && CapsLock)
+ c -= 'a' - 'A';
+ }
+ }
+ if (c)
+ LastASCII = c;
+ }
+
+ special = false;
+ }
+
+ if (INL_KeyHook && !special)
+ INL_KeyHook();
+ outp(0x20,0x20);
+}
+
+static 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 = 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(void)
+{
+ 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 = &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 = &JoyDefs[joy];
+
+ def->joyMinX = minx;
+ def->joyMaxX = maxx;
+ r = maxx - minx;
+ d = r / 5;
+ def->threshMinX = ((r / 2) - d) + minx;
+ def->threshMaxX = ((r / 2) + d) + minx;
+
+ def->joyMinY = miny;
+ def->joyMaxY = maxy;
+ r = maxy - miny;
+ d = r / 5;
+ 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)
+{
+ JoysPresent[joy] = false;
+}
+
+// Public routines
+
+///////////////////////////////////////////////////////////////////////////
+//
+// IN_Startup() - Starts up the Input Mgr
+//
+///////////////////////////////////////////////////////////////////////////
+void
+IN_Startup(void)
+{
+ boolean checkjoys,checkmouse;
+ word i;
+
+ if (IN_Started)
+ return;
+
+ checkjoys = true;
+ checkmouse = true;
+ for (i = 1;i < __argc;i++)
+ {
+ switch (US_CheckParm(__argv[i],ParmStrings))
+ {
+ case 0:
+ checkjoys = false;
+ break;
+ case 1:
+ checkmouse = false;
+ break;
+ }
+ }
+
+ INL_StartKbd();
+ MousePresent = checkmouse? INL_StartMouse() : false;
+
+ for (i = 0;i < MaxJoys;i++)
+ JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;
+
+ IN_Started = true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// IN_Default() - Sets up default conditions for the Input Mgr
+//
+///////////////////////////////////////////////////////////////////////////
+void
+IN_Default(boolean gotit,ControlType in)
+{
+ if
+ (
+ (!gotit)
+ || ((in == ctrl_Joystick1) && !JoysPresent[0])
+ || ((in == ctrl_Joystick2) && !JoysPresent[1])
+ || ((in == ctrl_Mouse) && !MousePresent)
+ )
+ in = ctrl_Keyboard1;
+ IN_SetControlType(0,in);
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// IN_Shutdown() - Shuts down the Input Mgr
+//
+///////////////////////////////////////////////////////////////////////////
+void
+IN_Shutdown(void)
+{
+ word i;
+
+ if (!IN_Started)
+ return;
+
+ INL_ShutMouse();
+ for (i = 0;i < MaxJoys;i++)
+ INL_ShutJoy(i);
+ INL_ShutKbd();
+
+ 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(void)
+{
+ int i;
+
+ LastScan = sc_None;
+ LastASCII = key_None;
+ for (i = 0;i < NumCodes;i++)
+ Keyboard[i] = false;
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// 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 (MousePresent)
+ {
+ buttons = INL_GetMouseButtons();
+ INL_GetMouseDelta(&dx,&dy);
+ INL_AdjustCursor(info,buttons,dx,dy);
+ }
+
+ for (i = 0;i < MaxJoys;i++)
+ {
+ if (!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 player,ControlInfo *info)
+{
+ boolean realdelta=false; // MDM (GAMERS EDGE)
+ 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
+ {
+ // MDM begin (GAMERS EDGE) - added this block
+ ControlTypeUsed = ctrl_None;
+
+ // Handle mouse input...
+ //
+ if ((MousePresent) && (ControlTypeUsed == ctrl_None))
+ {
+ INL_GetMouseDelta(&dx,&dy);
+ buttons = INL_GetMouseButtons();
+ realdelta = true;
+ if (dx || dy || buttons)
+ ControlTypeUsed = ctrl_Mouse;
+ }
+
+ // Handle joystick input...
+ //
+ if ((JoystickCalibrated) && (ControlTypeUsed == ctrl_None))
+ {
+ type = ctrl_Joystick1;
+ INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
+ buttons = INL_GetJoyButtons(type - ctrl_Joystick);
+ realdelta = true;
+ if (dx || dy || buttons)
+ ControlTypeUsed = ctrl_Joystick;
+ }
+
+ // Handle keyboard input...
+ //
+ if (ControlTypeUsed == ctrl_None)
+ {
+ type = ctrl_Keyboard1;
+ def = &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 (Keyboard[def->up])
+ my = motion_Up;
+ else if (Keyboard[def->down])
+ my = motion_Down;
+
+ if (Keyboard[def->left])
+ mx = motion_Left;
+ else if (Keyboard[def->right])
+ mx = motion_Right;
+
+ if (Keyboard[def->button0])
+ buttons += 1 << 0;
+ if (Keyboard[def->button1])
+ buttons += 1 << 1;
+ realdelta = false;
+ if (mx || my || buttons)
+ ControlTypeUsed = ctrl_Keyboard;
+ } // MDM end (GAMERS EDGE)
+ }
+
+ 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;
+ }
+
+ info->x = dx;
+ info->xaxis = mx;
+ info->y = dy;
+ info->yaxis = my;
+ info->button0 = buttons & (1 << 0);
+ info->button1 = buttons & (1 << 1);
+ 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
+}
+
+#if 0
+///////////////////////////////////////////////////////////////////////////
+//
+// IN_ReadControl() - Reads the device associated with the specified
+// player and fills in the control info struct
+//
+///////////////////////////////////////////////////////////////////////////
+void
+IN_ReadControl(int player,ControlInfo *info)
+{
+ 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 = Controls[player])
+ {
+ case ctrl_Keyboard1:
+ case ctrl_Keyboard2:
+ def = &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 (Keyboard[def->up])
+ my = motion_Up;
+ else if (Keyboard[def->down])
+ my = motion_Down;
+
+ if (Keyboard[def->left])
+ mx = motion_Left;
+ else if (Keyboard[def->right])
+ mx = motion_Right;
+
+ if (Keyboard[def->button0])
+ buttons += 1 << 0;
+ if (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;
+ }
+ }
+
+ 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;
+ }
+
+ info->x = dx;
+ info->xaxis = mx;
+ info->y = dy;
+ info->yaxis = my;
+ info->button0 = buttons & (1 << 0);
+ info->button1 = buttons & (1 << 1);
+ 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
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+//
+// IN_SetControlType() - Sets the control type to be used by the specified
+// player
+//
+///////////////////////////////////////////////////////////////////////////
+void
+IN_SetControlType(int player,ControlType type)
+{
+ // DEBUG - check that requested type is present?
+ Controls[player] = 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
+
+
+#if 0
+///////////////////////////////////////////////////////////////////////////
+//
+// 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]);
+}
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// IN_WaitForKey() - Waits for a scan code, then clears LastScan and
+// returns the scan code
+//
+///////////////////////////////////////////////////////////////////////////
+ScanCode
+IN_WaitForKey(void)
+{
+ ScanCode result;
+
+ while (!(result = LastScan))
+ ;
+ LastScan = 0;
+ return(result);
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
+// returns the ASCII value
+//
+///////////////////////////////////////////////////////////////////////////
+char
+IN_WaitForASCII(void)
+{
+ char result;
+
+ while (!(result = LastASCII))
+ ;
+ LastASCII = '\0';
+ return(result);
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// IN_AckBack() - Waits for either an ASCII keypress or a button press
+//
+///////////////////////////////////////////////////////////////////////////
+void
+IN_AckBack(void)
+{
+ word i;
+
+ while (!LastScan)
+ {
+ if (MousePresent)
+ {
+ if (INL_GetMouseButtons())
+ {
+ while (INL_GetMouseButtons())
+ ;
+ return;
+ }
+ }
+
+ for (i = 0;i < MaxJoys;i++)
+ {
+ if (JoysPresent[i])
+ {
+ if (IN_GetJoyButtonsDB(i))
+ {
+ while (IN_GetJoyButtonsDB(i))
+ ;
+ return;
+ }
+ }
+ }
+ }
+
+ IN_ClearKey(LastScan);
+ LastScan = sc_None;
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// IN_Ack() - Clears user input & then calls IN_AckBack()
+//
+///////////////////////////////////////////////////////////////////////////
+void
+IN_Ack(void)
+{
+ word i;
+
+ IN_ClearKey(LastScan);
+ LastScan = sc_None;
+
+ if (MousePresent)
+ while (INL_GetMouseButtons())
+ ;
+ for (i = 0;i < MaxJoys;i++)
+ if (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(void)
+{
+ boolean result;
+ word i;
+
+ result = LastScan;
+
+ if (MousePresent)
+ if (INL_GetMouseButtons())
+ result = true;
+
+ for (i = 0;i < MaxJoys;i++)
+ if (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);
+}