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