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