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