1 /* Catacomb Armageddon Source Code
2 * Copyright (C) 1993-2014 Flat Rock Software
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 // ID_IN.c - Input Manager
23 // By Jason Blochowiak
27 // This module handles dealing with the various input devices
29 // Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
30 // User Mgr (for command line parms)
33 // LastScan - The keyboard scan code of the last key pressed
34 // LastASCII - The ASCII value of the last key pressed
35 // DEBUG - there are more globals
41 boolean JoystickCalibrated=false; // MDM (GAMERS EDGE) - added
42 ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added
44 boolean Keyboard[NumCodes],
50 KeyboardDef KbdDefs[MaxKbds] = {{0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}};
51 JoystickDef JoyDefs[MaxJoys];
52 ControlType Controls[MaxPlayers];
55 Demo DemoMode = demo_Off;
\r
56 byte __segment *DemoBuffer;
\r
57 word DemoOffset,DemoSize;
61 static boolean IN_Started;
62 static boolean CapsLock;
63 static ScanCode CurCode,LastCode;
64 static byte far ASCIINames[] = // Unshifted ASCII for scan codes
66 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
67 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0
68 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1
69 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2
70 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
71 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
72 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
73 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
74 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
76 far ShiftNames[] = // Shifted ASCII for scan codes
78 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
79 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0
80 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1
81 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2
82 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
83 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
84 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
85 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
86 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
88 far SpecialNames[] = // ASCII for 0xe0 prefixed codes
90 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
91 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0
92 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1
93 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2
94 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3
95 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4
96 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
97 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
98 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
102 *ScanNames[] = // Scan code names with single chars
104 "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",
105 "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",
106 "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",
107 "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",
108 "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",
109 "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
110 "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
111 "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"
112 }, // DEBUG - consolidate these
115 far ExtScanCodes[] = // Scan codes with >1 char names
117 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,
118 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,
119 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,
123 *ExtScanNames[] = // Names corresponding to ExtScanCodes
125 "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",
126 "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",
127 "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",
128 "Down","Left","Right",""
131 static Direction DirTable[] = // Quick lookup for total direction
133 dir_NorthWest, dir_North, dir_NorthEast,
134 dir_West, dir_None, dir_East,
135 dir_SouthWest, dir_South, dir_SouthEast
138 static void (*INL_KeyHook)(void);
139 static void interrupt (*OldKeyVect)(void);
141 static char *ParmStrings[] = {"nojoys","nomouse",nil};
145 ///////////////////////////////////////////////////////////////////////////
147 // INL_KeyService() - Handles a keyboard interrupt (key up/down)
149 ///////////////////////////////////////////////////////////////////////////
150 static void interrupt
153 static boolean special;
157 k = inp(0x60); // Get the scan code
159 // Tell the XT keyboard controller to clear the key
160 outp(0x61,(temp = inp(0x61)) | 0x80);
163 if (k == 0xe0) // Special key prefix
165 else if (k == 0xe1) // Handle Pause key
169 if (k & 0x80) // Break code
173 // DEBUG - handle special keys: ctl-alt-delete, print scrn
180 CurCode = LastScan = k;
187 if (k == sc_CapsLock)
190 // DEBUG - make caps lock light work
193 if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted
196 if ((c >= 'A') && (c <= 'Z') && CapsLock)
202 if ((c >= 'a') && (c <= 'z') && CapsLock)
213 if (INL_KeyHook && !special)
223 int86(MouseInt,&CPURegs,&CPURegs);
226 ///////////////////////////////////////////////////////////////////////////
228 // INL_GetMouseDelta() - Gets the amount that the mouse has moved from the
231 ///////////////////////////////////////////////////////////////////////////
233 INL_GetMouseDelta(int *x,int *y)
241 ///////////////////////////////////////////////////////////////////////////
243 // INL_GetMouseButtons() - Gets the status of the mouse buttons from the
246 ///////////////////////////////////////////////////////////////////////////
248 INL_GetMouseButtons(void)
254 buttons = CPURegs.x.bx;
258 ///////////////////////////////////////////////////////////////////////////
260 // IN_GetJoyAbs() - Reads the absolute position of the specified joystick
262 ///////////////////////////////////////////////////////////////////////////
264 IN_GetJoyAbs(word joy,word *xp,word *yp)
271 xs = joy? 2 : 0; // Find shift value for x axis
272 xb = 1 << xs; // Use shift value to get x bit mask
273 ys = joy? 3 : 1; // Do the same for y axis
276 // Read the absolute joystick values
279 pushf // Save some registers
282 cli // Make sure an interrupt doesn't screw the timings
287 out dx,al // Clear the resistors
289 mov ah,[xb] // Get masks into registers
292 xor si,si // Clear count registers
294 xor bh,bh // Clear high byte of bx for later
296 push bp // Don't mess up stack frame
300 in al,dx // Get bits indicating whether all are finished
302 dec bp // Check bounding register
303 jz done // We have a silly value - abort
305 mov bl,al // Duplicate the bits
306 and bl,ah // Mask off useless bits (in [xb])
307 add si,bx // Possibly increment count register
308 mov cl,bl // Save for testing later
315 jnz loo // If both bits were 0, drop out
320 mov cl,[xs] // Get the number of bits to shift
321 shr si,cl // and shift the count that many times
326 mov [x],si // Store the values into the variables
331 popf // Restore the registers
338 ///////////////////////////////////////////////////////////////////////////
340 // INL_GetJoyDelta() - Returns the relative movement of the specified
341 // joystick (from +/-127, scaled adaptively)
343 ///////////////////////////////////////////////////////////////////////////
345 INL_GetJoyDelta(word joy,int *dx,int *dy,boolean adaptive)
349 dword TimeCount = *clockdw;
351 static dword lasttime;
353 IN_GetJoyAbs(joy,&x,&y);
356 if (x < def->threshMinX)
358 if (x < def->joyMinX)
361 x = -(x - def->threshMinX);
364 *dx = (x > 127)? -127 : -x;
366 else if (x > def->threshMaxX)
368 if (x > def->joyMaxX)
371 x = x - def->threshMaxX;
374 *dx = (x > 127)? 127 : x;
379 if (y < def->threshMinY)
381 if (y < def->joyMinY)
384 y = -(y - def->threshMinY);
387 *dy = (y > 127)? -127 : -y;
389 else if (y > def->threshMaxY)
391 if (y > def->joyMaxY)
394 y = y - def->threshMaxY;
397 *dy = (y > 127)? 127 : y;
404 time = (TimeCount - lasttime) / 2;
413 lasttime = TimeCount;
416 ///////////////////////////////////////////////////////////////////////////
418 // INL_GetJoyButtons() - Returns the button status of the specified
421 ///////////////////////////////////////////////////////////////////////////
423 INL_GetJoyButtons(word joy)
425 register word result;
427 result = inp(0x201); // Get all the joystick buttons
428 result >>= joy? 6 : 4; // Shift into bits 0-1
429 result &= 3; // Mask off the useless bits
434 ///////////////////////////////////////////////////////////////////////////
436 // IN_GetJoyButtonsDB() - Returns the de-bounced button status of the
437 // specified joystick
439 ///////////////////////////////////////////////////////////////////////////
441 IN_GetJoyButtonsDB(word joy)
443 dword TimeCount = *clockdw;
445 word result1,result2;
449 result1 = INL_GetJoyButtons(joy);
450 lasttime = TimeCount;
451 while(TimeCount == lasttime)
452 result2 = INL_GetJoyButtons(joy);
453 } while(result1 != result2);
457 ///////////////////////////////////////////////////////////////////////////
459 // INL_StartKbd() - Sets up my keyboard stuff for use
461 ///////////////////////////////////////////////////////////////////////////
465 INL_KeyHook = 0; // Clear key hook
469 OldKeyVect = _dos_getvect(KeyInt);
470 _dos_setvect(KeyInt,INL_KeyService);
473 ///////////////////////////////////////////////////////////////////////////
475 // INL_ShutKbd() - Restores keyboard control to the BIOS
477 ///////////////////////////////////////////////////////////////////////////
481 pokeb(0x40,0x17,peekb(0x40,0x17) & 0xfaf0); // Clear ctrl/alt/shift flags
483 _dos_setvect(KeyInt,OldKeyVect);
486 ///////////////////////////////////////////////////////////////////////////
488 // INL_StartMouse() - Detects and sets up the mouse
490 ///////////////////////////////////////////////////////////////////////////
495 if(_dos_getvect(MouseInt))
498 if(CPURegs.x.ax == 0xffff)
504 ///////////////////////////////////////////////////////////////////////////
506 // INL_ShutMouse() - Cleans up after the mouse
508 ///////////////////////////////////////////////////////////////////////////
515 // INL_SetJoyScale() - Sets up scaling values for the specified joystick
518 INL_SetJoyScale(word joy)
523 def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);
524 def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);
525 def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);
526 def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);
529 ///////////////////////////////////////////////////////////////////////////
531 // IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()
532 // to set up scaling values
534 ///////////////////////////////////////////////////////////////////////////
536 IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)
547 def->threshMinX = ((r / 2) - d) + minx;
548 def->threshMaxX = ((r / 2) + d) + minx;
554 def->threshMinY = ((r / 2) - d) + miny;
555 def->threshMaxY = ((r / 2) + d) + miny;
557 INL_SetJoyScale(joy);
560 ///////////////////////////////////////////////////////////////////////////
562 // INL_StartJoy() - Detects & auto-configures the specified joystick
563 // The auto-config assumes the joystick is centered
565 ///////////////////////////////////////////////////////////////////////////
567 INL_StartJoy(word joy)
571 IN_GetJoyAbs(joy,&x,&y);
575 ((x == 0) || (x > MaxJoyValue - 10))
576 || ((y == 0) || (y > MaxJoyValue - 10))
581 IN_SetupJoy(joy,0,x * 2,0,y * 2);
586 ///////////////////////////////////////////////////////////////////////////
588 // INL_ShutJoy() - Cleans up the joystick stuff
590 ///////////////////////////////////////////////////////////////////////////
592 INL_ShutJoy(word joy)
594 JoysPresent[joy] = false;
599 ///////////////////////////////////////////////////////////////////////////
601 // IN_Startup() - Starts up the Input Mgr
603 ///////////////////////////////////////////////////////////////////////////
607 boolean checkjoys,checkmouse;
615 for (i = 1;i < __argc;i++)
617 switch (US_CheckParm(__argv[i],ParmStrings))
629 MousePresent = checkmouse? INL_StartMouse() : false;
631 for (i = 0;i < MaxJoys;i++)
632 JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;
637 ///////////////////////////////////////////////////////////////////////////
639 // IN_Default() - Sets up default conditions for the Input Mgr
641 ///////////////////////////////////////////////////////////////////////////
643 IN_Default(boolean gotit,ControlType in)
648 || ((in == ctrl_Joystick1) && !JoysPresent[0])
649 || ((in == ctrl_Joystick2) && !JoysPresent[1])
650 || ((in == ctrl_Mouse) && !MousePresent)
653 IN_SetControlType(0,in);
656 ///////////////////////////////////////////////////////////////////////////
658 // IN_Shutdown() - Shuts down the Input Mgr
660 ///////////////////////////////////////////////////////////////////////////
670 for (i = 0;i < MaxJoys;i++)
677 ///////////////////////////////////////////////////////////////////////////
679 // IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()
680 // everytime a real make/break code gets hit
682 ///////////////////////////////////////////////////////////////////////////
684 IN_SetKeyHook(void (*hook)())
689 ///////////////////////////////////////////////////////////////////////////
691 // IN_ClearKeyDown() - Clears the keyboard array
693 ///////////////////////////////////////////////////////////////////////////
695 IN_ClearKeysDown(void)
700 LastASCII = key_None;
701 for (i = 0;i < NumCodes;i++)
705 ///////////////////////////////////////////////////////////////////////////
707 // INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()
709 ///////////////////////////////////////////////////////////////////////////
711 INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)
713 if (buttons & (1 << 0))
714 info->button0 = true;
715 if (buttons & (1 << 1))
716 info->button1 = true;
722 ///////////////////////////////////////////////////////////////////////////
724 // IN_ReadCursor() - Reads the input devices and fills in the cursor info
727 ///////////////////////////////////////////////////////////////////////////
729 IN_ReadCursor(CursorInfo *info)
735 info->x = info->y = 0;
736 info->button0 = info->button1 = false;
740 buttons = INL_GetMouseButtons();
741 INL_GetMouseDelta(&dx,&dy);
742 INL_AdjustCursor(info,buttons,dx,dy);
745 for (i = 0;i < MaxJoys;i++)
750 buttons = INL_GetJoyButtons(i);
751 INL_GetJoyDelta(i,&dx,&dy,true);
754 INL_AdjustCursor(info,buttons,dx,dy);
758 ///////////////////////////////////////////////////////////////////////////
760 // IN_ReadControl() - Reads the device associated with the specified
761 // player and fills in the control info struct
763 ///////////////////////////////////////////////////////////////////////////
765 IN_ReadControl(int player,ControlInfo *info)
767 boolean realdelta=false; // MDM (GAMERS EDGE)
773 register KeyboardDef *def;
776 mx = my = motion_None;
780 if (DemoMode == demo_Playback)
782 dbyte = DemoBuffer[DemoOffset + 1];
783 my = (dbyte & 3) - 1;
784 mx = ((dbyte >> 2) & 3) - 1;
785 buttons = (dbyte >> 4) & 3;
787 if (!(--DemoBuffer[DemoOffset]))
790 if (DemoOffset >= DemoSize)
791 DemoMode = demo_PlayDone;
796 else if (DemoMode == demo_PlayDone)
797 Quit("Demo playback exceeded");
801 // MDM begin (GAMERS EDGE) - added this block
802 ControlTypeUsed = ctrl_None;
804 // Handle mouse input...
806 if ((MousePresent) && (ControlTypeUsed == ctrl_None))
808 INL_GetMouseDelta(&dx,&dy);
809 buttons = INL_GetMouseButtons();
811 if (dx || dy || buttons)
812 ControlTypeUsed = ctrl_Mouse;
815 // Handle joystick input...
817 if ((JoystickCalibrated) && (ControlTypeUsed == ctrl_None))
819 type = ctrl_Joystick1;
820 INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
821 buttons = INL_GetJoyButtons(type - ctrl_Joystick);
823 if (dx || dy || buttons)
824 ControlTypeUsed = ctrl_Joystick;
827 // Handle keyboard input...
829 if (ControlTypeUsed == ctrl_None)
831 type = ctrl_Keyboard1;
832 def = &KbdDefs[type - ctrl_Keyboard];
834 if (Keyboard[def->upleft])
835 mx = motion_Left,my = motion_Up;
836 else if (Keyboard[def->upright])
837 mx = motion_Right,my = motion_Up;
838 else if (Keyboard[def->downleft])
839 mx = motion_Left,my = motion_Down;
840 else if (Keyboard[def->downright])
841 mx = motion_Right,my = motion_Down;
843 if (Keyboard[def->up])
845 else if (Keyboard[def->down])
848 if (Keyboard[def->left])
850 else if (Keyboard[def->right])
853 if (Keyboard[def->button0])
855 if (Keyboard[def->button1])
858 if (mx || my || buttons)
859 ControlTypeUsed = ctrl_Keyboard;
860 } // MDM end (GAMERS EDGE)
865 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
866 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
878 info->button0 = buttons & (1 << 0);
879 info->button1 = buttons & (1 << 1);
880 info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
883 if (DemoMode == demo_Record)
885 // Pack the control info into a byte
886 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
890 (DemoBuffer[DemoOffset + 1] == dbyte)
891 && (DemoBuffer[DemoOffset] < 255)
893 (DemoBuffer[DemoOffset])++;
896 if (DemoOffset || DemoBuffer[DemoOffset])
899 if (DemoOffset >= DemoSize)
900 Quit("Demo buffer overflow");
902 DemoBuffer[DemoOffset] = 1;
903 DemoBuffer[DemoOffset + 1] = dbyte;
910 ///////////////////////////////////////////////////////////////////////////
912 // IN_ReadControl() - Reads the device associated with the specified
913 // player and fills in the control info struct
915 ///////////////////////////////////////////////////////////////////////////
917 IN_ReadControl(int player,ControlInfo *info)
925 register KeyboardDef *def;
928 mx = my = motion_None;
932 if (DemoMode == demo_Playback)
934 dbyte = DemoBuffer[DemoOffset + 1];
935 my = (dbyte & 3) - 1;
936 mx = ((dbyte >> 2) & 3) - 1;
937 buttons = (dbyte >> 4) & 3;
939 if (!(--DemoBuffer[DemoOffset]))
942 if (DemoOffset >= DemoSize)
943 DemoMode = demo_PlayDone;
948 else if (DemoMode == demo_PlayDone)
949 Quit("Demo playback exceeded");
953 switch (type = Controls[player])
957 def = &KbdDefs[type - ctrl_Keyboard];
959 if (Keyboard[def->upleft])
960 mx = motion_Left,my = motion_Up;
961 else if (Keyboard[def->upright])
962 mx = motion_Right,my = motion_Up;
963 else if (Keyboard[def->downleft])
964 mx = motion_Left,my = motion_Down;
965 else if (Keyboard[def->downright])
966 mx = motion_Right,my = motion_Down;
968 if (Keyboard[def->up])
970 else if (Keyboard[def->down])
973 if (Keyboard[def->left])
975 else if (Keyboard[def->right])
978 if (Keyboard[def->button0])
980 if (Keyboard[def->button1])
986 INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
987 buttons = INL_GetJoyButtons(type - ctrl_Joystick);
991 INL_GetMouseDelta(&dx,&dy);
992 buttons = INL_GetMouseButtons();
1000 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
1001 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
1013 info->button0 = buttons & (1 << 0);
1014 info->button1 = buttons & (1 << 1);
1015 info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
1018 if (DemoMode == demo_Record)
1020 // Pack the control info into a byte
1021 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
1025 (DemoBuffer[DemoOffset + 1] == dbyte)
1026 && (DemoBuffer[DemoOffset] < 255)
1028 (DemoBuffer[DemoOffset])++;
1031 if (DemoOffset || DemoBuffer[DemoOffset])
1034 if (DemoOffset >= DemoSize)
1035 Quit("Demo buffer overflow");
1037 DemoBuffer[DemoOffset] = 1;
1038 DemoBuffer[DemoOffset + 1] = dbyte;
1045 ///////////////////////////////////////////////////////////////////////////
1047 // IN_SetControlType() - Sets the control type to be used by the specified
1050 ///////////////////////////////////////////////////////////////////////////
1052 IN_SetControlType(int player,ControlType type)
1054 // DEBUG - check that requested type is present?
1055 Controls[player] = type;
1059 ///////////////////////////////////////////////////////////////////////////
1061 // IN_StartDemoRecord() - Starts the demo recording, using a buffer the
1062 // size passed. Returns if the buffer allocation was successful
1064 ///////////////////////////////////////////////////////////////////////////
1066 IN_StartDemoRecord(word bufsize)
1071 MM_GetPtr((memptr *)&DemoBuffer,bufsize);
1072 DemoMode = demo_Record;
1073 DemoSize = bufsize & ~1;
1075 DemoBuffer[0] = DemoBuffer[1] = 0;
1080 ///////////////////////////////////////////////////////////////////////////
1082 // IN_StartDemoPlayback() - Plays back the demo pointed to of the given size
1084 ///////////////////////////////////////////////////////////////////////////
1086 IN_StartDemoPlayback(byte /*__segment*/ *buffer,word bufsize)
1088 DemoBuffer = buffer;
1089 DemoMode = demo_Playback;
1090 DemoSize = bufsize & ~1;
1094 ///////////////////////////////////////////////////////////////////////////
1096 // IN_StopDemo() - Turns off demo mode
1098 ///////////////////////////////////////////////////////////////////////////
1102 if ((DemoMode == demo_Record) && DemoOffset)
1105 DemoMode = demo_Off;
1108 ///////////////////////////////////////////////////////////////////////////
1110 // IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated
1112 ///////////////////////////////////////////////////////////////////////////
1114 IN_FreeDemoBuffer(void)
1117 MM_FreePtr((memptr *)&DemoBuffer);
1123 ///////////////////////////////////////////////////////////////////////////
1125 // IN_GetScanName() - Returns a string containing the name of the
1126 // specified scan code
1128 ///////////////////////////////////////////////////////////////////////////
1130 IN_GetScanName(ScanCode scan)
1135 for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)
1139 return(ScanNames[scan]);
1144 ///////////////////////////////////////////////////////////////////////////
1146 // IN_WaitForKey() - Waits for a scan code, then clears LastScan and
1147 // returns the scan code
1149 ///////////////////////////////////////////////////////////////////////////
1155 while (!(result = LastScan))
1161 ///////////////////////////////////////////////////////////////////////////
1163 // IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
1164 // returns the ASCII value
1166 ///////////////////////////////////////////////////////////////////////////
1168 IN_WaitForASCII(void)
1172 while (!(result = LastASCII))
1178 ///////////////////////////////////////////////////////////////////////////
1180 // IN_AckBack() - Waits for either an ASCII keypress or a button press
1182 ///////////////////////////////////////////////////////////////////////////
1192 if (INL_GetMouseButtons())
1194 while (INL_GetMouseButtons())
1200 for (i = 0;i < MaxJoys;i++)
1204 if (IN_GetJoyButtonsDB(i))
1206 while (IN_GetJoyButtonsDB(i))
1214 IN_ClearKey(LastScan);
1218 ///////////////////////////////////////////////////////////////////////////
1220 // IN_Ack() - Clears user input & then calls IN_AckBack()
1222 ///////////////////////////////////////////////////////////////////////////
1228 IN_ClearKey(LastScan);
1232 while (INL_GetMouseButtons())
1234 for (i = 0;i < MaxJoys;i++)
1236 while (IN_GetJoyButtonsDB(i))
1242 ///////////////////////////////////////////////////////////////////////////
1244 // IN_IsUserInput() - Returns true if a key has been pressed or a button
1247 ///////////////////////////////////////////////////////////////////////////
1249 IN_IsUserInput(void)
1257 if (INL_GetMouseButtons())
1260 for (i = 0;i < MaxJoys;i++)
1262 if (INL_GetJoyButtons(i))
1268 ///////////////////////////////////////////////////////////////////////////
1270 // IN_UserInput() - Waits for the specified delay time (in ticks) or the
1271 // user pressing a key or a mouse button. If the clear flag is set, it
1272 // then either clears the key or waits for the user to let the mouse
1275 ///////////////////////////////////////////////////////////////////////////
1277 IN_UserInput(dword delay,boolean clear)
1279 dword TimeCount = *clockdw;
1282 lasttime = TimeCount;
1285 if (IN_IsUserInput())
1291 } while (TimeCount - lasttime < delay);