]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_in.c
==== Ib CONTROL DONE./w.sh ./w.sh ==== \(^o^)/
[16.git] / src / lib / 16_in.c
1 /* Catacomb Apocalypse Source Code\r
2  * Copyright (C) 1993-2014 Flat Rock Software\r
3  *\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
8  *\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
13  *\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
17  */\r
18 \r
19 //\r
20 //      ID Engine\r
21 //      ID_IN.c - Input Manager\r
22 //      v1.0d1w\r
23 //      By Jason Blochowiak\r
24 //      Open Watcom port by sparky4\r
25 //\r
26 \r
27 //\r
28 //      This module handles dealing with the various input devices\r
29 //\r
30 //      Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),\r
31 //                              User Mgr (for command line parms)\r
32 //\r
33 //      Globals:\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
37 //\r
38 \r
39 #include "src/lib/16_in.h"\r
40 \r
41 byte testkeyin=0,testcontrolnoisy=0;\r
42 \r
43 /*\r
44 =============================================================================\r
45 \r
46                                         GLOBAL VARIABLES\r
47 \r
48 =============================================================================\r
49 */\r
50 struct inconfig\r
51 {\r
52         boolean                 MousePresent;\r
53         boolean                 JoysPresent[MaxJoys];\r
54         boolean                 JoyPadPresent[MaxPads];\r
55         boolean         Keyboard[NumCodes];\r
56         boolean         Paused;\r
57         char            LastASCII;\r
58         ScanCode        LastScan;\r
59 \r
60         KeyboardDef     KbdDefs[MaxKbds];\r
61         JoystickDef     JoyDefs[MaxJoys];\r
62         JoypadDef       JoypadDefs[MaxPads];\r
63 } inpu;\r
64 \r
65 //extern inconfig inpu;\r
66 //inpu.KbdDefs = {0x1d,0x38,/*0x47,*/0x48,/*0x49,*/0x4b,0x4d,/*0x4f,*/0x50/*,0x51*/};\r
67 \r
68 /*\r
69 =============================================================================\r
70 \r
71                                         LOCAL VARIABLES\r
72 \r
73 =============================================================================\r
74 */\r
75 \r
76 #ifdef __cplusplus              /* Function must be declared C style */\r
77 extern "C" {\r
78 #endif\r
79 \r
80 static struct instat {\r
81         boolean         IN_Started;\r
82         boolean         CapsLock;\r
83         ScanCode        CurCode,LastCode;\r
84 } inst;\r
85 \r
86 static  void                    (*INL_KeyHook)(void);\r
87 static  void interrupt  (*OldKeyVect)(void);\r
88 static  char                    *ParmStringsIN[] = {"nojoys","nomouse",nil};\r
89 \r
90 static  byte        far ASCIINames[] =          // Unshifted ASCII for scan codes\r
91                                         {\r
92 //       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
93         0  ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8  ,9  ,        // 0\r
94         'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0  ,'a','s',        // 1\r
95         'd','f','g','h','j','k','l',';',39 ,'`',0  ,92 ,'z','x','c','v',        // 2\r
96         'b','n','m',',','.','/',0  ,'*',0  ,' ',0  ,0  ,0  ,0  ,0  ,0  ,        // 3\r
97         0  ,0  ,0  ,0  ,0  ,0  ,0  ,'7','8','9','-','4','5','6','+','1',        // 4\r
98         '2','3','0',127,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 5\r
99         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 6\r
100         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0           // 7\r
101                                         },\r
102                                         far ShiftNames[] =              // Shifted ASCII for scan codes\r
103                                         {\r
104 //       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
105         0  ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8  ,9  ,        // 0\r
106         'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0  ,'A','S',        // 1\r
107         'D','F','G','H','J','K','L',':',34 ,'~',0  ,'|','Z','X','C','V',        // 2\r
108         'B','N','M','<','>','?',0  ,'*',0  ,' ',0  ,0  ,0  ,0  ,0  ,0  ,        // 3\r
109         0  ,0  ,0  ,0  ,0  ,0  ,0  ,'7','8','9','-','4','5','6','+','1',        // 4\r
110         '2','3','0',127,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 5\r
111         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 6\r
112         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0           // 7\r
113                                         },\r
114                                         far SpecialNames[] =    // ASCII for 0xe0 prefixed codes\r
115                                         {\r
116 //       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
117         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 0\r
118         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,13 ,0  ,0  ,0  ,        // 1\r
119         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 2\r
120         0  ,0  ,0  ,0  ,0  ,'/',0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 3\r
121         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 4\r
122         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 5\r
123         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 6\r
124         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0           // 7\r
125                                         },\r
126                                         *ScanNames[] =          // Scan code names with single chars\r
127                                         {\r
128         "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",\r
129         "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",\r
130         "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",\r
131         "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",\r
132         "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",\r
133         "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
134         "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
135         "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"\r
136                                         },      // DEBUG - consolidate these\r
137                                         far ExtScanCodes[] =    // Scan codes with >1 char names\r
138                                         {\r
139         1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,\r
140         0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,\r
141         0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,\r
142         0x50,0x4b,0x4d,0x00\r
143                                         },\r
144                                         *ExtScanNames[] =       // Names corresponding to ExtScanCodes\r
145                                         {\r
146         "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",\r
147         "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",\r
148         "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",\r
149         "Down","Left","Right",""\r
150                                         };\r
151 \r
152 static  Direction       DirTable[] =            // Quick lookup for total direction\r
153                                         {\r
154                                                 //dir_Nortinest,\r
155                                                 dir_North,\r
156                                                 dir_West,\r
157                                                 dir_None,\r
158                                                 dir_East,\r
159                                                 dir_South\r
160                                                 //dir_NorthEast,\r
161                                                 //dir_Soutinest,\r
162                                                 //,dir_SouthEast\r
163                                         };\r
164 #ifdef __cplusplus\r
165 }\r
166 #endif\r
167 \r
168 //      Internal routines\r
169 ///////////////////////////////////////////////////////////////////////////\r
170 //\r
171 //      INL_KeyService() - Handles a keyboard interrupt (key up/down)\r
172 //\r
173 ///////////////////////////////////////////////////////////////////////////\r
174 void interrupt\r
175 INL_KeyService()\r
176 {\r
177 static  boolean special;\r
178                 byte    k,c;\r
179                 register byte temp;\r
180 \r
181         k = inp(0x60);  // Get the scan code\r
182 \r
183         // Tell the XT keyboard controller to clear the key\r
184         outp(0x61,(temp = inp(0x61)) | 0x80);\r
185         outp(0x61,temp);\r
186 \r
187         if (k == 0xe0)          // Special key prefix\r
188                 special = true;\r
189         else if (k == 0xe1)     // Handle Pause key\r
190                 inpu.Paused = true;\r
191         else\r
192         {\r
193                 if (k & 0x80)   // Break code\r
194                 {\r
195                         k &= 0x7f;\r
196 \r
197 // DEBUG - handle special keys: ctl-alt-delete, print scrn\r
198 \r
199                         inpu.Keyboard[k] = false;\r
200                 }\r
201                 else                    // Make code\r
202                 {\r
203                         inst.LastCode = inst.CurCode;\r
204                         inst.CurCode = inpu.LastScan = k;\r
205                         inpu.Keyboard[k] = true;\r
206 \r
207                         if (special)\r
208                                 c = SpecialNames[k];\r
209                         else\r
210                         {\r
211                                 if (k == sc_CapsLock)\r
212                                 {\r
213                                         inst.CapsLock ^= true;\r
214                                         // DEBUG - make caps lock light work\r
215                                 }\r
216 \r
217                                 if (inpu.Keyboard[sc_LShift] || inpu.Keyboard[sc_RShift])       // If shifted\r
218                                 {\r
219                                         c = ShiftNames[k];\r
220                                         if ((c >= 'A') && (c <= 'Z') && inst.CapsLock)\r
221                                                 c += 'a' - 'A';\r
222                                 }\r
223                                 else\r
224                                 {\r
225                                         c = ASCIINames[k];\r
226                                         if ((c >= 'a') && (c <= 'z') && inst.CapsLock)\r
227                                                 c -= 'a' - 'A';\r
228                                 }\r
229                         }\r
230                         if (c)\r
231                                 inpu.LastASCII = c;\r
232                 }\r
233 \r
234                 special = false;\r
235         }\r
236 \r
237         if (INL_KeyHook && !special)\r
238                 INL_KeyHook();\r
239 //#ifdef TESTKEYIN\r
240         if(testkeyin > 0) printf("%c    [0x%x %u]       %u\n", c, k, k, inpu.Keyboard[k]);\r
241 //endif\r
242         outp(0x20,0x20);\r
243 }\r
244 \r
245 void\r
246 Mouse(int x)\r
247 {\r
248         union REGS CPURegs;\r
249         x = CPURegs.x.ax;\r
250         int86(MouseInt,&CPURegs,&CPURegs);\r
251 }\r
252 \r
253 ///////////////////////////////////////////////////////////////////////////\r
254 //\r
255 //      INL_GetMouseDelta() - Gets the amount that the mouse has moved from the\r
256 //              mouse driver\r
257 //\r
258 ///////////////////////////////////////////////////////////////////////////\r
259 static void\r
260 INL_GetMouseDelta(int *x,int *y)\r
261 {\r
262         union REGS CPURegs;\r
263         Mouse(MDelta);\r
264         *x = CPURegs.x.cx;\r
265         *y = CPURegs.x.dx;\r
266 }\r
267 \r
268 ///////////////////////////////////////////////////////////////////////////\r
269 //\r
270 //      INL_GetMouseButtons() - Gets the status of the mouse buttons from the\r
271 //              mouse driver\r
272 //\r
273 ///////////////////////////////////////////////////////////////////////////\r
274 static word\r
275 INL_GetMouseButtons(void)\r
276 {\r
277         union REGS CPURegs;\r
278         word    buttons;\r
279 \r
280         Mouse(MButtons);\r
281         buttons = CPURegs.x.bx;\r
282         return(buttons);\r
283 }\r
284 \r
285 ///////////////////////////////////////////////////////////////////////////\r
286 //\r
287 //      IN_GetJoyAbs() - Reads the absolute position of the specified joystick\r
288 //\r
289 ///////////////////////////////////////////////////////////////////////////\r
290 void\r
291 IN_GetJoyAbs(word joy,word *xp,word *yp)\r
292 {\r
293         byte    xb,yb,\r
294                         xs,ys;\r
295         word    x,y;\r
296 \r
297         x = y = 0;\r
298         xs = joy? 2 : 0;                // Find shift value for x axis\r
299         xb = 1 << xs;                   // Use shift value to get x bit mask\r
300         ys = joy? 3 : 1;                // Do the same for y axis\r
301         yb = 1 << ys;\r
302 \r
303 // Read the absolute joystick values\r
304         __asm\r
305         {\r
306                 pushf                           // Save some registers\r
307                 push    si\r
308                 push    di\r
309                 cli                                     // Make sure an interrupt doesn't screw the timings\r
310 \r
311 \r
312                 mov             dx,0x201\r
313                 in              al,dx\r
314                 out             dx,al           // Clear the resistors\r
315 \r
316                 mov             ah,[xb]         // Get masks into registers\r
317                 mov             ch,[yb]\r
318 \r
319                 xor             si,si           // Clear count registers\r
320                 xor             di,di\r
321                 xor             bh,bh           // Clear high byte of bx for later\r
322 \r
323                 push    bp                      // Don't mess up stack frame\r
324                 mov             bp,MaxJoyValue\r
325 \r
326 loo:\r
327                 in              al,dx           // Get bits indicating whether all are finished\r
328 \r
329                 dec             bp                      // Check bounding register\r
330                 jz              done            // We have a silly value - abort\r
331 \r
332                 mov             bl,al           // Duplicate the bits\r
333                 and             bl,ah           // Mask off useless bits (in [xb])\r
334                 add             si,bx           // Possibly increment count register\r
335                 mov             cl,bl           // Save for testing later\r
336 \r
337                 mov             bl,al\r
338                 and             bl,ch           // [yb]\r
339                 add             di,bx\r
340 \r
341                 add             cl,bl\r
342                 jnz             loo             // If both bits were 0, drop out\r
343 \r
344 done:\r
345                 pop             bp\r
346 \r
347                 mov             cl,[xs]         // Get the number of bits to shift\r
348                 shr             si,cl           //  and shift the count that many times\r
349 \r
350                 mov             cl,[ys]\r
351                 shr             di,cl\r
352 \r
353                 mov             [x],si          // Store the values into the variables\r
354                 mov             [y],di\r
355 \r
356                 pop             di\r
357                 pop             si\r
358                 popf                            // Restore the registers\r
359         }\r
360 \r
361         *xp = x;\r
362         *yp = y;\r
363 }\r
364 \r
365 ///////////////////////////////////////////////////////////////////////////\r
366 //\r
367 //      INL_GetJoyDelta() - Returns the relative movement of the specified\r
368 //              joystick (from +/-127, scaled adaptively)\r
369 //\r
370 ///////////////////////////////////////////////////////////////////////////\r
371 static void\r
372 INL_GetJoyDelta(word joy,int *dx,int *dy,boolean adaptive)\r
373 {\r
374         word            x,y;\r
375         word    time;\r
376         word TimeCount = *clockw;\r
377         JoystickDef     *def;\r
378 static  word    lasttime;\r
379 \r
380         IN_GetJoyAbs(joy,&x,&y);\r
381         def = inpu.JoyDefs + joy;\r
382 \r
383         if (x < def->threshMinX)\r
384         {\r
385                 if (x < def->joyMinX)\r
386                         x = def->joyMinX;\r
387 \r
388                 x = -(x - def->threshMinX);\r
389                 x *= def->joyMultXL;\r
390                 x >>= JoyScaleShift;\r
391                 *dx = (x > 127)? -127 : -x;\r
392         }\r
393         else if (x > def->threshMaxX)\r
394         {\r
395                 if (x > def->joyMaxX)\r
396                         x = def->joyMaxX;\r
397 \r
398                 x = x - def->threshMaxX;\r
399                 x *= def->joyMultXH;\r
400                 x >>= JoyScaleShift;\r
401                 *dx = (x > 127)? 127 : x;\r
402         }\r
403         else\r
404                 *dx = 0;\r
405 \r
406         if (y < def->threshMinY)\r
407         {\r
408                 if (y < def->joyMinY)\r
409                         y = def->joyMinY;\r
410 \r
411                 y = -(y - def->threshMinY);\r
412                 y *= def->joyMultYL;\r
413                 y >>= JoyScaleShift;\r
414                 *dy = (y > 127)? -127 : -y;\r
415         }\r
416         else if (y > def->threshMaxY)\r
417         {\r
418                 if (y > def->joyMaxY)\r
419                         y = def->joyMaxY;\r
420 \r
421                 y = y - def->threshMaxY;\r
422                 y *= def->joyMultYH;\r
423                 y >>= JoyScaleShift;\r
424                 *dy = (y > 127)? 127 : y;\r
425         }\r
426         else\r
427                 *dy = 0;\r
428 \r
429         if (adaptive)\r
430         {\r
431                 time = (TimeCount - lasttime) / 2;\r
432                 if (time)\r
433                 {\r
434                         if (time > 8)\r
435                                 time = 8;\r
436                         *dx *= time;\r
437                         *dy *= time;\r
438                 }\r
439         }\r
440         lasttime = TimeCount;\r
441 }\r
442 \r
443 ///////////////////////////////////////////////////////////////////////////\r
444 //\r
445 //      INL_GetJoyButtons() - Returns the button status of the specified\r
446 //              joystick\r
447 //\r
448 ///////////////////////////////////////////////////////////////////////////\r
449 static word\r
450 INL_GetJoyButtons(word joy)\r
451 {\r
452 register        word    result;\r
453 \r
454         result = inp(0x201);    // Get all the joystick buttons\r
455         result >>= joy? 6 : 4;  // Shift into bits 0-1\r
456         result &= 3;                            // Mask off the useless bits\r
457         result ^= 3;\r
458         return(result);\r
459 }\r
460 \r
461 ///////////////////////////////////////////////////////////////////////////\r
462 //\r
463 //      IN_GetJoyButtonsDB() - Returns the de-bounced button status of the\r
464 //              specified joystick\r
465 //\r
466 ///////////////////////////////////////////////////////////////////////////\r
467 word\r
468 IN_GetJoyButtonsDB(word joy)\r
469 {\r
470         word TimeCount = *clockw;\r
471         word    lasttime;\r
472         word            result1,result2;\r
473 \r
474         do\r
475         {\r
476                 result1 = INL_GetJoyButtons(joy);\r
477                 lasttime = TimeCount;\r
478                 while(TimeCount == lasttime)\r
479                 result2 = INL_GetJoyButtons(joy);\r
480         } while(result1 != result2);\r
481         return(result1);\r
482 }\r
483 \r
484 ///////////////////////////////////////////////////////////////////////////\r
485 //\r
486 //      INL_StartKbd() - Sets up my keyboard stuff for use\r
487 //\r
488 ///////////////////////////////////////////////////////////////////////////\r
489 static void\r
490 INL_StartKbd()\r
491 {\r
492         INL_KeyHook = 0;        // Clear key hook\r
493 \r
494         IN_ClearKeysDown();\r
495 \r
496         OldKeyVect = _dos_getvect(KeyInt);\r
497         _dos_setvect(KeyInt,INL_KeyService);\r
498 }\r
499 \r
500 ///////////////////////////////////////////////////////////////////////////\r
501 //\r
502 //      INL_ShutKbd() - Restores keyboard control to the BIOS\r
503 //\r
504 ///////////////////////////////////////////////////////////////////////////\r
505 static void\r
506 INL_ShutKbd(void)\r
507 {\r
508         pokeb(0x40,0x17,peekb(0x40,0x17) & 0xfaf0);     // Clear ctrl/alt/shift flags\r
509 \r
510         _dos_setvect(KeyInt,OldKeyVect);\r
511 }\r
512 \r
513 ///////////////////////////////////////////////////////////////////////////\r
514 //\r
515 //      INL_StartMouse() - Detects and sets up the mouse\r
516 //\r
517 ///////////////////////////////////////////////////////////////////////////\r
518 static boolean\r
519 INL_StartMouse(void)\r
520 {\r
521         union REGS CPURegs;\r
522         if(_dos_getvect(MouseInt))\r
523         {\r
524                 Mouse(MReset);\r
525                 if(CPURegs.x.ax == 0xffff)\r
526                         return(true);\r
527         }\r
528         return(false);\r
529 }\r
530 \r
531 ///////////////////////////////////////////////////////////////////////////\r
532 //\r
533 //      INL_ShutMouse() - Cleans up after the mouse\r
534 //\r
535 ///////////////////////////////////////////////////////////////////////////\r
536 static void\r
537 INL_ShutMouse(void)\r
538 {\r
539 }\r
540 \r
541 //\r
542 //      INL_SetJoyScale() - Sets up scaling values for the specified joystick\r
543 //\r
544 static void\r
545 INL_SetJoyScale(word joy)\r
546 {\r
547         JoystickDef     *def;\r
548 \r
549         def = &(inpu.JoyDefs[joy]);\r
550         def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);\r
551         def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);\r
552         def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);\r
553         def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);\r
554 }\r
555 \r
556 ///////////////////////////////////////////////////////////////////////////\r
557 //\r
558 //      IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()\r
559 //              to set up scaling values\r
560 //\r
561 ///////////////////////////////////////////////////////////////////////////\r
562 void\r
563 IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)\r
564 {\r
565         word            d,r;\r
566         JoystickDef     *def;\r
567 \r
568         def = &(inpu.JoyDefs[joy]);\r
569 \r
570         def->joyMinX = minx;\r
571         def->joyMaxX = maxx;\r
572         r = maxx - minx;\r
573         d = r / 3;\r
574         def->threshMinX = ((r / 2) - d) + minx;\r
575         def->threshMaxX = ((r / 2) + d) + minx;\r
576 \r
577         def->joyMinY = miny;\r
578         def->joyMaxY = maxy;\r
579         r = maxy - miny;\r
580         d = r / 3;\r
581         def->threshMinY = ((r / 2) - d) + miny;\r
582         def->threshMaxY = ((r / 2) + d) + miny;\r
583 \r
584         INL_SetJoyScale(joy);\r
585 }\r
586 \r
587 ///////////////////////////////////////////////////////////////////////////\r
588 //\r
589 //      INL_StartJoy() - Detects & auto-configures the specified joystick\r
590 //                                      The auto-config assumes the joystick is centered\r
591 //\r
592 ///////////////////////////////////////////////////////////////////////////\r
593 static boolean\r
594 INL_StartJoy(word joy)\r
595 {\r
596         word            x,y;\r
597 \r
598         IN_GetJoyAbs(joy,&x,&y);\r
599 \r
600         if\r
601         (\r
602                 ((x == 0) || (x > MaxJoyValue - 10))\r
603         ||      ((y == 0) || (y > MaxJoyValue - 10))\r
604         )\r
605                 return(false);\r
606         else\r
607         {\r
608                 IN_SetupJoy(joy,0,x * 2,0,y * 2);\r
609                 return(true);\r
610         }\r
611 }\r
612 \r
613 ///////////////////////////////////////////////////////////////////////////\r
614 //\r
615 //      INL_ShutJoy() - Cleans up the joystick stuff\r
616 //\r
617 ///////////////////////////////////////////////////////////////////////////\r
618 static void\r
619 INL_ShutJoy(word joy)\r
620 {\r
621         inpu.JoysPresent[joy] = false;\r
622 }\r
623 \r
624 //      Public routines\r
625 \r
626 ///////////////////////////////////////////////////////////////////////////\r
627 //\r
628 //      IN_Startup() - Starts up the Input Mgr\r
629 //\r
630 ///////////////////////////////////////////////////////////////////////////\r
631 void\r
632 IN_Startup()\r
633 {\r
634         boolean checkjoys,checkmouse;\r
635         word    i;\r
636 \r
637         if (inst.IN_Started)\r
638                 return;\r
639 \r
640         checkjoys = true;\r
641         checkmouse = true;\r
642         for (i = 1;i < __argc;i++)\r
643         {\r
644                 switch (US_CheckParm(__argv[i],ParmStringsIN))\r
645                 {\r
646                 case 0:\r
647                         checkjoys = false;\r
648                         break;\r
649                 case 1:\r
650                         checkmouse = false;\r
651                         break;\r
652                 }\r
653         }\r
654 \r
655         INL_StartKbd();\r
656         inpu.MousePresent = checkmouse? INL_StartMouse() : false;\r
657 \r
658         for (i = 0;i < MaxJoys;i++)\r
659                 inpu.JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;\r
660 \r
661         inst.IN_Started = true;\r
662 }\r
663 \r
664 ///////////////////////////////////////////////////////////////////////////\r
665 //\r
666 //      IN_Default() - Sets up default conditions for the Input Mgr\r
667 //\r
668 ///////////////////////////////////////////////////////////////////////////\r
669 void\r
670 IN_Default(boolean gotit,player_t *player,ControlType nt)\r
671 {\r
672         int i;\r
673         if\r
674         (\r
675                 (!gotit)\r
676         ||      ((nt == ctrl_Joystick1) && !inpu.JoysPresent[0])\r
677         ||      ((nt == ctrl_Joystick2) && !inpu.JoysPresent[1])\r
678         ||      ((nt == ctrl_Mouse) && !inpu.MousePresent)\r
679         ||      ((nt == ctrl_Joypad1) && !inpu.JoyPadPresent[0])\r
680         ||      ((nt == ctrl_Joypad2) && !inpu.JoyPadPresent[1])\r
681         )\r
682                 nt = ctrl_Keyboard1;\r
683         inpu.KbdDefs[0].button0 = 0x1c;\r
684         inpu.KbdDefs[0].button1 = 0x38;\r
685         //in.KbdDefs[0].upleft = 0x47;\r
686         inpu.KbdDefs[0].up = 0x48;\r
687         //in.KbdDefs[0].upright = 0x49;\r
688         inpu.KbdDefs[0].left = 0x4b;\r
689         inpu.KbdDefs[0].right = 0x4d;\r
690         //in.KbdDefs[0].downleft = 0x4f;\r
691         inpu.KbdDefs[0].down = 0x50;\r
692         //in.KbdDefs[0].downright = 0x51;\r
693         IN_SetControlType(0,player,nt);\r
694         for(i=0; i>MaxPlayers;i++)\r
695                 player[i].d=2;\r
696 }\r
697 \r
698 ///////////////////////////////////////////////////////////////////////////\r
699 //\r
700 //      IN_Shutdown() - Shuts down the Input Mgr\r
701 //\r
702 ///////////////////////////////////////////////////////////////////////////\r
703 void\r
704 IN_Shutdown()\r
705 {\r
706         word    i;\r
707 \r
708         if (!inst.IN_Started)\r
709                 return;\r
710 \r
711         INL_ShutMouse();\r
712         for (i = 0;i < MaxJoys;i++)\r
713                 INL_ShutJoy(i);\r
714         INL_ShutKbd();\r
715 \r
716         inst.IN_Started = false;\r
717 }\r
718 \r
719 ///////////////////////////////////////////////////////////////////////////\r
720 //\r
721 //      IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()\r
722 //                      everytime a real make/break code gets hit\r
723 //\r
724 ///////////////////////////////////////////////////////////////////////////\r
725 void\r
726 IN_SetKeyHook(void (*hook)())\r
727 {\r
728         INL_KeyHook = hook;\r
729 }\r
730 \r
731 ///////////////////////////////////////////////////////////////////////////\r
732 //\r
733 //      IN_ClearKeyDown() - Clears the keyboard array\r
734 //\r
735 ///////////////////////////////////////////////////////////////////////////\r
736 void\r
737 IN_ClearKeysDown()\r
738 {\r
739         int     i;\r
740 \r
741         inpu.LastScan = sc_None;\r
742         inpu.LastASCII = key_None;\r
743         memset (inpu.Keyboard,0,sizeof(inpu.Keyboard));\r
744 }\r
745 \r
746 ///////////////////////////////////////////////////////////////////////////\r
747 //\r
748 //      INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()\r
749 //\r
750 ///////////////////////////////////////////////////////////////////////////\r
751 static void\r
752 INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)\r
753 {\r
754         if (buttons & (1 << 0))\r
755                 info->button0 = true;\r
756         if (buttons & (1 << 1))\r
757                 info->button1 = true;\r
758 \r
759         info->x += dx;\r
760         info->y += dy;\r
761 }\r
762 \r
763 ///////////////////////////////////////////////////////////////////////////\r
764 //\r
765 //      IN_ReadCursor() - Reads the input devices and fills in the cursor info\r
766 //              struct\r
767 //\r
768 ///////////////////////////////////////////////////////////////////////////\r
769 void\r
770 IN_ReadCursor(CursorInfo *info)\r
771 {\r
772         word    i,\r
773                         buttons;\r
774         int             dx,dy;\r
775 \r
776         info->x = info->y = 0;\r
777         info->button0 = info->button1 = false;\r
778 \r
779         if (inpu.MousePresent)\r
780         {\r
781                 buttons = INL_GetMouseButtons();\r
782                 INL_GetMouseDelta(&dx,&dy);\r
783                 INL_AdjustCursor(info,buttons,dx,dy);\r
784         }\r
785 \r
786         for (i = 0;i < MaxJoys;i++)\r
787         {\r
788                 if (!inpu.JoysPresent[i])\r
789                         continue;\r
790 \r
791                 buttons = INL_GetJoyButtons(i);\r
792                 INL_GetJoyDelta(i,&dx,&dy,true);\r
793                 dx /= 64;\r
794                 dy /= 64;\r
795                 INL_AdjustCursor(info,buttons,dx,dy);\r
796         }\r
797 }\r
798 \r
799 ///////////////////////////////////////////////////////////////////////////\r
800 //\r
801 //      IN_ReadControl() - Reads the device associated with the specified\r
802 //              player and fills in the control info struct\r
803 //\r
804 ///////////////////////////////////////////////////////////////////////////\r
805 void near\r
806 IN_ReadControl(int pn,player_t *player)\r
807 {\r
808                         boolean         realdelta;\r
809                         byte            dbyte;\r
810                         word            buttons;\r
811                         int                     dx,dy;\r
812                         Motion          mx,my;\r
813                         ControlType     type;\r
814                         sword conpee;\r
815                         byte dir=DirTable[2];\r
816 register        KeyboardDef     *def;\r
817 \r
818         dx = dy = 0;\r
819         mx = my = motion_None;\r
820         buttons = 0;\r
821 \r
822 #if DEMO0\r
823         if (DemoMode == demo_Playback)\r
824         {\r
825                 dbyte = DemoBuffer[DemoOffset + 1];\r
826                 my = (dbyte & 3) - 1;\r
827                 mx = ((dbyte >> 2) & 3) - 1;\r
828                 buttons = (dbyte >> 4) & 3;\r
829 \r
830                 if (!(--DemoBuffer[DemoOffset]))\r
831                 {\r
832                         DemoOffset += 2;\r
833                         if (DemoOffset >= DemoSize)\r
834                                 DemoMode = demo_PlayDone;\r
835                 }\r
836 \r
837                 realdelta = false;\r
838         }\r
839         else if (DemoMode == demo_PlayDone)\r
840                 Quit("Demo playback exceeded");\r
841         else\r
842         {\r
843 #endif\r
844                 switch (type = player[pn].Controls)\r
845                 {\r
846                 case ctrl_Keyboard1:\r
847                 case ctrl_Keyboard2:\r
848                         def = &(inpu.KbdDefs[type - ctrl_Keyboard]);\r
849 \r
850 /*                      if (Keyboard[def->upleft])\r
851                                 mx = motion_Left,my = motion_Up;\r
852                         else if (Keyboard[def->upright])\r
853                                 mx = motion_Right,my = motion_Up;\r
854                         else if (Keyboard[def->downleft])\r
855                                 mx = motion_Left,my = motion_Down;\r
856                         else if (Keyboard[def->downright])\r
857                                 mx = motion_Right,my = motion_Down;*/\r
858                         if(DIRECTIONIFELSEGFXTEST)\r
859                         {\r
860                         if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){\r
861                                 if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]))\r
862                                         my = motion_Up;\r
863                                 if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up]))\r
864                                         my = motion_Down;\r
865                         }else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){\r
866                                 if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]))\r
867                                         mx = motion_Left;\r
868                                 if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left]))// || player[pn].pdir != 1)\r
869                                         mx = motion_Right;\r
870                         }else{  //2 keys pressed\r
871                                         switch (player[pn].pdir)\r
872                                         {\r
873                                                 case 0:\r
874                                                 case 4:\r
875                                                         if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right])) dir = DirTable[1];\r
876                                                         else if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left])) dir = DirTable[3];\r
877                                                 break;\r
878                                                 case 1:\r
879                                                 case 3:\r
880                                                         if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down])) dir = DirTable[0];\r
881                                                         else if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up])) dir = DirTable[4];\r
882                                                 break;\r
883                                                 default:\r
884                                                 break;\r
885                                         }\r
886                                         if(testcontrolnoisy > 0){ printf("dir=%c ", dirchar(dir)); printf("pdir=%c      ", dirchar(player[pn].pdir)); }\r
887                                 }\r
888                         }\r
889                         //input from player\r
890                         if (inpu.Keyboard[def->button0])\r
891                                 buttons += 1 << 0;\r
892                         if (inpu.Keyboard[def->button1])\r
893                                 buttons += 1 << 1;\r
894                         realdelta = false;\r
895                         break;\r
896                 case ctrl_Joystick1:\r
897                 case ctrl_Joystick2:\r
898                         INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);\r
899                         buttons = INL_GetJoyButtons(type - ctrl_Joystick);\r
900                         realdelta = true;\r
901                         break;\r
902                 case ctrl_Mouse:\r
903                         INL_GetMouseDelta(&dx,&dy);\r
904                         buttons = INL_GetMouseButtons();\r
905                         realdelta = true;\r
906                         break;\r
907                 case ctrl_Joypad1:\r
908                 case ctrl_Joypad2:\r
909                         printf("wwww");\r
910                         break;\r
911                 }\r
912 #ifdef DEMO0\r
913         }\r
914 #endif\r
915 \r
916         if (realdelta)\r
917         {\r
918                 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);\r
919                 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);\r
920         }\r
921         else\r
922         {\r
923                 dx = mx;// * 127;\r
924                 dy = my;// * 127;\r
925         }\r
926 \r
927         player[pn].info.x = dx;\r
928         player[pn].info.xaxis = mx;\r
929         player[pn].info.y = dy;\r
930         player[pn].info.yaxis = my;\r
931         player[pn].info.button0 = buttons & (1 << 0);\r
932         player[pn].info.button1 = buttons & (1 << 1);\r
933         player[pn].info.button2 = buttons & (1 << 2);\r
934         player[pn].info.button3 = buttons & (1 << 3);\r
935 //      player[pn].info.dir = DirTable[((my + 1) * 3) + (mx + 1)];\r
936         conpee=(((my + 1) * 2) + (mx + 1))-1;\r
937         player[pn].info.dir = DirTable[conpee];\r
938 \r
939         //TODO: overwriting direction must be added\r
940         if(DirTable[conpee]!=2) player[pn].pdir=DirTable[conpee];\r
941         if(player[pn].q==1 &&( dir!=2 || (mx!=motion_None || my!=motion_None)))\r
942         {\r
943                 if(dir==2) player[pn].d = player[pn].info.dir;\r
944                 else player[pn].d = DirTable[dir];\r
945         }\r
946 \r
947 #if DEMO0\r
948         if (DemoMode == demo_Record)\r
949         {\r
950                 // Pack the control info into a byte\r
951                 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);\r
952 \r
953                 if\r
954                 (\r
955                         (DemoBuffer[DemoOffset + 1] == dbyte)\r
956                 &&      (DemoBuffer[DemoOffset] < 255)\r
957                 )\r
958                         (DemoBuffer[DemoOffset])++;\r
959                 else\r
960                 {\r
961                         if (DemoOffset || DemoBuffer[DemoOffset])\r
962                                 DemoOffset += 2;\r
963 \r
964                         if (DemoOffset >= DemoSize)\r
965                                 Quit("Demo buffer overflow");\r
966 \r
967                         DemoBuffer[DemoOffset] = 1;\r
968                         DemoBuffer[DemoOffset + 1] = dbyte;\r
969                 }\r
970         }\r
971 #endif\r
972 //#ifdef TESTCONTROLNOISY\r
973 if(testcontrolnoisy > 0)\r
974 if((inpu.Keyboard[def->up] || inpu.Keyboard[def->down] || inpu.Keyboard[def->left] || inpu.Keyboard[def->right]) || player[pn].q>1)\r
975 {\r
976         printf("q=%d ", player[pn].q);\r
977         printf("cpee=%c ", dirchar(conpee));\r
978         //printf("(mx)=%d       ", mx);\r
979         //printf("(my)=%d       ", my);\r
980         printf("pdir=%c d=%c dir=%c ", dirchar(player[pn].pdir), dirchar(player[pn].d), dirchar(player[pn].info.dir));\r
981         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
982 }\r
983 //#endif\r
984 }\r
985 \r
986 ///////////////////////////////////////////////////////////////////////////\r
987 //\r
988 //      IN_SetControlType() - Sets the control type to be used by the specified\r
989 //              player\r
990 //\r
991 ///////////////////////////////////////////////////////////////////////////\r
992 void\r
993 IN_SetControlType(word pn,player_t *player,ControlType type)\r
994 {\r
995         // DEBUG - check that requested type is present?\r
996         player[pn].Controls = type;\r
997 }\r
998 \r
999 #if DEMO0\r
1000 ///////////////////////////////////////////////////////////////////////////\r
1001 //\r
1002 //      IN_StartDemoRecord() - Starts the demo recording, using a buffer the\r
1003 //              size passed. Returns if the buffer allocation was successful\r
1004 //\r
1005 ///////////////////////////////////////////////////////////////////////////\r
1006 boolean\r
1007 IN_StartDemoRecord(word bufsize)\r
1008 {\r
1009         if (!bufsize)\r
1010                 return(false);\r
1011 \r
1012         MM_GetPtr((memptr *)&DemoBuffer,bufsize);\r
1013         DemoMode = demo_Record;\r
1014         DemoSize = bufsize & ~1;\r
1015         DemoOffset = 0;\r
1016         DemoBuffer[0] = DemoBuffer[1] = 0;\r
1017 \r
1018         return(true);\r
1019 }\r
1020 \r
1021 ///////////////////////////////////////////////////////////////////////////\r
1022 //\r
1023 //      IN_StartDemoPlayback() - Plays back the demo pointed to of the given size\r
1024 //\r
1025 ///////////////////////////////////////////////////////////////////////////\r
1026 void\r
1027 IN_StartDemoPlayback(byte /*__segment*/ *buffer,word bufsize)\r
1028 {\r
1029         DemoBuffer = buffer;\r
1030         DemoMode = demo_Playback;\r
1031         DemoSize = bufsize & ~1;\r
1032         DemoOffset = 0;\r
1033 }\r
1034 \r
1035 ///////////////////////////////////////////////////////////////////////////\r
1036 //\r
1037 //      IN_StopDemo() - Turns off demo mode\r
1038 //\r
1039 ///////////////////////////////////////////////////////////////////////////\r
1040 void\r
1041 IN_StopDemo(void)\r
1042 {\r
1043         if ((DemoMode == demo_Record) && DemoOffset)\r
1044                 DemoOffset += 2;\r
1045 \r
1046         DemoMode = demo_Off;\r
1047 }\r
1048 \r
1049 ///////////////////////////////////////////////////////////////////////////\r
1050 //\r
1051 //      IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated\r
1052 //\r
1053 ///////////////////////////////////////////////////////////////////////////\r
1054 void\r
1055 IN_FreeDemoBuffer(void)\r
1056 {\r
1057         if (DemoBuffer)\r
1058                 MM_FreePtr((memptr *)&DemoBuffer);\r
1059 }\r
1060 #endif\r
1061 \r
1062 \r
1063 ///////////////////////////////////////////////////////////////////////////\r
1064 //\r
1065 //      IN_GetScanName() - Returns a string containing the name of the\r
1066 //              specified scan code\r
1067 //\r
1068 ///////////////////////////////////////////////////////////////////////////\r
1069 byte *\r
1070 IN_GetScanName(ScanCode scan)\r
1071 {\r
1072         byte            **p;\r
1073         ScanCode        far *s;\r
1074 \r
1075         for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)\r
1076                 if (*s == scan)\r
1077                         return(*p);\r
1078 \r
1079         return(ScanNames[scan]);\r
1080 }\r
1081 \r
1082 ///////////////////////////////////////////////////////////////////////////\r
1083 //\r
1084 //      IN_WaitForKey() - Waits for a scan code, then clears LastScan and\r
1085 //              returns the scan code\r
1086 //\r
1087 ///////////////////////////////////////////////////////////////////////////\r
1088 ScanCode\r
1089 IN_WaitForKey()\r
1090 {\r
1091         ScanCode        result;\r
1092 \r
1093         while (!(result = inpu.LastScan))\r
1094                 ;\r
1095         inpu.LastScan = 0;\r
1096         return(result);\r
1097 }\r
1098 \r
1099 ///////////////////////////////////////////////////////////////////////////\r
1100 //\r
1101 //      IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and\r
1102 //              returns the ASCII value\r
1103 //\r
1104 ///////////////////////////////////////////////////////////////////////////\r
1105 char\r
1106 IN_WaitForASCII()\r
1107 {\r
1108         char            result;\r
1109 \r
1110         while (!(result = inpu.LastASCII))\r
1111                 ;\r
1112         inpu.LastASCII = '\0';\r
1113         return(result);\r
1114 }\r
1115 \r
1116 ///////////////////////////////////////////////////////////////////////////\r
1117 //\r
1118 //      IN_AckBack() - Waits for either an ASCII keypress or a button press\r
1119 //\r
1120 ///////////////////////////////////////////////////////////////////////////\r
1121 void\r
1122 IN_AckBack()\r
1123 {\r
1124         word    i;\r
1125 \r
1126         while (!inpu.LastScan)\r
1127         {\r
1128                 if (inpu.MousePresent)\r
1129                 {\r
1130                         if (INL_GetMouseButtons())\r
1131                         {\r
1132                                 while (INL_GetMouseButtons())\r
1133                                         ;\r
1134                                 return;\r
1135                         }\r
1136                 }\r
1137 \r
1138                 for (i = 0;i < MaxJoys;i++)\r
1139                 {\r
1140                         if (inpu.JoysPresent[i])\r
1141                         {\r
1142                                 if (IN_GetJoyButtonsDB(i))\r
1143                                 {\r
1144                                         while (IN_GetJoyButtonsDB(i))\r
1145                                                 ;\r
1146                                         return;\r
1147                                 }\r
1148                         }\r
1149                 }\r
1150         }\r
1151 \r
1152         IN_ClearKey(inpu.LastScan);\r
1153         inpu.LastScan = sc_None;\r
1154 }\r
1155 \r
1156 ///////////////////////////////////////////////////////////////////////////\r
1157 //\r
1158 //      IN_Ack() - Clears user input & then calls IN_AckBack()\r
1159 //\r
1160 ///////////////////////////////////////////////////////////////////////////\r
1161 void\r
1162 IN_Ack()\r
1163 {\r
1164         word    i;\r
1165 \r
1166         IN_ClearKey(inpu.LastScan);\r
1167         inpu.LastScan = sc_None;\r
1168 \r
1169         if (inpu.MousePresent)\r
1170                 while (INL_GetMouseButtons())\r
1171                                         ;\r
1172         for (i = 0;i < MaxJoys;i++)\r
1173                 if (inpu.JoysPresent[i])\r
1174                         while (IN_GetJoyButtonsDB(i))\r
1175                                 ;\r
1176 \r
1177         IN_AckBack();\r
1178 }\r
1179 \r
1180 ///////////////////////////////////////////////////////////////////////////\r
1181 //\r
1182 //      IN_IsUserInput() - Returns true if a key has been pressed or a button\r
1183 //              is down\r
1184 //\r
1185 ///////////////////////////////////////////////////////////////////////////\r
1186 boolean\r
1187 IN_IsUserInput()\r
1188 {\r
1189         boolean result;\r
1190         word    i;\r
1191 \r
1192         result = inpu.LastScan;\r
1193 \r
1194         if (inpu.MousePresent)\r
1195                 if (INL_GetMouseButtons())\r
1196                         result = true;\r
1197 \r
1198         for (i = 0;i < MaxJoys;i++)\r
1199                 if (inpu.JoysPresent[i])\r
1200                         if (INL_GetJoyButtons(i))\r
1201                                 result = true;\r
1202 \r
1203         return(result);\r
1204 }\r
1205 \r
1206 ///////////////////////////////////////////////////////////////////////////\r
1207 //\r
1208 //      IN_UserInput() - Waits for the specified delay time (in ticks) or the\r
1209 //              user pressing a key or a mouse button. If the clear flag is set, it\r
1210 //              then either clears the key or waits for the user to let the mouse\r
1211 //              button up.\r
1212 //\r
1213 ///////////////////////////////////////////////////////////////////////////\r
1214 boolean\r
1215 IN_UserInput(dword delay,boolean clear)\r
1216 {\r
1217         word TimeCount = *clockw;\r
1218         word    lasttime;\r
1219 \r
1220         lasttime = TimeCount;\r
1221         do\r
1222         {\r
1223                 if (IN_IsUserInput())\r
1224                 {\r
1225                         if (clear)\r
1226                                 IN_AckBack();\r
1227                         return(true);\r
1228                 }\r
1229         } while (TimeCount - lasttime < delay);\r
1230         return(false);\r
1231 }\r
1232 \r
1233 boolean IN_KeyDown(byte code)\r
1234 {\r
1235         return inpu.Keyboard[code];\r
1236 }\r
1237 \r
1238 void IN_ClearKey(byte code)\r
1239 {\r
1240         inpu.Keyboard[code] = false;\r
1241         if(code == inpu.LastScan)\r
1242                 inpu.LastScan = sc_None;\r
1243         }\r
1244 \r
1245 boolean IN_qb(byte kee)\r
1246 {\r
1247 //#ifdef TESTKEYIN\r
1248 //      if(testkeyin > 0) printf("%u\n", inpu.Keyboard[kee]);\r
1249 //#endif\r
1250         if(inpu.Keyboard[kee]==true) return 1;\r
1251         else return 0;\r
1252 }\r