1 /* Catacomb Armageddon Source Code
\r
2 * Copyright (C) 1993-2014 Flat Rock Software
\r
4 * This program is free software; you can redistribute it and/or modify
\r
5 * it under the terms of the GNU General Public License as published by
\r
6 * the Free Software Foundation; either version 2 of the License, or
\r
7 * (at your option) any later version.
\r
9 * This program is distributed in the hope that it will be useful,
\r
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 * GNU General Public License for more details.
\r
14 * You should have received a copy of the GNU General Public License along
\r
15 * with this program; if not, write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
21 // ID_IN.c - Input Manager
\r
23 // By Jason Blochowiak
\r
27 // This module handles dealing with the various input devices
\r
29 // Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
\r
30 // User Mgr (for command line parms)
\r
33 // LastScan - The keyboard scan code of the last key pressed
\r
34 // LastASCII - The ASCII value of the last key pressed
\r
35 // DEBUG - there are more globals
\r
38 //#include "ID_HEADS.H"
42 #define KeyInt 9 // The keyboard ISR number
\r
44 // Stuff for the joystick
\r
45 #define JoyScaleMax 32768
\r
46 #define JoyScaleShift 8
\r
47 #define MaxJoyValue 5000
\r
50 boolean JoystickCalibrated=false; // MDM (GAMERS EDGE) - added
\r
51 ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added
\r
53 boolean Keyboard[NumCodes],
\r
54 JoysPresent[MaxJoys],
\r
59 KeyboardDef KbdDefs[MaxKbds] = {{0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}};
\r
60 JoystickDef JoyDefs[MaxJoys];
\r
61 ControlType Controls[MaxPlayers];
\r
63 Demo DemoMode = demo_Off;
\r
64 byte _seg *DemoBuffer;
\r
65 word DemoOffset,DemoSize;
\r
67 // Internal variables
\r
68 static boolean IN_Started;
\r
69 static boolean CapsLock;
\r
70 static ScanCode CurCode,LastCode;
\r
71 static byte far ASCIINames[] = // Unshifted ASCII for scan codes
\r
73 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
\r
74 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0
\r
75 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1
\r
76 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2
\r
77 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
\r
78 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
\r
79 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
\r
80 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
\r
81 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
\r
83 far ShiftNames[] = // Shifted ASCII for scan codes
\r
85 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
\r
86 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0
\r
87 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1
\r
88 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2
\r
89 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
\r
90 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
\r
91 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
\r
92 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
\r
93 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
\r
95 far SpecialNames[] = // ASCII for 0xe0 prefixed codes
\r
97 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
\r
98 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0
\r
99 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1
\r
100 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2
\r
101 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3
\r
102 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4
\r
103 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
\r
104 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
\r
105 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
\r
109 *ScanNames[] = // Scan code names with single chars
\r
111 "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",
\r
112 "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",
\r
113 "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",
\r
114 "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",
\r
115 "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",
\r
116 "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
\r
117 "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
\r
118 "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"
\r
119 }, // DEBUG - consolidate these
\r
122 far ExtScanCodes[] = // Scan codes with >1 char names
\r
124 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,
\r
125 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,
\r
126 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,
\r
127 0x50,0x4b,0x4d,0x00
\r
130 *ExtScanNames[] = // Names corresponding to ExtScanCodes
\r
132 "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",
\r
133 "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",
\r
134 "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",
\r
135 "Down","Left","Right",""
\r
138 static Direction DirTable[] = // Quick lookup for total direction
\r
140 dir_NorthWest, dir_North, dir_NorthEast,
\r
141 dir_West, dir_None, dir_East,
\r
142 dir_SouthWest, dir_South, dir_SouthEast
\r
145 static void (*INL_KeyHook)(void);
\r
146 static void interrupt (*OldKeyVect)(void);
\r
148 static char *ParmStrings[] = {"nojoys","nomouse",nil};
\r
150 // Internal routines
\r
152 ///////////////////////////////////////////////////////////////////////////
\r
154 // INL_KeyService() - Handles a keyboard interrupt (key up/down)
\r
156 ///////////////////////////////////////////////////////////////////////////
\r
157 static void interrupt
\r
158 INL_KeyService(void)
\r
160 static boolean special;
\r
164 k = inportb(0x60); // Get the scan code
\r
166 // Tell the XT keyboard controller to clear the key
\r
167 outportb(0x61,(temp = inportb(0x61)) | 0x80);
\r
168 outportb(0x61,temp);
\r
170 if (k == 0xe0) // Special key prefix
\r
172 else if (k == 0xe1) // Handle Pause key
\r
176 if (k & 0x80) // Break code
\r
180 // DEBUG - handle special keys: ctl-alt-delete, print scrn
\r
182 Keyboard[k] = false;
\r
186 LastCode = CurCode;
\r
187 CurCode = LastScan = k;
\r
188 Keyboard[k] = true;
\r
191 c = SpecialNames[k];
\r
194 if (k == sc_CapsLock)
\r
197 // DEBUG - make caps lock light work
\r
200 if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted
\r
203 if ((c >= 'A') && (c <= 'Z') && CapsLock)
\r
209 if ((c >= 'a') && (c <= 'z') && CapsLock)
\r
220 if (INL_KeyHook && !special)
\r
222 outportb(0x20,0x20);
\r
225 ///////////////////////////////////////////////////////////////////////////
\r
227 // INL_GetMouseDelta() - Gets the amount that the mouse has moved from the
\r
230 ///////////////////////////////////////////////////////////////////////////
\r
232 INL_GetMouseDelta(int *x,int *y)
\r
239 ///////////////////////////////////////////////////////////////////////////
\r
241 // INL_GetMouseButtons() - Gets the status of the mouse buttons from the
\r
244 ///////////////////////////////////////////////////////////////////////////
\r
246 INL_GetMouseButtons(void)
\r
255 ///////////////////////////////////////////////////////////////////////////
\r
257 // IN_GetJoyAbs() - Reads the absolute position of the specified joystick
\r
259 ///////////////////////////////////////////////////////////////////////////
\r
261 IN_GetJoyAbs(word joy,word *xp,word *yp)
\r
268 xs = joy? 2 : 0; // Find shift value for x axis
\r
269 xb = 1 << xs; // Use shift value to get x bit mask
\r
270 ys = joy? 3 : 1; // Do the same for y axis
\r
273 // Read the absolute joystick values
\r
274 asm pushf // Save some registers
\r
277 asm cli // Make sure an interrupt doesn't screw the timings
\r
282 asm out dx,al // Clear the resistors
\r
284 asm mov ah,[xb] // Get masks into registers
\r
287 asm xor si,si // Clear count registers
\r
289 asm xor bh,bh // Clear high byte of bx for later
\r
291 asm push bp // Don't mess up stack frame
\r
292 asm mov bp,MaxJoyValue
\r
295 asm in al,dx // Get bits indicating whether all are finished
\r
297 asm dec bp // Check bounding register
\r
298 asm jz done // We have a silly value - abort
\r
300 asm mov bl,al // Duplicate the bits
\r
301 asm and bl,ah // Mask off useless bits (in [xb])
\r
302 asm add si,bx // Possibly increment count register
\r
303 asm mov cl,bl // Save for testing later
\r
306 asm and bl,ch // [yb]
\r
310 asm jnz loop // If both bits were 0, drop out
\r
315 asm mov cl,[xs] // Get the number of bits to shift
\r
316 asm shr si,cl // and shift the count that many times
\r
321 asm mov [x],si // Store the values into the variables
\r
326 asm popf // Restore the registers
\r
332 ///////////////////////////////////////////////////////////////////////////
\r
334 // INL_GetJoyDelta() - Returns the relative movement of the specified
\r
335 // joystick (from +/-127, scaled adaptively)
\r
337 ///////////////////////////////////////////////////////////////////////////
\r
339 INL_GetJoyDelta(word joy,int *dx,int *dy,boolean adaptive)
\r
344 static longword lasttime;
\r
346 IN_GetJoyAbs(joy,&x,&y);
\r
347 def = JoyDefs + joy;
\r
349 if (x < def->threshMinX)
\r
351 if (x < def->joyMinX)
\r
354 x = -(x - def->threshMinX);
\r
355 x *= def->joyMultXL;
\r
356 x >>= JoyScaleShift;
\r
357 *dx = (x > 127)? -127 : -x;
\r
359 else if (x > def->threshMaxX)
\r
361 if (x > def->joyMaxX)
\r
364 x = x - def->threshMaxX;
\r
365 x *= def->joyMultXH;
\r
366 x >>= JoyScaleShift;
\r
367 *dx = (x > 127)? 127 : x;
\r
372 if (y < def->threshMinY)
\r
374 if (y < def->joyMinY)
\r
377 y = -(y - def->threshMinY);
\r
378 y *= def->joyMultYL;
\r
379 y >>= JoyScaleShift;
\r
380 *dy = (y > 127)? -127 : -y;
\r
382 else if (y > def->threshMaxY)
\r
384 if (y > def->joyMaxY)
\r
387 y = y - def->threshMaxY;
\r
388 y *= def->joyMultYH;
\r
389 y >>= JoyScaleShift;
\r
390 *dy = (y > 127)? 127 : y;
\r
397 time = (TimeCount - lasttime) / 2;
\r
406 lasttime = TimeCount;
\r
409 ///////////////////////////////////////////////////////////////////////////
\r
411 // INL_GetJoyButtons() - Returns the button status of the specified
\r
414 ///////////////////////////////////////////////////////////////////////////
\r
416 INL_GetJoyButtons(word joy)
\r
418 register word result;
\r
420 result = inportb(0x201); // Get all the joystick buttons
\r
421 result >>= joy? 6 : 4; // Shift into bits 0-1
\r
422 result &= 3; // Mask off the useless bits
\r
427 ///////////////////////////////////////////////////////////////////////////
\r
429 // IN_GetJoyButtonsDB() - Returns the de-bounced button status of the
\r
430 // specified joystick
\r
432 ///////////////////////////////////////////////////////////////////////////
\r
434 IN_GetJoyButtonsDB(word joy)
\r
437 word result1,result2;
\r
441 result1 = INL_GetJoyButtons(joy);
\r
442 lasttime = TimeCount;
\r
443 while (TimeCount == lasttime)
\r
445 result2 = INL_GetJoyButtons(joy);
\r
446 } while (result1 != result2);
\r
450 ///////////////////////////////////////////////////////////////////////////
\r
452 // INL_StartKbd() - Sets up my keyboard stuff for use
\r
454 ///////////////////////////////////////////////////////////////////////////
\r
458 INL_KeyHook = 0; // Clear key hook
\r
460 IN_ClearKeysDown();
\r
462 OldKeyVect = getvect(KeyInt);
\r
463 setvect(KeyInt,INL_KeyService);
\r
466 ///////////////////////////////////////////////////////////////////////////
\r
468 // INL_ShutKbd() - Restores keyboard control to the BIOS
\r
470 ///////////////////////////////////////////////////////////////////////////
\r
474 poke(0x40,0x17,peek(0x40,0x17) & 0xfaf0); // Clear ctrl/alt/shift flags
\r
476 setvect(KeyInt,OldKeyVect);
\r
479 ///////////////////////////////////////////////////////////////////////////
\r
481 // INL_StartMouse() - Detects and sets up the mouse
\r
483 ///////////////////////////////////////////////////////////////////////////
\r
485 INL_StartMouse(void)
\r
487 if (getvect(MouseInt))
\r
496 ///////////////////////////////////////////////////////////////////////////
\r
498 // INL_ShutMouse() - Cleans up after the mouse
\r
500 ///////////////////////////////////////////////////////////////////////////
\r
502 INL_ShutMouse(void)
\r
507 // INL_SetJoyScale() - Sets up scaling values for the specified joystick
\r
510 INL_SetJoyScale(word joy)
\r
514 def = &JoyDefs[joy];
\r
515 def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);
\r
516 def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);
\r
517 def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);
\r
518 def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);
\r
521 ///////////////////////////////////////////////////////////////////////////
\r
523 // IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()
\r
524 // to set up scaling values
\r
526 ///////////////////////////////////////////////////////////////////////////
\r
528 IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)
\r
533 def = &JoyDefs[joy];
\r
535 def->joyMinX = minx;
\r
536 def->joyMaxX = maxx;
\r
539 def->threshMinX = ((r / 2) - d) + minx;
\r
540 def->threshMaxX = ((r / 2) + d) + minx;
\r
542 def->joyMinY = miny;
\r
543 def->joyMaxY = maxy;
\r
546 def->threshMinY = ((r / 2) - d) + miny;
\r
547 def->threshMaxY = ((r / 2) + d) + miny;
\r
549 INL_SetJoyScale(joy);
\r
552 ///////////////////////////////////////////////////////////////////////////
\r
554 // INL_StartJoy() - Detects & auto-configures the specified joystick
\r
555 // The auto-config assumes the joystick is centered
\r
557 ///////////////////////////////////////////////////////////////////////////
\r
559 INL_StartJoy(word joy)
\r
563 IN_GetJoyAbs(joy,&x,&y);
\r
567 ((x == 0) || (x > MaxJoyValue - 10))
\r
568 || ((y == 0) || (y > MaxJoyValue - 10))
\r
573 IN_SetupJoy(joy,0,x * 2,0,y * 2);
\r
578 ///////////////////////////////////////////////////////////////////////////
\r
580 // INL_ShutJoy() - Cleans up the joystick stuff
\r
582 ///////////////////////////////////////////////////////////////////////////
\r
584 INL_ShutJoy(word joy)
\r
586 JoysPresent[joy] = false;
\r
591 ///////////////////////////////////////////////////////////////////////////
\r
593 // IN_Startup() - Starts up the Input Mgr
\r
595 ///////////////////////////////////////////////////////////////////////////
\r
599 boolean checkjoys,checkmouse;
\r
607 for (i = 1;i < _argc;i++)
\r
609 switch (US_CheckParm(_argv[i],ParmStrings))
\r
615 checkmouse = false;
\r
621 MousePresent = checkmouse? INL_StartMouse() : false;
\r
623 for (i = 0;i < MaxJoys;i++)
\r
624 JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;
\r
629 ///////////////////////////////////////////////////////////////////////////
\r
631 // IN_Default() - Sets up default conditions for the Input Mgr
\r
633 ///////////////////////////////////////////////////////////////////////////
\r
635 IN_Default(boolean gotit,ControlType in)
\r
640 || ((in == ctrl_Joystick1) && !JoysPresent[0])
\r
641 || ((in == ctrl_Joystick2) && !JoysPresent[1])
\r
642 || ((in == ctrl_Mouse) && !MousePresent)
\r
644 in = ctrl_Keyboard1;
\r
645 IN_SetControlType(0,in);
\r
648 ///////////////////////////////////////////////////////////////////////////
\r
650 // IN_Shutdown() - Shuts down the Input Mgr
\r
652 ///////////////////////////////////////////////////////////////////////////
\r
662 for (i = 0;i < MaxJoys;i++)
\r
666 IN_Started = false;
\r
669 ///////////////////////////////////////////////////////////////////////////
\r
671 // IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()
\r
672 // everytime a real make/break code gets hit
\r
674 ///////////////////////////////////////////////////////////////////////////
\r
676 IN_SetKeyHook(void (*hook)())
\r
678 INL_KeyHook = hook;
\r
681 ///////////////////////////////////////////////////////////////////////////
\r
683 // IN_ClearKeyDown() - Clears the keyboard array
\r
685 ///////////////////////////////////////////////////////////////////////////
\r
687 IN_ClearKeysDown(void)
\r
691 LastScan = sc_None;
\r
692 LastASCII = key_None;
\r
693 for (i = 0;i < NumCodes;i++)
\r
694 Keyboard[i] = false;
\r
697 ///////////////////////////////////////////////////////////////////////////
\r
699 // INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()
\r
701 ///////////////////////////////////////////////////////////////////////////
\r
703 INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)
\r
705 if (buttons & (1 << 0))
\r
706 info->button0 = true;
\r
707 if (buttons & (1 << 1))
\r
708 info->button1 = true;
\r
714 ///////////////////////////////////////////////////////////////////////////
\r
716 // IN_ReadCursor() - Reads the input devices and fills in the cursor info
\r
719 ///////////////////////////////////////////////////////////////////////////
\r
721 IN_ReadCursor(CursorInfo *info)
\r
727 info->x = info->y = 0;
\r
728 info->button0 = info->button1 = false;
\r
732 buttons = INL_GetMouseButtons();
\r
733 INL_GetMouseDelta(&dx,&dy);
\r
734 INL_AdjustCursor(info,buttons,dx,dy);
\r
737 for (i = 0;i < MaxJoys;i++)
\r
739 if (!JoysPresent[i])
\r
742 buttons = INL_GetJoyButtons(i);
\r
743 INL_GetJoyDelta(i,&dx,&dy,true);
\r
746 INL_AdjustCursor(info,buttons,dx,dy);
\r
750 ///////////////////////////////////////////////////////////////////////////
\r
752 // IN_ReadControl() - Reads the device associated with the specified
\r
753 // player and fills in the control info struct
\r
755 ///////////////////////////////////////////////////////////////////////////
\r
757 IN_ReadControl(int player,ControlInfo *info)
\r
759 boolean realdelta=false; // MDM (GAMERS EDGE)
\r
765 register KeyboardDef *def;
\r
768 mx = my = motion_None;
\r
772 if (DemoMode == demo_Playback)
\r
774 dbyte = DemoBuffer[DemoOffset + 1];
\r
775 my = (dbyte & 3) - 1;
\r
776 mx = ((dbyte >> 2) & 3) - 1;
\r
777 buttons = (dbyte >> 4) & 3;
\r
779 if (!(--DemoBuffer[DemoOffset]))
\r
782 if (DemoOffset >= DemoSize)
\r
783 DemoMode = demo_PlayDone;
\r
788 else if (DemoMode == demo_PlayDone)
\r
789 Quit("Demo playback exceeded");
\r
793 // MDM begin (GAMERS EDGE) - added this block
\r
794 ControlTypeUsed = ctrl_None;
\r
796 // Handle mouse input...
\r
798 if ((MousePresent) && (ControlTypeUsed == ctrl_None))
\r
800 INL_GetMouseDelta(&dx,&dy);
\r
801 buttons = INL_GetMouseButtons();
\r
803 if (dx || dy || buttons)
\r
804 ControlTypeUsed = ctrl_Mouse;
\r
807 // Handle joystick input...
\r
809 if ((JoystickCalibrated) && (ControlTypeUsed == ctrl_None))
\r
811 type = ctrl_Joystick1;
\r
812 INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
\r
813 buttons = INL_GetJoyButtons(type - ctrl_Joystick);
\r
815 if (dx || dy || buttons)
\r
816 ControlTypeUsed = ctrl_Joystick;
\r
819 // Handle keyboard input...
\r
821 if (ControlTypeUsed == ctrl_None)
\r
823 type = ctrl_Keyboard1;
\r
824 def = &KbdDefs[type - ctrl_Keyboard];
\r
826 if (Keyboard[def->upleft])
\r
827 mx = motion_Left,my = motion_Up;
\r
828 else if (Keyboard[def->upright])
\r
829 mx = motion_Right,my = motion_Up;
\r
830 else if (Keyboard[def->downleft])
\r
831 mx = motion_Left,my = motion_Down;
\r
832 else if (Keyboard[def->downright])
\r
833 mx = motion_Right,my = motion_Down;
\r
835 if (Keyboard[def->up])
\r
837 else if (Keyboard[def->down])
\r
840 if (Keyboard[def->left])
\r
842 else if (Keyboard[def->right])
\r
845 if (Keyboard[def->button0])
\r
847 if (Keyboard[def->button1])
\r
850 if (mx || my || buttons)
\r
851 ControlTypeUsed = ctrl_Keyboard;
\r
852 } // MDM end (GAMERS EDGE)
\r
857 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
\r
858 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
\r
870 info->button0 = buttons & (1 << 0);
\r
871 info->button1 = buttons & (1 << 1);
\r
872 info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
\r
875 if (DemoMode == demo_Record)
\r
877 // Pack the control info into a byte
\r
878 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
\r
882 (DemoBuffer[DemoOffset + 1] == dbyte)
\r
883 && (DemoBuffer[DemoOffset] < 255)
\r
885 (DemoBuffer[DemoOffset])++;
\r
888 if (DemoOffset || DemoBuffer[DemoOffset])
\r
891 if (DemoOffset >= DemoSize)
\r
892 Quit("Demo buffer overflow");
\r
894 DemoBuffer[DemoOffset] = 1;
\r
895 DemoBuffer[DemoOffset + 1] = dbyte;
\r
902 ///////////////////////////////////////////////////////////////////////////
\r
904 // IN_ReadControl() - Reads the device associated with the specified
\r
905 // player and fills in the control info struct
\r
907 ///////////////////////////////////////////////////////////////////////////
\r
909 IN_ReadControl(int player,ControlInfo *info)
\r
917 register KeyboardDef *def;
\r
920 mx = my = motion_None;
\r
924 if (DemoMode == demo_Playback)
\r
926 dbyte = DemoBuffer[DemoOffset + 1];
\r
927 my = (dbyte & 3) - 1;
\r
928 mx = ((dbyte >> 2) & 3) - 1;
\r
929 buttons = (dbyte >> 4) & 3;
\r
931 if (!(--DemoBuffer[DemoOffset]))
\r
934 if (DemoOffset >= DemoSize)
\r
935 DemoMode = demo_PlayDone;
\r
940 else if (DemoMode == demo_PlayDone)
\r
941 Quit("Demo playback exceeded");
\r
945 switch (type = Controls[player])
\r
947 case ctrl_Keyboard1:
\r
948 case ctrl_Keyboard2:
\r
949 def = &KbdDefs[type - ctrl_Keyboard];
\r
951 if (Keyboard[def->upleft])
\r
952 mx = motion_Left,my = motion_Up;
\r
953 else if (Keyboard[def->upright])
\r
954 mx = motion_Right,my = motion_Up;
\r
955 else if (Keyboard[def->downleft])
\r
956 mx = motion_Left,my = motion_Down;
\r
957 else if (Keyboard[def->downright])
\r
958 mx = motion_Right,my = motion_Down;
\r
960 if (Keyboard[def->up])
\r
962 else if (Keyboard[def->down])
\r
965 if (Keyboard[def->left])
\r
967 else if (Keyboard[def->right])
\r
970 if (Keyboard[def->button0])
\r
972 if (Keyboard[def->button1])
\r
976 case ctrl_Joystick1:
\r
977 case ctrl_Joystick2:
\r
978 INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
\r
979 buttons = INL_GetJoyButtons(type - ctrl_Joystick);
\r
983 INL_GetMouseDelta(&dx,&dy);
\r
984 buttons = INL_GetMouseButtons();
\r
992 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
\r
993 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
\r
1005 info->button0 = buttons & (1 << 0);
\r
1006 info->button1 = buttons & (1 << 1);
\r
1007 info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
\r
1010 if (DemoMode == demo_Record)
\r
1012 // Pack the control info into a byte
\r
1013 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
\r
1017 (DemoBuffer[DemoOffset + 1] == dbyte)
\r
1018 && (DemoBuffer[DemoOffset] < 255)
\r
1020 (DemoBuffer[DemoOffset])++;
\r
1023 if (DemoOffset || DemoBuffer[DemoOffset])
\r
1026 if (DemoOffset >= DemoSize)
\r
1027 Quit("Demo buffer overflow");
\r
1029 DemoBuffer[DemoOffset] = 1;
\r
1030 DemoBuffer[DemoOffset + 1] = dbyte;
\r
1037 ///////////////////////////////////////////////////////////////////////////
\r
1039 // IN_SetControlType() - Sets the control type to be used by the specified
\r
1042 ///////////////////////////////////////////////////////////////////////////
\r
1044 IN_SetControlType(int player,ControlType type)
\r
1046 // DEBUG - check that requested type is present?
\r
1047 Controls[player] = type;
\r
1051 ///////////////////////////////////////////////////////////////////////////
\r
1053 // IN_StartDemoRecord() - Starts the demo recording, using a buffer the
\r
1054 // size passed. Returns if the buffer allocation was successful
\r
1056 ///////////////////////////////////////////////////////////////////////////
\r
1058 IN_StartDemoRecord(word bufsize)
\r
1063 MM_GetPtr((memptr *)&DemoBuffer,bufsize);
\r
1064 DemoMode = demo_Record;
\r
1065 DemoSize = bufsize & ~1;
\r
1067 DemoBuffer[0] = DemoBuffer[1] = 0;
\r
1072 ///////////////////////////////////////////////////////////////////////////
\r
1074 // IN_StartDemoPlayback() - Plays back the demo pointed to of the given size
\r
1076 ///////////////////////////////////////////////////////////////////////////
\r
1078 IN_StartDemoPlayback(byte /*_1seg*/ *buffer,word bufsize)
\r
1080 DemoBuffer = buffer;
\r
1081 DemoMode = demo_Playback;
\r
1082 DemoSize = bufsize & ~1;
\r
1086 ///////////////////////////////////////////////////////////////////////////
\r
1088 // IN_StopDemo() - Turns off demo mode
\r
1090 ///////////////////////////////////////////////////////////////////////////
\r
1094 if ((DemoMode == demo_Record) && DemoOffset)
\r
1097 DemoMode = demo_Off;
\r
1100 ///////////////////////////////////////////////////////////////////////////
\r
1102 // IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated
\r
1104 ///////////////////////////////////////////////////////////////////////////
\r
1106 IN_FreeDemoBuffer(void)
\r
1109 MM_FreePtr((memptr *)&DemoBuffer);
\r
1115 ///////////////////////////////////////////////////////////////////////////
\r
1117 // IN_GetScanName() - Returns a string containing the name of the
\r
1118 // specified scan code
\r
1120 ///////////////////////////////////////////////////////////////////////////
\r
1122 IN_GetScanName(ScanCode scan)
\r
1127 for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)
\r
1131 return(ScanNames[scan]);
\r
1136 ///////////////////////////////////////////////////////////////////////////
\r
1138 // IN_WaitForKey() - Waits for a scan code, then clears LastScan and
\r
1139 // returns the scan code
\r
1141 ///////////////////////////////////////////////////////////////////////////
\r
1143 IN_WaitForKey(void)
\r
1147 while (!(result = LastScan))
\r
1153 ///////////////////////////////////////////////////////////////////////////
\r
1155 // IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
\r
1156 // returns the ASCII value
\r
1158 ///////////////////////////////////////////////////////////////////////////
\r
1160 IN_WaitForASCII(void)
\r
1164 while (!(result = LastASCII))
\r
1170 ///////////////////////////////////////////////////////////////////////////
\r
1172 // IN_AckBack() - Waits for either an ASCII keypress or a button press
\r
1174 ///////////////////////////////////////////////////////////////////////////
\r
1184 if (INL_GetMouseButtons())
\r
1186 while (INL_GetMouseButtons())
\r
1192 for (i = 0;i < MaxJoys;i++)
\r
1194 if (JoysPresent[i])
\r
1196 if (IN_GetJoyButtonsDB(i))
\r
1198 while (IN_GetJoyButtonsDB(i))
\r
1206 IN_ClearKey(LastScan);
\r
1207 LastScan = sc_None;
\r
1210 ///////////////////////////////////////////////////////////////////////////
\r
1212 // IN_Ack() - Clears user input & then calls IN_AckBack()
\r
1214 ///////////////////////////////////////////////////////////////////////////
\r
1220 IN_ClearKey(LastScan);
\r
1221 LastScan = sc_None;
\r
1224 while (INL_GetMouseButtons())
\r
1226 for (i = 0;i < MaxJoys;i++)
\r
1227 if (JoysPresent[i])
\r
1228 while (IN_GetJoyButtonsDB(i))
\r
1234 ///////////////////////////////////////////////////////////////////////////
\r
1236 // IN_IsUserInput() - Returns true if a key has been pressed or a button
\r
1239 ///////////////////////////////////////////////////////////////////////////
\r
1241 IN_IsUserInput(void)
\r
1246 result = LastScan;
\r
1249 if (INL_GetMouseButtons())
\r
1252 for (i = 0;i < MaxJoys;i++)
\r
1253 if (JoysPresent[i])
\r
1254 if (INL_GetJoyButtons(i))
\r
1260 ///////////////////////////////////////////////////////////////////////////
\r
1262 // IN_UserInput() - Waits for the specified delay time (in ticks) or the
\r
1263 // user pressing a key or a mouse button. If the clear flag is set, it
\r
1264 // then either clears the key or waits for the user to let the mouse
\r
1267 ///////////////////////////////////////////////////////////////////////////
\r
1269 IN_UserInput(longword delay,boolean clear)
\r
1271 longword lasttime;
\r
1273 lasttime = TimeCount;
\r
1276 if (IN_IsUserInput())
\r
1282 } while (TimeCount - lasttime < delay);
\r