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