1 /* Catacomb Apocalypse 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
24 // Open Watcom port by sparky4
\r
28 // This module handles dealing with the various input devices
\r
30 // Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
\r
31 // User Mgr (for command line parms)
\r
34 // LastScan - The keyboard scan code of the last key pressed
\r
35 // LastASCII - The ASCII value of the last key pressed
\r
36 // DEBUG - there are more globals
\r
39 #include "src/lib/16_in.h"
\r
41 boolean testkeyin=0,testcontrolnoisy=0,testctrltype=0;
\r
44 =============================================================================
\r
48 =============================================================================
\r
52 boolean MousePresent;
\r
53 boolean JoysPresent[MaxJoys];
\r
54 boolean Keyboard[NumCodes];
\r
59 KeyboardDef KbdDefs[MaxKbds];
\r
60 JoystickDef JoyDefs[MaxJoys];
\r
63 //extern inconfig inpu;
\r
64 //inpu.KbdDefs = {0x1d,0x38,/*0x47,*/0x48,/*0x49,*/0x4b,0x4d,/*0x4f,*/0x50/*,0x51*/};
\r
67 =============================================================================
\r
71 =============================================================================
\r
74 #ifdef __cplusplus /* Function must be declared C style */
\r
78 static struct instat {
\r
81 ScanCode CurCode,LastCode;
\r
84 static void (*INL_KeyHook)(void);
\r
85 static void interrupt (*OldKeyVect)(void);
\r
86 static char *ParmStringsIN[] = {"nojoys","nomouse",nil};
\r
88 static byte far ASCIINames[] = // Unshifted ASCII for scan codes
\r
90 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
\r
91 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0
\r
92 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1
\r
93 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2
\r
94 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
\r
95 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
\r
96 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
\r
97 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
\r
98 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
\r
100 far ShiftNames[] = // Shifted ASCII for scan codes
\r
102 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
\r
103 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0
\r
104 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1
\r
105 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2
\r
106 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
\r
107 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
\r
108 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
\r
109 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
\r
110 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
\r
112 far SpecialNames[] = // ASCII for 0xe0 prefixed codes
\r
114 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
\r
115 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0
\r
116 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1
\r
117 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2
\r
118 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3
\r
119 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4
\r
120 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
\r
121 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
\r
122 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
\r
124 *ScanNames[] = // Scan code names with single chars
\r
126 "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",
\r
127 "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",
\r
128 "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",
\r
129 "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",
\r
130 "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",
\r
131 "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
\r
132 "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
\r
133 "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"
\r
134 }, // DEBUG - consolidate these
\r
135 far ExtScanCodes[] = // Scan codes with >1 char names
\r
137 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,
\r
138 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,
\r
139 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,
\r
140 0x50,0x4b,0x4d,0x00
\r
142 *ExtScanNames[] = // Names corresponding to ExtScanCodes
\r
144 "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",
\r
145 "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",
\r
146 "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",
\r
147 "Down","Left","Right",""
\r
150 static Direction DirTable[] = // Quick lookup for total direction
\r
166 // Internal routines
\r
167 ///////////////////////////////////////////////////////////////////////////
\r
169 // INL_KeyService() - Handles a keyboard interrupt (key up/down)
\r
171 ///////////////////////////////////////////////////////////////////////////
\r
175 static boolean special;
\r
177 register byte temp;
\r
179 k = inp(0x60); // Get the scan code
\r
181 // Tell the XT keyboard controller to clear the key
\r
182 outp(0x61,(temp = inp(0x61)) | 0x80);
\r
185 if (k == 0xe0) // Special key prefix
\r
187 else if (k == 0xe1) // Handle Pause key
\r
188 inpu.Paused = true;
\r
191 if (k & 0x80) // Break code
\r
195 // DEBUG - handle special keys: ctl-alt-delete, print scrn
\r
197 inpu.Keyboard[k] = false;
\r
201 inst.LastCode = inst.CurCode;
\r
202 inst.CurCode = inpu.LastScan = k;
\r
203 inpu.Keyboard[k] = true;
\r
206 c = SpecialNames[k];
\r
209 if (k == sc_CapsLock)
\r
211 inst.CapsLock ^= true;
\r
212 // DEBUG - make caps lock light work
\r
215 if (inpu.Keyboard[sc_LShift] || inpu.Keyboard[sc_RShift]) // If shifted
\r
218 if ((c >= 'A') && (c <= 'Z') && inst.CapsLock)
\r
224 if ((c >= 'a') && (c <= 'z') && inst.CapsLock)
\r
229 inpu.LastASCII = c;
\r
235 if (INL_KeyHook && !special)
\r
238 if(testkeyin > 0) printf("%c %u [0x%x %u] %u\n", c, c, k, k, inpu.Keyboard[k]);
\r
246 union REGS CPURegs;
\r
248 int86(MouseInt,&CPURegs,&CPURegs);
\r
251 ///////////////////////////////////////////////////////////////////////////
\r
253 // INL_GetMouseDelta() - Gets the amount that the mouse has moved from the
\r
256 ///////////////////////////////////////////////////////////////////////////
\r
258 INL_GetMouseDelta(int *x,int *y)
\r
260 union REGS CPURegs;
\r
266 ///////////////////////////////////////////////////////////////////////////
\r
268 // INL_GetMouseButtons() - Gets the status of the mouse buttons from the
\r
271 ///////////////////////////////////////////////////////////////////////////
\r
273 INL_GetMouseButtons(void)
\r
275 union REGS CPURegs;
\r
279 buttons = CPURegs.x.bx;
\r
283 ///////////////////////////////////////////////////////////////////////////
\r
285 // IN_GetJoyAbs() - Reads the absolute position of the specified joystick
\r
287 ///////////////////////////////////////////////////////////////////////////
\r
289 IN_GetJoyAbs(word joy,word *xp,word *yp)
\r
296 xs = joy? 2 : 0; // Find shift value for x axis
\r
297 xb = 1 << xs; // Use shift value to get x bit mask
\r
298 ys = joy? 3 : 1; // Do the same for y axis
\r
301 // Read the absolute joystick values
\r
304 pushf // Save some registers
\r
307 cli // Make sure an interrupt doesn't screw the timings
\r
312 out dx,al // Clear the resistors
\r
314 mov ah,[xb] // Get masks into registers
\r
317 xor si,si // Clear count registers
\r
319 xor bh,bh // Clear high byte of bx for later
\r
321 push bp // Don't mess up stack frame
\r
325 in al,dx // Get bits indicating whether all are finished
\r
327 dec bp // Check bounding register
\r
328 jz done // We have a silly value - abort
\r
330 mov bl,al // Duplicate the bits
\r
331 and bl,ah // Mask off useless bits (in [xb])
\r
332 add si,bx // Possibly increment count register
\r
333 mov cl,bl // Save for testing later
\r
340 jnz loo // If both bits were 0, drop out
\r
345 mov cl,[xs] // Get the number of bits to shift
\r
346 shr si,cl // and shift the count that many times
\r
351 mov [x],si // Store the values into the variables
\r
356 popf // Restore the registers
\r
363 ///////////////////////////////////////////////////////////////////////////
\r
365 // INL_GetJoyDelta() - Returns the relative movement of the specified
\r
366 // joystick (from +/-127, scaled adaptively)
\r
368 ///////////////////////////////////////////////////////////////////////////
\r
370 INL_GetJoyDelta(word joy,int *dx,int *dy,boolean adaptive)
\r
374 word TimeCount = *clockw;
\r
376 static word lasttime;
\r
378 IN_GetJoyAbs(joy,&x,&y);
\r
379 def = inpu.JoyDefs + joy;
\r
381 //TODO: inject p16 input controls!
\r
383 /* if(DIRECTIONIFELSE)
\r
385 if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){
\r
386 if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]))
\r
388 if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up]))
\r
390 }else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){
\r
391 if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]))
\r
393 if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left]))// || player[pn].pdir != 1)
\r
396 //if(mx+my!=1 && mx+my!=-1 && mx!=my!=0)
\r
398 switch (player[pn].pdir)
\r
402 if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right])) dir = DirTable[1];
\r
403 else if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left])) dir = DirTable[3];
\r
407 if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down])) dir = DirTable[0];
\r
408 else if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up])) dir = DirTable[4];
\r
413 if(testcontrolnoisy > 0){ printf("dir=%c ", dirchar(dir)); printf("pdir=%c ", dirchar(player[pn].pdir)); }
\r
414 }//else printf(" ");
\r
416 if (x < def->threshMinX)
\r
418 if (x < def->joyMinX)
\r
421 x = -(x - def->threshMinX);
\r
422 x *= def->joyMultXL;
\r
423 x >>= JoyScaleShift;
\r
424 *dx = (x > 127)? -127 : -x;
\r
426 else if (x > def->threshMaxX)
\r
428 if (x > def->joyMaxX)
\r
431 x = x - def->threshMaxX;
\r
432 x *= def->joyMultXH;
\r
433 x >>= JoyScaleShift;
\r
434 *dx = (x > 127)? 127 : x;
\r
439 if (y < def->threshMinY)
\r
441 if (y < def->joyMinY)
\r
444 y = -(y - def->threshMinY);
\r
445 y *= def->joyMultYL;
\r
446 y >>= JoyScaleShift;
\r
447 *dy = (y > 127)? -127 : -y;
\r
449 else if (y > def->threshMaxY)
\r
451 if (y > def->joyMaxY)
\r
454 y = y - def->threshMaxY;
\r
455 y *= def->joyMultYH;
\r
456 y >>= JoyScaleShift;
\r
457 *dy = (y > 127)? 127 : y;
\r
464 time = (TimeCount - lasttime) / 2;
\r
473 lasttime = TimeCount;
\r
476 ///////////////////////////////////////////////////////////////////////////
\r
478 // INL_GetJoyButtons() - Returns the button status of the specified
\r
481 ///////////////////////////////////////////////////////////////////////////
\r
483 INL_GetJoyButtons(word joy)
\r
485 register word result;
\r
487 result = inp(0x201); // Get all the joystick buttons
\r
488 result >>= joy? 6 : 4; // Shift into bits 0-1
\r
489 result &= 3; // Mask off the useless bits
\r
494 ///////////////////////////////////////////////////////////////////////////
\r
496 // IN_GetJoyButtonsDB() - Returns the de-bounced button status of the
\r
497 // specified joystick
\r
499 ///////////////////////////////////////////////////////////////////////////
\r
501 IN_GetJoyButtonsDB(word joy)
\r
503 word TimeCount = *clockw;
\r
505 word result1,result2;
\r
509 result1 = INL_GetJoyButtons(joy);
\r
510 lasttime = TimeCount;
\r
511 while(TimeCount == lasttime)
\r
512 result2 = INL_GetJoyButtons(joy);
\r
513 } while(result1 != result2);
\r
517 ///////////////////////////////////////////////////////////////////////////
\r
519 // INL_StartKbd() - Sets up my keyboard stuff for use
\r
521 ///////////////////////////////////////////////////////////////////////////
\r
525 INL_KeyHook = 0; // Clear key hook
\r
527 IN_ClearKeysDown();
\r
529 OldKeyVect = _dos_getvect(KeyInt);
\r
530 _dos_setvect(KeyInt,INL_KeyService);
\r
533 ///////////////////////////////////////////////////////////////////////////
\r
535 // INL_ShutKbd() - Restores keyboard control to the BIOS
\r
537 ///////////////////////////////////////////////////////////////////////////
\r
541 pokeb(0x40,0x17,peekb(0x40,0x17) & 0xfaf0); // Clear ctrl/alt/shift flags
\r
543 _dos_setvect(KeyInt,OldKeyVect);
\r
546 ///////////////////////////////////////////////////////////////////////////
\r
548 // INL_StartMouse() - Detects and sets up the mouse
\r
550 ///////////////////////////////////////////////////////////////////////////
\r
552 INL_StartMouse(void)
\r
554 union REGS CPURegs;
\r
555 if(_dos_getvect(MouseInt))
\r
558 if(CPURegs.x.ax == 0xffff)
\r
564 ///////////////////////////////////////////////////////////////////////////
\r
566 // INL_ShutMouse() - Cleans up after the mouse
\r
568 ///////////////////////////////////////////////////////////////////////////
\r
570 INL_ShutMouse(void)
\r
575 // INL_SetJoyScale() - Sets up scaling values for the specified joystick
\r
578 INL_SetJoyScale(word joy)
\r
582 def = &(inpu.JoyDefs[joy]);
\r
583 def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);
\r
584 def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);
\r
585 def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);
\r
586 def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);
\r
589 ///////////////////////////////////////////////////////////////////////////
\r
591 // IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()
\r
592 // to set up scaling values
\r
594 ///////////////////////////////////////////////////////////////////////////
\r
596 IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)
\r
601 def = &(inpu.JoyDefs[joy]);
\r
603 def->joyMinX = minx;
\r
604 def->joyMaxX = maxx;
\r
607 def->threshMinX = ((r / 2) - d) + minx;
\r
608 def->threshMaxX = ((r / 2) + d) + minx;
\r
610 def->joyMinY = miny;
\r
611 def->joyMaxY = maxy;
\r
614 def->threshMinY = ((r / 2) - d) + miny;
\r
615 def->threshMaxY = ((r / 2) + d) + miny;
\r
617 INL_SetJoyScale(joy);
\r
620 ///////////////////////////////////////////////////////////////////////////
\r
622 // INL_StartJoy() - Detects & auto-configures the specified joystick
\r
623 // The auto-config assumes the joystick is centered
\r
625 ///////////////////////////////////////////////////////////////////////////
\r
627 INL_StartJoy(word joy)
\r
631 IN_GetJoyAbs(joy,&x,&y);
\r
635 ((x == 0) || (x > MaxJoyValue - 10))
\r
636 || ((y == 0) || (y > MaxJoyValue - 10))
\r
641 IN_SetupJoy(joy,0,x * 2,0,y * 2);
\r
646 ///////////////////////////////////////////////////////////////////////////
\r
648 // INL_ShutJoy() - Cleans up the joystick stuff
\r
650 ///////////////////////////////////////////////////////////////////////////
\r
652 INL_ShutJoy(word joy)
\r
654 inpu.JoysPresent[joy] = false;
\r
659 ///////////////////////////////////////////////////////////////////////////
\r
661 // IN_Startup() - Starts up the Input Mgr
\r
663 ///////////////////////////////////////////////////////////////////////////
\r
667 boolean checkjoys,checkmouse;
\r
670 if (inst.IN_Started)
\r
675 for (i = 1;i < __argc;i++)
\r
677 switch (US_CheckParm(__argv[i],ParmStringsIN))
\r
683 checkmouse = false;
\r
689 inpu.MousePresent = checkmouse? INL_StartMouse() : false;
\r
691 for (i = 0;i < MaxJoys;i++)
\r
692 inpu.JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;
\r
694 inst.IN_Started = true;
\r
698 ///////////////////////////////////////////////////////////////////////////
\r
700 // IN_Default() - Sets up default conditions for the Input Mgr
\r
702 ///////////////////////////////////////////////////////////////////////////
\r
704 IN_Default(boolean gotit,player_t *player,ControlType nt)
\r
707 if(testctrltype==0)
\r
711 || ((nt == ctrl_Joystick1) && !inpu.JoysPresent[0])
\r
712 || ((nt == ctrl_Joystick2) && !inpu.JoysPresent[1])
\r
713 || ((nt == ctrl_Mouse) && !inpu.MousePresent)
\r
715 nt = ctrl_Keyboard1;
\r
716 inpu.KbdDefs[0].button0 = 0x1c;
\r
717 inpu.KbdDefs[0].button1 = 0x38;
\r
718 //in.KbdDefs[0].upleft = 0x47;
\r
719 inpu.KbdDefs[0].up = 0x48;
\r
720 //in.KbdDefs[0].upright = 0x49;
\r
721 inpu.KbdDefs[0].left = 0x4b;
\r
722 inpu.KbdDefs[0].right = 0x4d;
\r
723 //in.KbdDefs[0].downleft = 0x4f;
\r
724 inpu.KbdDefs[0].down = 0x50;
\r
725 //in.KbdDefs[0].downright = 0x51;
\r
726 IN_SetControlType(0,player,nt);
\r
727 for(i=0; i>MaxPlayers;i++)
\r
731 ///////////////////////////////////////////////////////////////////////////
\r
733 // IN_Shutdown() - Shuts down the Input Mgr
\r
735 ///////////////////////////////////////////////////////////////////////////
\r
741 if (!inst.IN_Started)
\r
745 for (i = 0;i < MaxJoys;i++)
\r
749 inst.IN_Started = false;
\r
752 ///////////////////////////////////////////////////////////////////////////
\r
754 // IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()
\r
755 // everytime a real make/break code gets hit
\r
757 ///////////////////////////////////////////////////////////////////////////
\r
759 IN_SetKeyHook(void (*hook)())
\r
761 INL_KeyHook = hook;
\r
764 ///////////////////////////////////////////////////////////////////////////
\r
766 // IN_ClearKeyDown() - Clears the keyboard array
\r
768 ///////////////////////////////////////////////////////////////////////////
\r
774 inpu.LastScan = sc_None;
\r
775 inpu.LastASCII = key_None;
\r
776 memset (inpu.Keyboard,0,sizeof(inpu.Keyboard));
\r
779 ///////////////////////////////////////////////////////////////////////////
\r
781 // INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()
\r
783 ///////////////////////////////////////////////////////////////////////////
\r
785 INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)
\r
787 if (buttons & (1 << 0))
\r
788 info->button0 = true;
\r
789 if (buttons & (1 << 1))
\r
790 info->button1 = true;
\r
796 ///////////////////////////////////////////////////////////////////////////
\r
798 // IN_ReadCursor() - Reads the input devices and fills in the cursor info
\r
801 ///////////////////////////////////////////////////////////////////////////
\r
803 IN_ReadCursor(CursorInfo *info)
\r
809 info->x = info->y = 0;
\r
810 info->button0 = info->button1 = false;
\r
812 if (inpu.MousePresent)
\r
814 buttons = INL_GetMouseButtons();
\r
815 INL_GetMouseDelta(&dx,&dy);
\r
816 INL_AdjustCursor(info,buttons,dx,dy);
\r
819 for (i = 0;i < MaxJoys;i++)
\r
821 if (!inpu.JoysPresent[i])
\r
824 buttons = INL_GetJoyButtons(i);
\r
825 INL_GetJoyDelta(i,&dx,&dy,true);
\r
828 INL_AdjustCursor(info,buttons,dx,dy);
\r
832 ///////////////////////////////////////////////////////////////////////////
\r
834 // IN_ReadControl() - Reads the device associated with the specified
\r
835 // player and fills in the control info struct
\r
837 ///////////////////////////////////////////////////////////////////////////
\r
839 IN_ReadControl(int pn,player_t *player)
\r
848 byte dir=DirTable[2];
\r
849 register KeyboardDef *def;
\r
852 mx = my = motion_None;
\r
856 if (DemoMode == demo_Playback)
\r
858 dbyte = DemoBuffer[DemoOffset + 1];
\r
859 my = (dbyte & 3) - 1;
\r
860 mx = ((dbyte >> 2) & 3) - 1;
\r
861 buttons = (dbyte >> 4) & 3;
\r
863 if (!(--DemoBuffer[DemoOffset]))
\r
866 if (DemoOffset >= DemoSize)
\r
867 DemoMode = demo_PlayDone;
\r
872 else if (DemoMode == demo_PlayDone)
\r
873 Quit("Demo playback exceeded");
\r
877 if(testctrltype>0) printf("player[pn].Controls=%c\n", player[pn].Controls);
\r
878 switch (type = player[pn].Controls)
\r
880 case ctrl_Keyboard1:
\r
881 case ctrl_Keyboard2:
\r
882 def = &(inpu.KbdDefs[type - ctrl_Keyboard]);
\r
884 /* if (Keyboard[def->upleft])
\r
885 mx = motion_Left,my = motion_Up;
\r
886 else if (Keyboard[def->upright])
\r
887 mx = motion_Right,my = motion_Up;
\r
888 else if (Keyboard[def->downleft])
\r
889 mx = motion_Left,my = motion_Down;
\r
890 else if (Keyboard[def->downright])
\r
891 mx = motion_Right,my = motion_Down;*/
\r
892 if(DIRECTIONIFELSE)
\r
894 if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){
\r
895 if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]))
\r
897 if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up]))
\r
899 }else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){
\r
900 if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]))
\r
902 if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left]))// || player[pn].pdir != 1)
\r
905 //if(mx+my!=1 && mx+my!=-1 && mx!=my!=0)
\r
907 switch (player[pn].pdir)
\r
911 if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right])) dir = DirTable[1];
\r
912 else if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left])) dir = DirTable[3];
\r
916 if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down])) dir = DirTable[0];
\r
917 else if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up])) dir = DirTable[4];
\r
922 if(testcontrolnoisy > 0){ printf("dir=%c ", dirchar(dir)); printf("pdir=%c ", dirchar(player[pn].pdir)); }
\r
923 }//else printf(" ");
\r
925 //input from player
\r
926 if (inpu.Keyboard[def->button0])
\r
928 if (inpu.Keyboard[def->button1])
\r
932 case ctrl_Joystick1:
\r
933 case ctrl_Joystick2:
\r
934 INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
\r
935 buttons = INL_GetJoyButtons(type - ctrl_Joystick);
\r
939 INL_GetMouseDelta(&dx,&dy);
\r
940 buttons = INL_GetMouseButtons();
\r
950 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
\r
951 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
\r
959 player[pn].info.x = dx;
\r
960 player[pn].info.xaxis = mx;
\r
961 player[pn].info.y = dy;
\r
962 player[pn].info.yaxis = my;
\r
963 player[pn].info.button0 = buttons & (1 << 0);
\r
964 player[pn].info.button1 = buttons & (1 << 1);
\r
965 player[pn].info.button2 = buttons & (1 << 2);
\r
966 player[pn].info.button3 = buttons & (1 << 3);
\r
967 // player[pn].info.dir = DirTable[((my + 1) * 3) + (mx + 1)];
\r
968 conpee=(((my + 1) * 2) + (mx + 1))-1;
\r
969 player[pn].info.dir = DirTable[conpee];
\r
971 if(DirTable[conpee]!=2) player[pn].pdir=DirTable[conpee];
\r
972 if(player[pn].q==1 &&( dir!=2 || (mx!=motion_None || my!=motion_None)))
\r
974 if(dir==2) player[pn].d = player[pn].info.dir;
\r
975 else player[pn].d = DirTable[dir];
\r
979 if (DemoMode == demo_Record)
\r
981 // Pack the control info into a byte
\r
982 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
\r
986 (DemoBuffer[DemoOffset + 1] == dbyte)
\r
987 && (DemoBuffer[DemoOffset] < 255)
\r
989 (DemoBuffer[DemoOffset])++;
\r
992 if (DemoOffset || DemoBuffer[DemoOffset])
\r
995 if (DemoOffset >= DemoSize)
\r
996 Quit("Demo buffer overflow");
\r
998 DemoBuffer[DemoOffset] = 1;
\r
999 DemoBuffer[DemoOffset + 1] = dbyte;
\r
1003 //#ifdef TESTCONTROLNOISY
\r
1004 if(testcontrolnoisy > 0)
\r
1005 if((inpu.Keyboard[def->up] || inpu.Keyboard[def->down] || inpu.Keyboard[def->left] || inpu.Keyboard[def->right]) || player[pn].q>1)
\r
1007 printf("q=%d ", player[pn].q);
\r
1008 printf("cpee=%c ", dirchar(conpee));
\r
1009 //printf("(mx)=%d ", mx);
\r
1010 //printf("(my)=%d ", my);
\r
1011 //printf("[%d] ", mx+my);
\r
1012 printf("pdir=%c d=%c dir=%c ", dirchar(player[pn].pdir), dirchar(player[pn].d), dirchar(player[pn].info.dir));
\r
1013 printf("%c%d %c%d %c%d %c%d\n", dirchar(0), inpu.Keyboard[def->up], dirchar(4), inpu.Keyboard[def->down], dirchar(1), inpu.Keyboard[def->left], dirchar(3), inpu.Keyboard[def->right]);
\r
1018 ///////////////////////////////////////////////////////////////////////////
\r
1020 // IN_SetControlType() - Sets the control type to be used by the specified
\r
1023 ///////////////////////////////////////////////////////////////////////////
\r
1025 IN_SetControlType(word pn,player_t *player,ControlType type)
\r
1027 // DEBUG - check that requested type is present?
\r
1028 player[pn].Controls = type;
\r
1032 ///////////////////////////////////////////////////////////////////////////
\r
1034 // IN_StartDemoRecord() - Starts the demo recording, using a buffer the
\r
1035 // size passed. Returns if the buffer allocation was successful
\r
1037 ///////////////////////////////////////////////////////////////////////////
\r
1039 IN_StartDemoRecord(word bufsize)
\r
1044 MM_GetPtr((memptr *)&DemoBuffer,bufsize);
\r
1045 DemoMode = demo_Record;
\r
1046 DemoSize = bufsize & ~1;
\r
1048 DemoBuffer[0] = DemoBuffer[1] = 0;
\r
1053 ///////////////////////////////////////////////////////////////////////////
\r
1055 // IN_StartDemoPlayback() - Plays back the demo pointed to of the given size
\r
1057 ///////////////////////////////////////////////////////////////////////////
\r
1059 IN_StartDemoPlayback(byte /*__segment*/ *buffer,word bufsize)
\r
1061 DemoBuffer = buffer;
\r
1062 DemoMode = demo_Playback;
\r
1063 DemoSize = bufsize & ~1;
\r
1067 ///////////////////////////////////////////////////////////////////////////
\r
1069 // IN_StopDemo() - Turns off demo mode
\r
1071 ///////////////////////////////////////////////////////////////////////////
\r
1075 if ((DemoMode == demo_Record) && DemoOffset)
\r
1078 DemoMode = demo_Off;
\r
1081 ///////////////////////////////////////////////////////////////////////////
\r
1083 // IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated
\r
1085 ///////////////////////////////////////////////////////////////////////////
\r
1087 IN_FreeDemoBuffer(void)
\r
1090 MM_FreePtr((memptr *)&DemoBuffer);
\r
1095 ///////////////////////////////////////////////////////////////////////////
\r
1097 // IN_GetScanName() - Returns a string containing the name of the
\r
1098 // specified scan code
\r
1100 ///////////////////////////////////////////////////////////////////////////
\r
1102 IN_GetScanName(ScanCode scan)
\r
1107 for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)
\r
1111 return(ScanNames[scan]);
\r
1114 ///////////////////////////////////////////////////////////////////////////
\r
1116 // IN_WaitForKey() - Waits for a scan code, then clears LastScan and
\r
1117 // returns the scan code
\r
1119 ///////////////////////////////////////////////////////////////////////////
\r
1125 while (!(result = inpu.LastScan))
\r
1127 inpu.LastScan = 0;
\r
1131 ///////////////////////////////////////////////////////////////////////////
\r
1133 // IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
\r
1134 // returns the ASCII value
\r
1136 ///////////////////////////////////////////////////////////////////////////
\r
1142 while (!(result = inpu.LastASCII))
\r
1144 inpu.LastASCII = '\0';
\r
1148 ///////////////////////////////////////////////////////////////////////////
\r
1150 // IN_AckBack() - Waits for either an ASCII keypress or a button press
\r
1152 ///////////////////////////////////////////////////////////////////////////
\r
1158 while (!inpu.LastScan)
\r
1160 if (inpu.MousePresent)
\r
1162 if (INL_GetMouseButtons())
\r
1164 while (INL_GetMouseButtons())
\r
1170 for (i = 0;i < MaxJoys;i++)
\r
1172 if (inpu.JoysPresent[i])
\r
1174 if (IN_GetJoyButtonsDB(i))
\r
1176 while (IN_GetJoyButtonsDB(i))
\r
1184 IN_ClearKey(inpu.LastScan);
\r
1185 inpu.LastScan = sc_None;
\r
1188 ///////////////////////////////////////////////////////////////////////////
\r
1190 // IN_Ack() - Clears user input & then calls IN_AckBack()
\r
1192 ///////////////////////////////////////////////////////////////////////////
\r
1198 IN_ClearKey(inpu.LastScan);
\r
1199 inpu.LastScan = sc_None;
\r
1201 if (inpu.MousePresent)
\r
1202 while (INL_GetMouseButtons())
\r
1204 for (i = 0;i < MaxJoys;i++)
\r
1205 if (inpu.JoysPresent[i])
\r
1206 while (IN_GetJoyButtonsDB(i))
\r
1212 ///////////////////////////////////////////////////////////////////////////
\r
1214 // IN_IsUserInput() - Returns true if a key has been pressed or a button
\r
1217 ///////////////////////////////////////////////////////////////////////////
\r
1224 result = inpu.LastScan;
\r
1226 if (inpu.MousePresent)
\r
1227 if (INL_GetMouseButtons())
\r
1230 for (i = 0;i < MaxJoys;i++)
\r
1231 if (inpu.JoysPresent[i])
\r
1232 if (INL_GetJoyButtons(i))
\r
1238 ///////////////////////////////////////////////////////////////////////////
\r
1240 // IN_UserInput() - Waits for the specified delay time (in ticks) or the
\r
1241 // user pressing a key or a mouse button. If the clear flag is set, it
\r
1242 // then either clears the key or waits for the user to let the mouse
\r
1245 ///////////////////////////////////////////////////////////////////////////
\r
1247 IN_UserInput(dword delay,boolean clear)
\r
1249 word TimeCount = *clockw;
\r
1252 lasttime = TimeCount;
\r
1255 if (IN_IsUserInput())
\r
1261 } while (TimeCount - lasttime < delay);
\r
1265 boolean IN_KeyDown(byte code)
\r
1267 return inpu.Keyboard[code];
\r
1270 void IN_ClearKey(byte code)
\r
1272 inpu.Keyboard[code] = false;
\r
1273 if(code == inpu.LastScan)
\r
1274 inpu.LastScan = sc_None;
\r
1277 boolean IN_qb(byte kee)
\r
1279 //#ifdef TESTKEYIN
\r
1280 // if(testkeyin > 0) printf("%u\n", inpu.Keyboard[kee]);
\r
1282 if(inpu.Keyboard[kee]==true) return 1;
\r
1287 void IN_initplayer(player_t *player, word pn)
\r
1289 player[pn].x = player[pn].tx*TILEWH;
\r
1290 player[pn].y = player[pn].ty*TILEWH;
\r
1291 player[pn].triggerx = player[pn].tx;
\r
1292 player[pn].triggery = player[pn].ty+1;
\r
1293 /* player[0].info.x = player[0].tx;
\r
1294 player[0].info.xaxis = player[0].tx*TILEWH;
\r
1295 player[0].info.y = player[0].ty;
\r
1296 player[0].info.yaxis = player[0].ty*TILEWH;*/
\r
1300 player[pn].speed=4;
\r
1301 player[pn].persist_aniframe=0;
\r
1302 player[pn].spt=(TILEWH/(player[pn].speed)); //speed per tile wwww
\r