1 /* Project 16 Source Code~
\r
2 * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
\r
4 * This file is part of Project 16.
\r
6 * Project 16 is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 3 of the License, or
\r
9 * (at your option) any later version.
\r
11 * Project 16 is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with this program. If not, see <http://www.gnu.org/licenses/>, or
\r
18 * write to the Free Software Foundation, Inc., 51 Franklin Street,
\r
19 * Fifth Floor, Boston, MA 02110-1301 USA.
\r
24 // ID_IN.c - Input Manager
\r
26 // By Jason Blochowiak
\r
27 // Open Watcom port by sparky4
\r
31 // This module handles dealing with the various input devices
\r
33 // Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
\r
34 // User Mgr (for command line parms)
\r
37 // LastScan - The keyboard scan code of the last key pressed
\r
38 // LastASCII - The ASCII value of the last key pressed
\r
39 // DEBUG - there are more globals
\r
42 #include "src/lib/16_in.h"
\r
45 static word far* clockw= (word far*) 0x046C; /* 18.2hz clock */
\r
48 =============================================================================
\r
52 =============================================================================
\r
56 boolean MousePresent;
\r
57 boolean JoysPresent[MaxJoys];
\r
58 boolean Keyboard[NumCodes];
\r
63 KeyboardDef KbdDefs[MaxKbds];
\r
64 JoystickDef JoyDefs[MaxJoys];
\r
67 //gvar->in.KbdDefs = {0x1d,0x38,/*0x47,*/0x48,/*0x49,*/0x4b,0x4d,/*0x4f,*/0x50/*,0x51*/};
\r
70 =============================================================================
\r
74 =============================================================================
\r
77 #ifdef __cplusplus /* Function must be declared C style */
\r
81 /*static struct instat {
\r
83 ScanCode CurCode,LastCode;
\r
85 boolean Keyboard[NumCodes];
\r
91 //the def stuff is need fix warnings
\r
97 static byte far ASCIINames[] = // Unshifted ASCII for scan codes
\r
99 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
\r
100 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0
\r
101 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1
\r
102 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2
\r
103 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
\r
104 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
\r
105 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
\r
106 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
\r
107 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
\r
109 far ShiftNames[] = // Shifted ASCII for scan codes
\r
111 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
\r
112 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0
\r
113 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1
\r
114 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2
\r
115 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
\r
116 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
\r
117 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
\r
118 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
\r
119 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
\r
121 far SpecialNames[] = // ASCII for 0xe0 prefixed codes
\r
123 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
\r
124 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0
\r
125 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1
\r
126 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2
\r
127 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3
\r
128 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4
\r
129 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
\r
130 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
\r
131 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
\r
133 *ScanNames[] = // Scan code names with single chars
\r
135 "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",
\r
136 "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",
\r
137 "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",
\r
138 "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",
\r
139 "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",
\r
140 "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
\r
141 "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
\r
142 "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"
\r
143 }, // DEBUG - consolidate these
\r
144 far ExtScanCodes[] = // Scan codes with >1 char names
\r
146 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,
\r
147 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,
\r
148 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,
\r
149 0x50,0x4b,0x4d,0x00
\r
151 *ExtScanNames[] = // Names corresponding to ExtScanCodes
\r
153 "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",
\r
154 "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",
\r
155 "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",
\r
156 "Down","Left","Right",""
\r
159 static Direction DirTable[] = // Quick lookup for total direction
\r
161 /*dir_NorthWest, */dir_North,/* dir_NorthEast,*/
\r
162 dir_West, dir_None, dir_East,
\r
163 /*dir_SouthWest, */dir_South/*, dir_SouthEast*/
\r
169 static void (*INL_KeyHook)(void);
\r
170 static void interrupt (*OldKeyVect)(void);
\r
171 static char *ParmStringsIN[] = {"nojoys","nomouse",nil};
\r
172 static void INL_StartKbd(void);
\r
174 // Internal routines
\r
176 ///////////////////////////////////////////////////////////////////////////
\r
178 // INL_KeyService() - Handles a keyboard interrupt (key up/down)
\r
180 ///////////////////////////////////////////////////////////////////////////
\r
181 /*static */void interrupt
\r
182 INL_KeyService(void)
\r
184 static boolean special;
\r
188 k = inportb(0x60); // Get the scan code
\r
190 // Tell the XT keyboard controller to clear the key
\r
191 outportb(0x61,(temp = inportb(0x61)) | 0x80);
\r
192 outportb(0x61,temp);
\r
194 if (k == 0xe0) // Special key prefix
\r
196 else if (k == 0xe1) // Handle Pause key
\r
197 inst.Paused = true;
\r
200 if (k & 0x80) // Break code
\r
204 // DEBUG - handle special keys: ctl-alt-delete, print scrn
\r
206 inst.Keyboard[k] = false;
\r
210 inst.LastCode = inst.CurCode;
\r
211 inst.CurCode = inst.LastScan = k;
\r
212 inst.Keyboard[k] = true;
\r
215 c = SpecialNames[k];
\r
218 if (k == sc_CapsLock)
\r
220 inst.CapsLock ^= true;
\r
221 // DEBUG - make caps lock light work
\r
224 if (inst.Keyboard[sc_LShift] || inst.Keyboard[sc_RShift]) // If shifted
\r
227 if ((c >= 'A') && (c <= 'Z') && inst.CapsLock)
\r
233 if ((c >= 'a') && (c <= 'z') && inst.CapsLock)
\r
238 inst.LastASCII = c;
\r
244 if (INL_KeyHook && !special)
\r
246 #ifdef __DEBUG_InputMgr__
\r
247 if(dbg_testkeyin > 0) printf("%c %u [0x%x %u] %u\n", c, c, k, k, inst.Keyboard[k]);
\r
249 outportb(0x20,0x20);
\r
252 ///////////////////////////////////////////////////////////////////////////
\r
254 // INL_GetMouseDelta() - Gets the amount that the mouse has moved from the
\r
257 ///////////////////////////////////////////////////////////////////////////
\r
259 INL_GetMouseDelta(int *x,int *y)
\r
266 ///////////////////////////////////////////////////////////////////////////
\r
268 // INL_GetMouseButtons() - Gets the status of the mouse buttons from the
\r
271 ///////////////////////////////////////////////////////////////////////////
\r
273 INL_GetMouseButtons(void)
\r
282 ///////////////////////////////////////////////////////////////////////////
\r
284 // IN_GetJoyAbs() - Reads the absolute position of the specified joystick
\r
286 ///////////////////////////////////////////////////////////////////////////
\r
288 IN_GetJoyAbs(word joy,word *xp,word *yp)
\r
295 xs = joy? 2 : 0; // Find shift value for x axis
\r
296 xb = 1 << xs; // Use shift value to get x bit mask
\r
297 ys = joy? 3 : 1; // Do the same for y axis
\r
300 // Read the absolute joystick values
\r
302 pushf // Save some registers
\r
305 cli // Make sure an interrupt doesn't screw the timings
\r
310 out dx,al // Clear the resistors
\r
312 mov ah,[xb] // Get masks into registers
\r
315 xor si,si // Clear count registers
\r
317 xor bh,bh // Clear high byte of bx for later
\r
319 push bp // Don't mess up stack frame
\r
321 #ifdef __BORLANDC__
\r
325 #ifdef __BORLANDC__
\r
328 in al,dx // Get bits indicating whether all are finished
\r
330 dec bp // Check bounding register
\r
331 jz done // We have a silly value - abort
\r
333 mov bl,al // Duplicate the bits
\r
334 and bl,ah // Mask off useless bits (in [xb])
\r
335 add si,bx // Possibly increment count register
\r
336 mov cl,bl // Save for testing later
\r
343 jnz loo // If both bits were 0, drop out
\r
344 #ifdef __BORLANDC__
\r
348 #ifdef __BORLANDC__
\r
353 mov cl,[xs] // Get the number of bits to shift
\r
354 shr si,cl // and shift the count that many times
\r
359 mov [x],si // Store the values into the variables
\r
364 popf // Restore the registers
\r
371 ///////////////////////////////////////////////////////////////////////////
\r
373 // INL_GetJoyDelta() - Returns the relative movement of the specified
\r
374 // joystick (from +/-127)
\r
376 ///////////////////////////////////////////////////////////////////////////
\r
377 void INL_GetJoyDelta(word joy,int *dx,int *dy/*,boolean adaptive*/, global_game_variables_t *gvar)
\r
380 //00 word TimeCount = *clockw;
\r
382 //00static word lasttime;
\r
384 IN_GetJoyAbs(joy,&x,&y);
\r
385 def = gvar->in.JoyDefs + joy;
\r
387 if (x < def->threshMinX)
\r
389 if (x < def->joyMinX)
\r
392 x = -(x - def->threshMinX);
\r
393 x *= def->joyMultXL;
\r
394 x >>= JoyScaleShift;
\r
395 *dx = (x > 127)? -127 : -x;
\r
397 else if (x > def->threshMaxX)
\r
399 if (x > def->joyMaxX)
\r
402 x = x - def->threshMaxX;
\r
403 x *= def->joyMultXH;
\r
404 x >>= JoyScaleShift;
\r
405 *dx = (x > 127)? 127 : x;
\r
410 if (y < def->threshMinY)
\r
412 if (y < def->joyMinY)
\r
415 y = -(y - def->threshMinY);
\r
416 y *= def->joyMultYL;
\r
417 y >>= JoyScaleShift;
\r
418 *dy = (y > 127)? -127 : -y;
\r
420 else if (y > def->threshMaxY)
\r
422 if (y > def->joyMaxY)
\r
425 y = y - def->threshMaxY;
\r
426 y *= def->joyMultYH;
\r
427 y >>= JoyScaleShift;
\r
428 *dy = (y > 127)? 127 : y;
\r
434 // time = (TimeCount - lasttime) / 2;
\r
443 //00 lasttime = TimeCount;
\r
446 ///////////////////////////////////////////////////////////////////////////
\r
448 // INL_GetJoyButtons() - Returns the button status of the specified
\r
451 ///////////////////////////////////////////////////////////////////////////
\r
453 INL_GetJoyButtons(word joy)
\r
455 register word result;
\r
457 result = inportb(0x201); // Get all the joystick buttons
\r
458 result >>= joy? 6 : 4; // Shift into bits 0-1
\r
459 result &= 3; // Mask off the useless bits
\r
464 ///////////////////////////////////////////////////////////////////////////
\r
466 // IN_GetJoyButtonsDB() - Returns the de-bounced button status of the
\r
467 // specified joystick
\r
469 ///////////////////////////////////////////////////////////////////////////
\r
471 IN_GetJoyButtonsDB(word joy)
\r
473 //00 word TimeCount = *clockw;
\r
474 //00 word lasttime;
\r
475 word result1,result2;
\r
479 result1 = INL_GetJoyButtons(joy);
\r
480 //00 lasttime = TimeCount;
\r
481 //00 while(TimeCount == lasttime)
\r
483 result2 = INL_GetJoyButtons(joy);
\r
484 } while(result1 != result2);
\r
488 ///////////////////////////////////////////////////////////////////////////
\r
490 // INL_StartKbd() - Sets up my keyboard stuff for use
\r
492 ///////////////////////////////////////////////////////////////////////////
\r
496 INL_KeyHook = NULL; // Clear key hook
\r
498 IN_ClearKeysDown();
\r
500 OldKeyVect = getvect(KeyInt);//IN_KbdLED();
\r
501 setvect(KeyInt,INL_KeyService);
\r
504 ///////////////////////////////////////////////////////////////////////////
\r
506 // INL_ShutKbd() - Restores keyboard control to the BIOS
\r
508 ///////////////////////////////////////////////////////////////////////////
\r
512 pokeb(0x40,0x17,peekb(0x40,0x17) & 0xfaf0); // Clear ctrl/alt/shift flags
\r
514 setvect(KeyInt,OldKeyVect);
\r
517 ///////////////////////////////////////////////////////////////////////////
\r
519 // INL_StartMouse() - Detects and sets up the mouse
\r
521 ///////////////////////////////////////////////////////////////////////////
\r
523 INL_StartMouse(void)
\r
526 if (getvect(MouseInt))
\r
537 if ((vector=MK_FP(peek(0,0x33*4+2),peek(0,0x33*4)))==NULL)
\r
540 if (*vector == 207)
\r
548 ///////////////////////////////////////////////////////////////////////////
\r
550 // INL_ShutMouse() - Cleans up after the mouse
\r
552 ///////////////////////////////////////////////////////////////////////////
\r
554 INL_ShutMouse(void)
\r
559 // INL_SetJoyScale() - Sets up scaling values for the specified joystick
\r
562 INL_SetJoyScale(word joy, global_game_variables_t *gvar)
\r
566 def = &(gvar->in.JoyDefs[joy]);
\r
567 def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);
\r
568 def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);
\r
569 def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);
\r
570 def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);
\r
573 ///////////////////////////////////////////////////////////////////////////
\r
575 // IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()
\r
576 // to set up scaling values
\r
578 ///////////////////////////////////////////////////////////////////////////
\r
580 IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy, global_game_variables_t *gvar)
\r
585 def = &(gvar->in.JoyDefs[joy]);
\r
587 def->joyMinX = minx;
\r
588 def->joyMaxX = maxx;
\r
591 def->threshMinX = ((r / 2) - d) + minx;
\r
592 def->threshMaxX = ((r / 2) + d) + minx;
\r
594 def->joyMinY = miny;
\r
595 def->joyMaxY = maxy;
\r
598 def->threshMinY = ((r / 2) - d) + miny;
\r
599 def->threshMaxY = ((r / 2) + d) + miny;
\r
601 INL_SetJoyScale(joy, gvar);
\r
604 ///////////////////////////////////////////////////////////////////////////
\r
606 // INL_StartJoy() - Detects & auto-configures the specified joystick
\r
607 // The auto-config assumes the joystick is centered
\r
609 ///////////////////////////////////////////////////////////////////////////
\r
611 INL_StartJoy(word joy, global_game_variables_t *gvar)
\r
615 IN_GetJoyAbs(joy,&x,&y);
\r
619 ((x == 0) || (x > MaxJoyValue - 10))
\r
620 || ((y == 0) || (y > MaxJoyValue - 10))
\r
625 IN_SetupJoy(joy,0,x * 2,0,y * 2, gvar);
\r
630 ///////////////////////////////////////////////////////////////////////////
\r
632 // INL_ShutJoy() - Cleans up the joystick stuff
\r
634 ///////////////////////////////////////////////////////////////////////////
\r
636 INL_ShutJoy(word joy, global_game_variables_t *gvar)
\r
638 gvar->in.JoysPresent[joy] = false;
\r
643 ///////////////////////////////////////////////////////////////////////////
\r
645 // IN_Startup() - Starts up the Input Mgr
\r
647 ///////////////////////////////////////////////////////////////////////////
\r
649 IN_Startup(global_game_variables_t *gvar)
\r
651 boolean checkjoys,checkmouse;
\r
654 if (gvar->in.IN_Started)
\r
659 for (i = 1;i < _argc;i++)
\r
661 switch (US_CheckParm(_argv[i],ParmStringsIN))
\r
667 checkmouse = false;
\r
673 gvar->in.MousePresent = checkmouse? INL_StartMouse() : false;
\r
675 for (i = 0;i < MaxJoys;i++)
\r
676 gvar->in.JoysPresent[i] = checkjoys? INL_StartJoy(i, gvar) : false;
\r
678 gvar->in.inst = &inst;
\r
680 gvar->in.IN_Started = true;
\r
683 ///////////////////////////////////////////////////////////////////////////
\r
685 // IN_Default() - Sets up default conditions for the Input Mgr
\r
687 ///////////////////////////////////////////////////////////////////////////
\r
689 IN_Default(boolean gotit,player_t *player,ControlType nt, global_game_variables_t *gvar)
\r
695 || ((nt == ctrl_Joystick1) && !gvar->in.JoysPresent[0])
\r
696 || ((nt == ctrl_Joystick2) && !gvar->in.JoysPresent[1])
\r
697 || ((nt == ctrl_Mouse) && !gvar->in.MousePresent)
\r
699 nt = ctrl_Keyboard1;
\r
700 gvar->in.KbdDefs[0].button0 = 0x1c;
\r
701 gvar->in.KbdDefs[0].button1 = 0x38;
\r
702 //in.KbdDefs[0].upleft = 0x47;
\r
703 gvar->in.KbdDefs[0].up = 0x48;
\r
704 //in.KbdDefs[0].upright = 0x49;
\r
705 gvar->in.KbdDefs[0].left = 0x4b;
\r
706 gvar->in.KbdDefs[0].right = 0x4d;
\r
707 //in.KbdDefs[0].downleft = 0x4f;
\r
708 gvar->in.KbdDefs[0].down = 0x50;
\r
709 //in.KbdDefs[0].downright = 0x51;
\r
710 IN_SetControlType(player,nt);
\r
711 for(i=0; i>MaxPlayers;i++)
\r
712 player[i].enti.d =2;
\r
715 ///////////////////////////////////////////////////////////////////////////
\r
717 // IN_Shutdown() - Shuts down the Input Mgr
\r
719 ///////////////////////////////////////////////////////////////////////////
\r
721 IN_Shutdown(global_game_variables_t *gvar)
\r
725 if (!gvar->in.IN_Started)
\r
729 for (i = 0;i < MaxJoys;i++)
\r
730 INL_ShutJoy(i, gvar);
\r
733 gvar->in.IN_Started = false;
\r
736 ///////////////////////////////////////////////////////////////////////////
\r
738 // IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()
\r
739 // everytime a real make/break code gets hit
\r
741 ///////////////////////////////////////////////////////////////////////////
\r
743 IN_SetKeyHook(void (*hook)())
\r
745 INL_KeyHook = hook;
\r
748 ///////////////////////////////////////////////////////////////////////////
\r
750 // IN_ClearKeysDown() - Clears the keyboard array
\r
752 ///////////////////////////////////////////////////////////////////////////
\r
754 IN_ClearKeysDown(void)
\r
758 inst.LastScan = sc_None;
\r
759 inst.LastASCII = key_None;
\r
760 memset (inst.Keyboard,0,sizeof(inst.Keyboard));
\r
763 ///////////////////////////////////////////////////////////////////////////
\r
765 // INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()
\r
767 ///////////////////////////////////////////////////////////////////////////
\r
769 INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)
\r
771 if (buttons & (1 << 0))
\r
772 info->button0 = true;
\r
773 if (buttons & (1 << 1))
\r
774 info->button1 = true;
\r
780 ///////////////////////////////////////////////////////////////////////////
\r
782 // IN_ReadCursor() - Reads the input devices and fills in the cursor info
\r
785 ///////////////////////////////////////////////////////////////////////////
\r
787 IN_ReadCursor(CursorInfo *info, global_game_variables_t *gvar)
\r
793 info->x = info->y = 0;
\r
794 info->button0 = info->button1 = false;
\r
796 if (gvar->in.MousePresent)
\r
798 buttons = INL_GetMouseButtons();
\r
799 INL_GetMouseDelta(&dx,&dy);
\r
800 INL_AdjustCursor(info,buttons,dx,dy);
\r
803 for (i = 0;i < MaxJoys;i++)
\r
805 if (!gvar->in.JoysPresent[i])
\r
808 buttons = INL_GetJoyButtons(i);
\r
809 INL_GetJoyDelta(i,&dx,&dy/*,true*/, gvar);
\r
812 INL_AdjustCursor(info,buttons,dx,dy);
\r
816 //if else for gfxtesting and direction
\r
817 #define DIRECTIONIFELSE (player->info.dir == 2)
\r
818 //#define NDIRECTIONIFELSE (player->info.dir != 2)
\r
820 ///////////////////////////////////////////////////////////////////////////
\r
822 // IN_ReadControl() - Reads the device associated with the specified
\r
823 // player and fills in the control info struct
\r
825 ///////////////////////////////////////////////////////////////////////////
\r
827 IN_ReadControl(player_t *player, global_game_variables_t *gvar)
\r
838 byte dir=DirTable[2];
\r
839 register KeyboardDef *def;
\r
842 mx = my = motion_None;
\r
846 if (DemoMode == demo_Playback)
\r
848 dbyte = DemoBuffer[DemoOffset + 1];
\r
849 my = (dbyte & 3) - 1;
\r
850 mx = ((dbyte >> 2) & 3) - 1;
\r
851 buttons = (dbyte >> 4) & 3;
\r
853 if (!(--DemoBuffer[DemoOffset]))
\r
856 if (DemoOffset >= DemoSize)
\r
857 DemoMode = demo_PlayDone;
\r
862 else if (DemoMode == demo_PlayDone)
\r
863 Quit ("Demo playback exceeded");
\r
867 switch (type = player->Controls)
\r
869 case ctrl_Keyboard:
\r
870 def = &(gvar->in.KbdDefs[type - ctrl_Keyboard]);
\r
872 /* if (Keyboard[def->upleft])
\r
873 mx = motion_Left,my = motion_Up;
\r
874 else if (Keyboard[def->upright])
\r
875 mx = motion_Right,my = motion_Up;
\r
876 else if (Keyboard[def->downleft])
\r
877 mx = motion_Left,my = motion_Down;
\r
878 else if (Keyboard[def->downright])
\r
879 mx = motion_Right,my = motion_Down;*/
\r
880 //TODO: make this into a function that the joystick AND keyboard can use wwww
\r
881 if(DIRECTIONIFELSE)//(player->info.dir == 2)
\r
883 if(!inst.Keyboard[def->left] && !inst.Keyboard[def->right]){
\r
884 if((inst.Keyboard[def->up] && !inst.Keyboard[def->down]))
\r
886 if((inst.Keyboard[def->down] && !inst.Keyboard[def->up]))
\r
888 }else if(!inst.Keyboard[def->up] && !inst.Keyboard[def->down]){
\r
889 if((inst.Keyboard[def->left] && !inst.Keyboard[def->right]))
\r
891 if((inst.Keyboard[def->right] && !inst.Keyboard[def->left]))
\r
893 }else{ //2 keys pressed
\r
894 switch (player->pdir)
\r
898 if((inst.Keyboard[def->left] && !inst.Keyboard[def->right])){ dir = DirTable[1]; }//mx = motion_Left; }
\r
899 else if((inst.Keyboard[def->right] && !inst.Keyboard[def->left])){ dir = DirTable[3]; }//mx = motion_Right; }
\r
903 if((inst.Keyboard[def->up] && !inst.Keyboard[def->down])){ dir = DirTable[0]; }//my = motion_Up; }
\r
904 else if((inst.Keyboard[def->down] && !inst.Keyboard[def->up])){ dir = DirTable[4]; }//my = motion_Down; }
\r
909 #ifdef __DEBUG_InputMgr__
\r
910 //if(dbg_testcontrolnoisy > 0){ printf("dir=%c ", dirchar(dir)); printf("pdir=%c ", dirchar(player->pdir)); }
\r
914 //input from player
\r
915 if (inst.Keyboard[def->button0])
\r
917 if (inst.Keyboard[def->button1])
\r
921 case ctrl_Joystick1:
\r
922 case ctrl_Joystick2:
\r
923 INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy/*,false*/, gvar);
\r
924 buttons = INL_GetJoyButtons(type - ctrl_Joystick);
\r
928 INL_GetMouseDelta(&dx,&dy);
\r
929 buttons = INL_GetMouseButtons();
\r
939 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
\r
940 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
\r
948 player->info.x = dx;
\r
949 player->info.xaxis = mx;
\r
950 player->info.y = dy;
\r
951 player->info.yaxis = my;
\r
952 player->info.button0 = buttons & (1 << 0);
\r
953 player->info.button1 = buttons & (1 << 1);
\r
954 player->info.button2 = buttons & (1 << 2);
\r
955 player->info.button3 = buttons & (1 << 3);
\r
956 // player->info.dir = DirTable[((my + 1) * 3) + (mx + 1)];
\r
957 conpee=(((my + 1) * 2) + (mx + 1))-1;
\r
958 player->info.dir = DirTable[conpee];
\r
960 if(DirTable[conpee]!=2) player->pdir=DirTable[conpee];
\r
961 if(player->enti.q==1 &&( dir!=2 || (mx!=motion_None || my!=motion_None)))
\r
963 if(dir==2) player->enti.d = player->info.dir;
\r
964 else player->enti.d = DirTable[dir];
\r
968 if (DemoMode == demo_Record)
\r
970 // Pack the control info into a byte
\r
971 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
\r
975 (DemoBuffer[DemoOffset + 1] == dbyte)
\r
976 && (DemoBuffer[DemoOffset] < 255)
\r
978 (DemoBuffer[DemoOffset])++;
\r
981 if (DemoOffset || DemoBuffer[DemoOffset])
\r
984 if (DemoOffset >= DemoSize)
\r
985 Quit ("Demo buffer overflow");
\r
987 DemoBuffer[DemoOffset] = 1;
\r
988 DemoBuffer[DemoOffset + 1] = dbyte;
\r
992 #ifdef __DEBUG_InputMgr__
\r
993 if(dbg_joymousedelta)
\r
996 static int old_dx,old_dy;
\r
997 static word old_buttons=0;
\r
998 if(dx!=old_dx || dy!=old_dy) printf("dx,dy [%d,%d] %d,%d\n", dx, dy, mx, my);
\r
999 if(dx!=old_dx) old_dx=dx;
\r
1000 if(dy!=old_dy) old_dy=dy;
\r
1001 if(old_buttons!=buttons)
\r
1003 printf(" buttons={%u,%u,%u,%u}\n", player->info.button0, player->info.button1, player->info.button2, player->info.button3);
\r
1004 old_buttons=buttons;
\r
1009 if(dbg_testcontrolnoisy > 0)
\r
1010 if(player->info.dir!=2/*(inst.Keyboard[def->up] || inst.Keyboard[def->down] || inst.Keyboard[def->left] || inst.Keyboard[def->right])*/ || player->enti.q>1)
\r
1012 //printf("b1=%u b2=%u b3=%u b4=%u ", player->info.button0, player->info.button1, player->info.button2, player->info.button3);
\r
1013 //printf("q=%d ", player->enti.q);
\r
1014 //printf("cpee=%c ", dirchar(conpee));
\r
1015 printf("pdir=%c d=%c dir=%c ", dirchar(player->pdir), dirchar(player->enti.d), dirchar(player->info.dir));
\r
1016 /*if(realdelta) */printf("dx=%d dy=%d mx=%d my=%d", player->info.x, player->info.y, player->info.xaxis, player->info.yaxis);
\r
1017 //else if(!realdelta) printf("%c%d %c%d %c%d %c%d", dirchar(0), inst.Keyboard[def->up], dirchar(4), inst.Keyboard[def->down], dirchar(1), inst.Keyboard[def->left], dirchar(3), inst.Keyboard[def->right]);
\r
1023 ///////////////////////////////////////////////////////////////////////////
\r
1025 // IN_SetControlType() - Sets the control type to be used by the specified
\r
1028 ///////////////////////////////////////////////////////////////////////////
\r
1030 IN_SetControlType(player_t *player,ControlType type)
\r
1032 // DEBUG - check that requested type is present?
\r
1033 player->Controls = type;
\r
1037 ///////////////////////////////////////////////////////////////////////////
\r
1039 // IN_StartDemoRecord() - Starts the demo recording, using a buffer the
\r
1040 // size passed. Returns if the buffer allocation was successful
\r
1042 ///////////////////////////////////////////////////////////////////////////
\r
1044 IN_StartDemoRecord(word bufsize)
\r
1049 MM_GetPtr((memptr *)&DemoBuffer,bufsize);
\r
1050 DemoMode = demo_Record;
\r
1051 DemoSize = bufsize & ~1;
\r
1053 DemoBuffer[0] = DemoBuffer[1] = 0;
\r
1058 ///////////////////////////////////////////////////////////////////////////
\r
1060 // IN_StartDemoPlayback() - Plays back the demo pointed to of the given size
\r
1062 ///////////////////////////////////////////////////////////////////////////
\r
1064 IN_StartDemoPlayback(byte /*__segment*/ *buffer,word bufsize)
\r
1066 DemoBuffer = buffer;
\r
1067 DemoMode = demo_Playback;
\r
1068 DemoSize = bufsize & ~1;
\r
1072 ///////////////////////////////////////////////////////////////////////////
\r
1074 // IN_StopDemo() - Turns off demo mode
\r
1076 ///////////////////////////////////////////////////////////////////////////
\r
1080 if ((DemoMode == demo_Record) && DemoOffset)
\r
1083 DemoMode = demo_Off;
\r
1086 ///////////////////////////////////////////////////////////////////////////
\r
1088 // IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated
\r
1090 ///////////////////////////////////////////////////////////////////////////
\r
1092 IN_FreeDemoBuffer(void)
\r
1095 MM_FreePtr((memptr *)&DemoBuffer);
\r
1100 ///////////////////////////////////////////////////////////////////////////
\r
1102 // IN_GetScanName() - Returns a string containing the name of the
\r
1103 // specified scan code
\r
1105 ///////////////////////////////////////////////////////////////////////////
\r
1107 IN_GetScanName(ScanCode scan)
\r
1112 for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)
\r
1116 return(ScanNames[scan]);
\r
1119 ///////////////////////////////////////////////////////////////////////////
\r
1121 // IN_WaitForKey() - Waits for a scan code, then clears LastScan and
\r
1122 // returns the scan code
\r
1124 ///////////////////////////////////////////////////////////////////////////
\r
1126 IN_WaitForKey(void)
\r
1130 while (!(result = inst.LastScan))
\r
1132 inst.LastScan = 0;
\r
1136 ///////////////////////////////////////////////////////////////////////////
\r
1138 // IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
\r
1139 // returns the ASCII value
\r
1141 ///////////////////////////////////////////////////////////////////////////
\r
1143 IN_WaitForASCII(void)
\r
1147 while (!(result = inst.LastASCII))
\r
1149 inst.LastASCII = '\0';
\r
1153 ///////////////////////////////////////////////////////////////////////////
\r
1155 // IN_Ack() - waits for a button or key press. If a button is down, upon
\r
1156 // calling, it must be released for it to be recognized
\r
1158 ///////////////////////////////////////////////////////////////////////////
\r
1160 boolean btnstate[8];
\r
1162 void IN_StartAck(global_game_variables_t *gvar)
\r
1164 unsigned i,buttons;
\r
1167 // get initial state of everything
\r
1169 IN_ClearKeysDown();
\r
1170 memset (btnstate,0,sizeof(btnstate));
\r
1172 buttons = IN_JoyButtons () << 4;
\r
1173 if (gvar->in.MousePresent)
\r
1174 buttons |= IN_MouseButtons (gvar);
\r
1176 for (i=0;i<8;i++,buttons>>=1)
\r
1178 btnstate[i] = true;
\r
1182 boolean IN_CheckAck (global_game_variables_t *gvar)
\r
1184 unsigned i,buttons;
\r
1187 // see if something has been pressed
\r
1189 if(!gvar->in.IN_Started)
\r
1193 if (inst.LastScan)
\r
1197 buttons = IN_JoyButtons () << 4;
\r
1198 if (gvar->in.MousePresent)
\r
1199 buttons |= IN_MouseButtons (gvar);
\r
1201 for (i=0;i<8;i++,buttons>>=1)
\r
1208 btnstate[i]=false;
\r
1214 void IN_Ack (global_game_variables_t *gvar)
\r
1216 IN_StartAck (gvar);
\r
1218 while (!IN_CheckAck (gvar))
\r
1222 ///////////////////////////////////////////////////////////////////////////
\r
1224 // IN_IsUserInput() - Returns true if a key has been pressed or a button
\r
1227 ///////////////////////////////////////////////////////////////////////////
\r
1229 IN_IsUserInput(global_game_variables_t *gvar)
\r
1234 result = inst.LastScan;
\r
1236 if (gvar->in.MousePresent)
\r
1237 if (INL_GetMouseButtons())
\r
1240 for (i = 0;i < MaxJoys;i++)
\r
1241 if (gvar->in.JoysPresent[i])
\r
1242 if (INL_GetJoyButtons(i))
\r
1248 ///////////////////////////////////////////////////////////////////////////
\r
1250 // IN_UserInput() - Waits for the specified delay time (in ticks) or the
\r
1251 // user pressing a key or a mouse button. If the clear flag is set, it
\r
1252 // then either clears the key or waits for the user to let the mouse
\r
1255 ///////////////////////////////////////////////////////////////////////////
\r
1256 boolean IN_UserInput(word delay, global_game_variables_t *gvar)
\r
1258 word TimeCount = *clockw;
\r
1261 lasttime = TimeCount;
\r
1262 IN_StartAck (gvar);
\r
1265 if (IN_CheckAck(gvar))
\r
1267 } while (TimeCount - lasttime < delay);
\r
1271 //===========================================================================
\r
1274 ===================
\r
1278 ===================
\r
1281 byte IN_MouseButtons (global_game_variables_t *gvar)
\r
1283 if (gvar->in.MousePresent)
\r
1294 ===================
\r
1298 ===================
\r
1301 byte IN_JoyButtons (void)
\r
1305 joybits = inportb(0x201); // Get all the joystick buttons
\r
1306 joybits >>= 4; // only the high bits are useful
\r
1307 joybits ^= 15; // return with 1=pressed
\r
1312 boolean IN_KeyDown(byte code)
\r
1314 #ifdef __DEBUG_InputMgr__
\r
1315 // if(inst.Keyboard[code])
\r
1316 // printf("IN_KeyDown(%c): %u\n", code, inst.Keyboard[code]);
\r
1319 return inst.Keyboard[code];
\r
1320 #ifdef __DEBUG_InputMgr__
\r
1322 if(dbg_nointest && kbhit())
\r
1329 void IN_ClearKey(byte code)
\r
1331 inst.Keyboard[code] = false;
\r
1332 if(code == inst.LastScan)
\r
1333 inst.LastScan = sc_None;
\r
1336 boolean IN_qb(byte kee)
\r
1338 #ifdef __DEBUG_InputMgr__
\r
1339 if(dbg_testkeyin) if(inst.Keyboard[kee]) printf("IN_qb(): %u\n", inst.Keyboard[kee]);
\r
1341 if(inst.Keyboard[kee]==true) return 1;
\r
1345 ScanCode IN_GetLastScan()
\r
1347 return inst.LastScan;
\r
1350 ScanCode IN_GetCurCode()
\r
1352 return inst.CurCode;
\r
1357 byte far *lock_key;
\r
1359 // turn off num-lock via BIOS
\r
1360 lock_key = MK_FP(0x040, 0x017); // Pointing to the address of the bios shift state keys
\r
1361 *lock_key&=(~(16 | 32 | 64)); // toggle off the locks by changing the values of the 4th, 5th, and 6th bits of the address byte of 0040:0017
\r
1362 OldKeyVect(); // call BIOS keyhandler to change keyboard lights
\r