]> 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 #define KeyInt          9       // The keyboard ISR number\r
25 \r
26 //\r
27 // mouse constants\r
28 //\r
29 #define MReset          0\r
30 #define MButtons        3\r
31 #define MDelta          11\r
32 \r
33 #define MouseInt        0x33\r
34 #define Mouse(x)        _AX = x,geninterrupt(MouseInt)\r
35 \r
36 //\r
37 // joystick constants\r
38 //\r
39 #define JoyScaleMax             32768\r
40 #define JoyScaleShift   8\r
41 #define MaxJoyValue             5000\r
42 \r
43 /*\r
44 =============================================================================\r
45 \r
46                                         GLOBAL VARIABLES\r
47 \r
48 =============================================================================\r
49 */\r
50 \r
51 //\r
52 // configuration variables\r
53 //\r
54 boolean                 MousePresent;\r
55 boolean                 JoysPresent[MaxJoys];\r
56 boolean                 JoyPadPresent;\r
57 \r
58 \r
59 //      Global variables\r
60                 boolean         Keyboard[NumCodes];\r
61                 boolean         Paused;\r
62                 char            LastASCII;\r
63                 ScanCode        LastScan;\r
64 \r
65                 KeyboardDef     KbdDefs = {{0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}};\r
66                 JoystickDef     JoyDefs[MaxJoys];\r
67                 ControlType     Controls[MaxPlayers];\r
68 \r
69                 dword   MouseDownCount;\r
70 \r
71                 Demo            DemoMode = demo_Off;\r
72                 byte _seg       *DemoBuffer;\r
73                 word            DemoOffset,DemoSize;\r
74 \r
75 /*\r
76 =============================================================================\r
77 \r
78                                         LOCAL VARIABLES\r
79 \r
80 =============================================================================\r
81 */\r
82 static  byte        far ASCIINames[] =          // Unshifted ASCII for scan codes\r
83                                         {\r
84 //       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
85         0  ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8  ,9  ,        // 0\r
86         'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0  ,'a','s',        // 1\r
87         'd','f','g','h','j','k','l',';',39 ,'`',0  ,92 ,'z','x','c','v',        // 2\r
88         'b','n','m',',','.','/',0  ,'*',0  ,' ',0  ,0  ,0  ,0  ,0  ,0  ,        // 3\r
89         0  ,0  ,0  ,0  ,0  ,0  ,0  ,'7','8','9','-','4','5','6','+','1',        // 4\r
90         '2','3','0',127,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 5\r
91         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 6\r
92         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0           // 7\r
93                                         },\r
94                                         far ShiftNames[] =              // Shifted ASCII for scan codes\r
95                                         {\r
96 //       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
97         0  ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8  ,9  ,        // 0\r
98         'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0  ,'A','S',        // 1\r
99         'D','F','G','H','J','K','L',':',34 ,'~',0  ,'|','Z','X','C','V',        // 2\r
100         'B','N','M','<','>','?',0  ,'*',0  ,' ',0  ,0  ,0  ,0  ,0  ,0  ,        // 3\r
101         0  ,0  ,0  ,0  ,0  ,0  ,0  ,'7','8','9','-','4','5','6','+','1',        // 4\r
102         '2','3','0',127,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 5\r
103         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 6\r
104         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0           // 7\r
105                                         },\r
106                                         far SpecialNames[] =    // ASCII for 0xe0 prefixed codes\r
107                                         {\r
108 //       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
109         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 0\r
110         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,13 ,0  ,0  ,0  ,        // 1\r
111         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 2\r
112         0  ,0  ,0  ,0  ,0  ,'/',0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 3\r
113         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 4\r
114         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 5\r
115         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 6\r
116         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0           // 7\r
117                                         };\r
118 \r
119 \r
120 static  boolean         IN_Started;\r
121 static  boolean         CapsLock;\r
122 static  ScanCode        CurCode,LastCode;\r
123 \r
124 static  Direction       DirTable[] =            // Quick lookup for total direction\r
125                                         {\r
126                                                 dir_NorthWest,  dir_North,      dir_NorthEast,\r
127                                                 dir_West,               dir_None,       dir_East,\r
128                                                 dir_SouthWest,  dir_South,      dir_SouthEast\r
129                                         };\r
130 \r
131 static  void                    (*INL_KeyHook)(void);\r
132 static  void interrupt  (*OldKeyVect)(void);\r
133 \r
134 static  char                    *ParmStrings[] = {"nojoys","nomouse",nil};\r
135 \r
136 //      Internal routines\r
137 \r
138 ///////////////////////////////////////////////////////////////////////////\r
139 //\r
140 //      INL_KeyService() - Handles a keyboard interrupt (key up/down)\r
141 //\r
142 ///////////////////////////////////////////////////////////////////////////\r
143 static void interrupt\r
144 INL_KeyService(void)\r
145 {\r
146 static  boolean special;\r
147                 byte    k,c,\r
148                                 temp;\r
149                 int             i;\r
150 \r
151         k = inp(0x60);  // Get the scan code\r
152 \r
153         // Tell the XT keyboard controller to clear the key\r
154         outportb(0x61,(temp = inp(0x61)) | 0x80);\r
155         outportb(0x61,temp);\r
156 \r
157         if (k == 0xe0)          // Special key prefix\r
158                 special = true;\r
159         else if (k == 0xe1)     // Handle Pause key\r
160                 Paused = true;\r
161         else\r
162         {\r
163                 if (k & 0x80)   // Break code\r
164                 {\r
165                         k &= 0x7f;\r
166 \r
167 // DEBUG - handle special keys: ctl-alt-delete, print scrn\r
168 \r
169                         Keyboard[k] = false;\r
170                 }\r
171                 else                    // Make code\r
172                 {\r
173                         LastCode = CurCode;\r
174                         CurCode = LastScan = k;\r
175                         Keyboard[k] = true;\r
176 \r
177                         if (special)\r
178                                 c = SpecialNames[k];\r
179                         else\r
180                         {\r
181                                 if (k == sc_CapsLock)\r
182                                 {\r
183                                         CapsLock ^= true;\r
184                                         // DEBUG - make caps lock light work\r
185                                 }\r
186 \r
187                                 if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted\r
188                                 {\r
189                                         c = ShiftNames[k];\r
190                                         if ((c >= 'A') && (c <= 'Z') && CapsLock)\r
191                                                 c += 'a' - 'A';\r
192                                 }\r
193                                 else\r
194                                 {\r
195                                         c = ASCIINames[k];\r
196                                         if ((c >= 'a') && (c <= 'z') && CapsLock)\r
197                                                 c -= 'a' - 'A';\r
198                                 }\r
199                         }\r
200                         if (c)\r
201                                 LastASCII = c;\r
202                 }\r
203 \r
204                 special = false;\r
205         }\r
206 \r
207         if (INL_KeyHook && !special)\r
208                 INL_KeyHook();\r
209         outportb(0x20,0x20);\r
210 }\r
211 \r
212 ///////////////////////////////////////////////////////////////////////////\r
213 //\r
214 //      INL_GetMouseDelta() - Gets the amount that the mouse has moved from the\r
215 //              mouse driver\r
216 //\r
217 ///////////////////////////////////////////////////////////////////////////\r
218 static void\r
219 INL_GetMouseDelta(int *x,int *y)\r
220 {\r
221         Mouse(MDelta);\r
222         *x = _CX;\r
223         *y = _DX;\r
224 }\r
225 \r
226 ///////////////////////////////////////////////////////////////////////////\r
227 //\r
228 //      INL_GetMouseButtons() - Gets the status of the mouse buttons from the\r
229 //              mouse driver\r
230 //\r
231 ///////////////////////////////////////////////////////////////////////////\r
232 static word\r
233 INL_GetMouseButtons(void)\r
234 {\r
235         word    buttons;\r
236 \r
237         Mouse(MButtons);\r
238         buttons = _BX;\r
239         return(buttons);\r
240 }\r
241 \r
242 ///////////////////////////////////////////////////////////////////////////\r
243 //\r
244 //      IN_GetJoyAbs() - Reads the absolute position of the specified joystick\r
245 //\r
246 ///////////////////////////////////////////////////////////////////////////\r
247 void\r
248 IN_GetJoyAbs(word joy,word *xp,word *yp)\r
249 {\r
250         byte    xb,yb,\r
251                         xs,ys;\r
252         word    x,y;\r
253 \r
254         x = y = 0;\r
255         xs = joy? 2 : 0;                // Find shift value for x axis\r
256         xb = 1 << xs;                   // Use shift value to get x bit mask\r
257         ys = joy? 3 : 1;                // Do the same for y axis\r
258         yb = 1 << ys;\r
259 \r
260 // Read the absolute joystick values\r
261 asm             pushf                           // Save some registers\r
262 asm             push    si\r
263 asm             push    di\r
264 asm             cli                                     // Make sure an interrupt doesn't screw the timings\r
265 \r
266 \r
267 asm             mov             dx,0x201\r
268 asm             in              al,dx\r
269 asm             out             dx,al           // Clear the resistors\r
270 \r
271 asm             mov             ah,[xb]         // Get masks into registers\r
272 asm             mov             ch,[yb]\r
273 \r
274 asm             xor             si,si           // Clear count registers\r
275 asm             xor             di,di\r
276 asm             xor             bh,bh           // Clear high byte of bx for later\r
277 \r
278 asm             push    bp                      // Don't mess up stack frame\r
279 asm             mov             bp,MaxJoyValue\r
280 \r
281 loop:\r
282 asm             in              al,dx           // Get bits indicating whether all are finished\r
283 \r
284 asm             dec             bp                      // Check bounding register\r
285 asm             jz              done            // We have a silly value - abort\r
286 \r
287 asm             mov             bl,al           // Duplicate the bits\r
288 asm             and             bl,ah           // Mask off useless bits (in [xb])\r
289 asm             add             si,bx           // Possibly increment count register\r
290 asm             mov             cl,bl           // Save for testing later\r
291 \r
292 asm             mov             bl,al\r
293 asm             and             bl,ch           // [yb]\r
294 asm             add             di,bx\r
295 \r
296 asm             add             cl,bl\r
297 asm             jnz             loop            // If both bits were 0, drop out\r
298 \r
299 done:\r
300 asm     pop             bp\r
301 \r
302 asm             mov             cl,[xs]         // Get the number of bits to shift\r
303 asm             shr             si,cl           //  and shift the count that many times\r
304 \r
305 asm             mov             cl,[ys]\r
306 asm             shr             di,cl\r
307 \r
308 asm             mov             [x],si          // Store the values into the variables\r
309 asm             mov             [y],di\r
310 \r
311 asm             pop             di\r
312 asm             pop             si\r
313 asm             popf                            // Restore the registers\r
314 \r
315         *xp = x;\r
316         *yp = y;\r
317 }\r
318 \r
319 ///////////////////////////////////////////////////////////////////////////\r
320 //\r
321 //      INL_GetJoyDelta() - Returns the relative movement of the specified\r
322 //              joystick (from +/-127)\r
323 //\r
324 ///////////////////////////////////////////////////////////////////////////\r
325 void INL_GetJoyDelta(word joy,int *dx,int *dy)\r
326 {\r
327         word            x,y;\r
328         dword   time;\r
329         JoystickDef     *def;\r
330 static  dword   lasttime;\r
331 \r
332         IN_GetJoyAbs(joy,&x,&y);\r
333         def = JoyDefs + joy;\r
334 \r
335         if (x < def->threshMinX)\r
336         {\r
337                 if (x < def->joyMinX)\r
338                         x = def->joyMinX;\r
339 \r
340                 x = -(x - def->threshMinX);\r
341                 x *= def->joyMultXL;\r
342                 x >>= JoyScaleShift;\r
343                 *dx = (x > 127)? -127 : -x;\r
344         }\r
345         else if (x > def->threshMaxX)\r
346         {\r
347                 if (x > def->joyMaxX)\r
348                         x = def->joyMaxX;\r
349 \r
350                 x = x - def->threshMaxX;\r
351                 x *= def->joyMultXH;\r
352                 x >>= JoyScaleShift;\r
353                 *dx = (x > 127)? 127 : x;\r
354         }\r
355         else\r
356                 *dx = 0;\r
357 \r
358         if (y < def->threshMinY)\r
359         {\r
360                 if (y < def->joyMinY)\r
361                         y = def->joyMinY;\r
362 \r
363                 y = -(y - def->threshMinY);\r
364                 y *= def->joyMultYL;\r
365                 y >>= JoyScaleShift;\r
366                 *dy = (y > 127)? -127 : -y;\r
367         }\r
368         else if (y > def->threshMaxY)\r
369         {\r
370                 if (y > def->joyMaxY)\r
371                         y = def->joyMaxY;\r
372 \r
373                 y = y - def->threshMaxY;\r
374                 y *= def->joyMultYH;\r
375                 y >>= JoyScaleShift;\r
376                 *dy = (y > 127)? 127 : y;\r
377         }\r
378         else\r
379                 *dy = 0;\r
380 \r
381         lasttime = TimeCount;\r
382 }\r
383 \r
384 ///////////////////////////////////////////////////////////////////////////\r
385 //\r
386 //      INL_GetJoyButtons() - Returns the button status of the specified\r
387 //              joystick\r
388 //\r
389 ///////////////////////////////////////////////////////////////////////////\r
390 static word\r
391 INL_GetJoyButtons(word joy)\r
392 {\r
393 register        word    result;\r
394 \r
395         result = inp(0x201);    // Get all the joystick buttons\r
396         result >>= joy? 6 : 4;  // Shift into bits 0-1\r
397         result &= 3;                            // Mask off the useless bits\r
398         result ^= 3;\r
399         return(result);\r
400 }\r
401 \r
402 ///////////////////////////////////////////////////////////////////////////\r
403 //\r
404 //      IN_GetJoyButtonsDB() - Returns the de-bounced button status of the\r
405 //              specified joystick\r
406 //\r
407 ///////////////////////////////////////////////////////////////////////////\r
408 word\r
409 IN_GetJoyButtonsDB(word joy)\r
410 {\r
411         dword   lasttime;\r
412         word            result1,result2;\r
413 \r
414         do\r
415         {\r
416                 result1 = INL_GetJoyButtons(joy);\r
417                 lasttime = TimeCount;\r
418                 while (TimeCount == lasttime)\r
419                         ;\r
420                 result2 = INL_GetJoyButtons(joy);\r
421         } while (result1 != result2);\r
422         return(result1);\r
423 }\r
424 \r
425 ///////////////////////////////////////////////////////////////////////////\r
426 //\r
427 //      INL_StartKbd() - Sets up my keyboard stuff for use\r
428 //\r
429 ///////////////////////////////////////////////////////////////////////////\r
430 static void\r
431 INL_StartKbd(void)\r
432 {\r
433         INL_KeyHook = NULL;                     // no key hook routine\r
434 \r
435         IN_ClearKeysDown();\r
436 \r
437         OldKeyVect = getvect(KeyInt);\r
438         setvect(KeyInt,INL_KeyService);\r
439 }\r
440 \r
441 ///////////////////////////////////////////////////////////////////////////\r
442 //\r
443 //      INL_ShutKbd() - Restores keyboard control to the BIOS\r
444 //\r
445 ///////////////////////////////////////////////////////////////////////////\r
446 static void\r
447 INL_ShutKbd(void)\r
448 {\r
449         poke(0x40,0x17,peek(0x40,0x17) & 0xfaf0);       // Clear ctrl/alt/shift flags\r
450 \r
451         setvect(KeyInt,OldKeyVect);\r
452 }\r
453 \r
454 ///////////////////////////////////////////////////////////////////////////\r
455 //\r
456 //      INL_StartMouse() - Detects and sets up the mouse\r
457 //\r
458 ///////////////////////////////////////////////////////////////////////////\r
459 static boolean\r
460 INL_StartMouse(void)\r
461 {\r
462 #if 0\r
463         if (getvect(MouseInt))\r
464         {\r
465                 Mouse(MReset);\r
466                 if (_AX == 0xffff)\r
467                         return(true);\r
468         }\r
469         return(false);\r
470 #endif\r
471  union REGS regs;\r
472  unsigned char far *vector;\r
473 \r
474 \r
475  if ((vector=MK_FP(peek(0,0x33*4+2),peek(0,0x33*4)))==NULL)\r
476    return false;\r
477 \r
478  if (*vector == 207)\r
479    return false;\r
480 \r
481  Mouse(MReset);\r
482  return true;\r
483 }\r
484 \r
485 ///////////////////////////////////////////////////////////////////////////\r
486 //\r
487 //      INL_ShutMouse() - Cleans up after the mouse\r
488 //\r
489 ///////////////////////////////////////////////////////////////////////////\r
490 static void\r
491 INL_ShutMouse(void)\r
492 {\r
493 }\r
494 \r
495 //\r
496 //      INL_SetJoyScale() - Sets up scaling values for the specified joystick\r
497 //\r
498 static void\r
499 INL_SetJoyScale(word joy)\r
500 {\r
501         JoystickDef     *def;\r
502 \r
503         def = &JoyDefs[joy];\r
504         def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);\r
505         def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);\r
506         def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);\r
507         def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);\r
508 }\r
509 \r
510 ///////////////////////////////////////////////////////////////////////////\r
511 //\r
512 //      IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()\r
513 //              to set up scaling values\r
514 //\r
515 ///////////////////////////////////////////////////////////////////////////\r
516 void\r
517 IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)\r
518 {\r
519         word            d,r;\r
520         JoystickDef     *def;\r
521 \r
522         def = &JoyDefs[joy];\r
523 \r
524         def->joyMinX = minx;\r
525         def->joyMaxX = maxx;\r
526         r = maxx - minx;\r
527         d = r / 3;\r
528         def->threshMinX = ((r / 2) - d) + minx;\r
529         def->threshMaxX = ((r / 2) + d) + minx;\r
530 \r
531         def->joyMinY = miny;\r
532         def->joyMaxY = maxy;\r
533         r = maxy - miny;\r
534         d = r / 3;\r
535         def->threshMinY = ((r / 2) - d) + miny;\r
536         def->threshMaxY = ((r / 2) + d) + miny;\r
537 \r
538         INL_SetJoyScale(joy);\r
539 }\r
540 \r
541 ///////////////////////////////////////////////////////////////////////////\r
542 //\r
543 //      INL_StartJoy() - Detects & auto-configures the specified joystick\r
544 //                                      The auto-config assumes the joystick is centered\r
545 //\r
546 ///////////////////////////////////////////////////////////////////////////\r
547 static boolean\r
548 INL_StartJoy(word joy)\r
549 {\r
550         word            x,y;\r
551 \r
552         IN_GetJoyAbs(joy,&x,&y);\r
553 \r
554         if\r
555         (\r
556                 ((x == 0) || (x > MaxJoyValue - 10))\r
557         ||      ((y == 0) || (y > MaxJoyValue - 10))\r
558         )\r
559                 return(false);\r
560         else\r
561         {\r
562                 IN_SetupJoy(joy,0,x * 2,0,y * 2);\r
563                 return(true);\r
564         }\r
565 }\r
566 \r
567 ///////////////////////////////////////////////////////////////////////////\r
568 //\r
569 //      INL_ShutJoy() - Cleans up the joystick stuff\r
570 //\r
571 ///////////////////////////////////////////////////////////////////////////\r
572 static void\r
573 INL_ShutJoy(word joy)\r
574 {\r
575         JoysPresent[joy] = false;\r
576 }\r
577 \r
578 \r
579 ///////////////////////////////////////////////////////////////////////////\r
580 //\r
581 //      IN_Startup() - Starts up the Input Mgr\r
582 //\r
583 ///////////////////////////////////////////////////////////////////////////\r
584 void\r
585 IN_Startup(void)\r
586 {\r
587         boolean checkjoys,checkmouse;\r
588         word    i;\r
589 \r
590         if (IN_Started)\r
591                 return;\r
592 \r
593         checkjoys = true;\r
594         checkmouse = true;\r
595         for (i = 1;i < _argc;i++)\r
596         {\r
597                 switch (US_CheckParm(_argv[i],ParmStrings))\r
598                 {\r
599                 case 0:\r
600                         checkjoys = false;\r
601                         break;\r
602                 case 1:\r
603                         checkmouse = false;\r
604                         break;\r
605                 }\r
606         }\r
607 \r
608         INL_StartKbd();\r
609         MousePresent = checkmouse? INL_StartMouse() : false;\r
610 \r
611         for (i = 0;i < MaxJoys;i++)\r
612                 JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;\r
613 \r
614         IN_Started = true;\r
615 }\r
616 \r
617 ///////////////////////////////////////////////////////////////////////////\r
618 //\r
619 //      IN_Default() - Sets up default conditions for the Input Mgr\r
620 //\r
621 ///////////////////////////////////////////////////////////////////////////\r
622 void\r
623 IN_Default(boolean gotit,ControlType in)\r
624 {\r
625         if\r
626         (\r
627                 (!gotit)\r
628         ||      ((in == ctrl_Joystick1) && !JoysPresent[0])\r
629         ||      ((in == ctrl_Joystick2) && !JoysPresent[1])\r
630         ||      ((in == ctrl_Mouse) && !MousePresent)\r
631         )\r
632                 in = ctrl_Keyboard1;\r
633         IN_SetControlType(0,in);\r
634 }\r
635 \r
636 ///////////////////////////////////////////////////////////////////////////\r
637 //\r
638 //      IN_Shutdown() - Shuts down the Input Mgr\r
639 //\r
640 ///////////////////////////////////////////////////////////////////////////\r
641 void\r
642 IN_Shutdown(void)\r
643 {\r
644         word    i;\r
645 \r
646         if (!IN_Started)\r
647                 return;\r
648 \r
649         INL_ShutMouse();\r
650         for (i = 0;i < MaxJoys;i++)\r
651                 INL_ShutJoy(i);\r
652         INL_ShutKbd();\r
653 \r
654         IN_Started = false;\r
655 }\r
656 \r
657 ///////////////////////////////////////////////////////////////////////////\r
658 //\r
659 //      IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()\r
660 //                      everytime a real make/break code gets hit\r
661 //\r
662 ///////////////////////////////////////////////////////////////////////////\r
663 void\r
664 IN_SetKeyHook(void (*hook)())\r
665 {\r
666         INL_KeyHook = hook;\r
667 }\r
668 \r
669 ///////////////////////////////////////////////////////////////////////////\r
670 //\r
671 //      IN_ClearKeysDown() - Clears the keyboard array\r
672 //\r
673 ///////////////////////////////////////////////////////////////////////////\r
674 void\r
675 IN_ClearKeysDown(void)\r
676 {\r
677         int     i;\r
678 \r
679         LastScan = sc_None;\r
680         LastASCII = key_None;\r
681         memset (Keyboard,0,sizeof(Keyboard));\r
682 }\r
683 \r
684 \r
685 ///////////////////////////////////////////////////////////////////////////\r
686 //\r
687 //      IN_ReadControl() - Reads the device associated with the specified\r
688 //              player and fills in the control info struct\r
689 //\r
690 ///////////////////////////////////////////////////////////////////////////\r
691 void\r
692 IN_ReadControl(int player,CursorInfo *info)\r
693 {\r
694                         boolean         realdelta;\r
695                         byte            dbyte;\r
696                         word            buttons;\r
697                         int                     dx,dy;\r
698                         Motion          mx,my;\r
699                         ControlType     type;\r
700 register        KeyboardDef     *def;\r
701 \r
702         dx = dy = 0;\r
703         mx = my = motion_None;\r
704         buttons = 0;\r
705 \r
706         if (DemoMode == demo_Playback)\r
707         {\r
708                 dbyte = DemoBuffer[DemoOffset + 1];\r
709                 my = (dbyte & 3) - 1;\r
710                 mx = ((dbyte >> 2) & 3) - 1;\r
711                 buttons = (dbyte >> 4) & 3;\r
712 \r
713                 if (!(--DemoBuffer[DemoOffset]))\r
714                 {\r
715                         DemoOffset += 2;\r
716                         if (DemoOffset >= DemoSize)\r
717                                 DemoMode = demo_PlayDone;\r
718                 }\r
719 \r
720                 realdelta = false;\r
721         }\r
722         else if (DemoMode == demo_PlayDone)\r
723                 Quit("Demo playback exceeded");\r
724         else\r
725         {\r
726                 switch (type = Controls[player])\r
727                 {\r
728                 case ctrl_Keyboard:\r
729                         def = &KbdDefs;\r
730 \r
731                         if (Keyboard[def->upleft])\r
732                                 mx = motion_Left,my = motion_Up;\r
733                         else if (Keyboard[def->upright])\r
734                                 mx = motion_Right,my = motion_Up;\r
735                         else if (Keyboard[def->downleft])\r
736                                 mx = motion_Left,my = motion_Down;\r
737                         else if (Keyboard[def->downright])\r
738                                 mx = motion_Right,my = motion_Down;\r
739 \r
740                         if (Keyboard[def->up])\r
741                                 my = motion_Up;\r
742                         else if (Keyboard[def->down])\r
743                                 my = motion_Down;\r
744 \r
745                         if (Keyboard[def->left])\r
746                                 mx = motion_Left;\r
747                         else if (Keyboard[def->right])\r
748                                 mx = motion_Right;\r
749 \r
750                         if (Keyboard[def->button0])\r
751                                 buttons += 1 << 0;\r
752                         if (Keyboard[def->button1])\r
753                                 buttons += 1 << 1;\r
754                         realdelta = false;\r
755                         break;\r
756                 case ctrl_Joystick1:\r
757                 case ctrl_Joystick2:\r
758                         INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy);\r
759                         buttons = INL_GetJoyButtons(type - ctrl_Joystick);\r
760                         realdelta = true;\r
761                         break;\r
762                 case ctrl_Mouse:\r
763                         INL_GetMouseDelta(&dx,&dy);\r
764                         buttons = INL_GetMouseButtons();\r
765                         realdelta = true;\r
766                         break;\r
767                 }\r
768         }\r
769 \r
770         if (realdelta)\r
771         {\r
772                 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);\r
773                 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);\r
774         }\r
775         else\r
776         {\r
777                 dx = mx * 127;\r
778                 dy = my * 127;\r
779         }\r
780 \r
781         info->x = dx;\r
782         info->xaxis = mx;\r
783         info->y = dy;\r
784         info->yaxis = my;\r
785         info->button0 = buttons & (1 << 0);\r
786         info->button1 = buttons & (1 << 1);\r
787         info->button2 = buttons & (1 << 2);\r
788         info->button3 = buttons & (1 << 3);\r
789         info->dir = DirTable[((my + 1) * 3) + (mx + 1)];\r
790 \r
791         if (DemoMode == demo_Record)\r
792         {\r
793                 // Pack the control info into a byte\r
794                 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);\r
795 \r
796                 if\r
797                 (\r
798                         (DemoBuffer[DemoOffset + 1] == dbyte)\r
799                 &&      (DemoBuffer[DemoOffset] < 255)\r
800                 )\r
801                         (DemoBuffer[DemoOffset])++;\r
802                 else\r
803                 {\r
804                         if (DemoOffset || DemoBuffer[DemoOffset])\r
805                                 DemoOffset += 2;\r
806 \r
807                         if (DemoOffset >= DemoSize)\r
808                                 Quit("Demo buffer overflow");\r
809 \r
810                         DemoBuffer[DemoOffset] = 1;\r
811                         DemoBuffer[DemoOffset + 1] = dbyte;\r
812                 }\r
813         }\r
814 }\r
815 \r
816 ///////////////////////////////////////////////////////////////////////////\r
817 //\r
818 //      IN_SetControlType() - Sets the control type to be used by the specified\r
819 //              player\r
820 //\r
821 ///////////////////////////////////////////////////////////////////////////\r
822 void\r
823 IN_SetControlType(int player,ControlType type)\r
824 {\r
825         // DEBUG - check that requested type is present?\r
826         Controls[player] = type;\r
827 }\r
828 \r
829 ///////////////////////////////////////////////////////////////////////////\r
830 //\r
831 //      IN_WaitForKey() - Waits for a scan code, then clears LastScan and\r
832 //              returns the scan code\r
833 //\r
834 ///////////////////////////////////////////////////////////////////////////\r
835 ScanCode\r
836 IN_WaitForKey(void)\r
837 {\r
838         ScanCode        result;\r
839 \r
840         while (!(result = LastScan))\r
841                 ;\r
842         LastScan = 0;\r
843         return(result);\r
844 }\r
845 \r
846 ///////////////////////////////////////////////////////////////////////////\r
847 //\r
848 //      IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and\r
849 //              returns the ASCII value\r
850 //\r
851 ///////////////////////////////////////////////////////////////////////////\r
852 char\r
853 IN_WaitForASCII(void)\r
854 {\r
855         char            result;\r
856 \r
857         while (!(result = LastASCII))\r
858                 ;\r
859         LastASCII = '\0';\r
860         return(result);\r
861 }\r
862 \r
863 ///////////////////////////////////////////////////////////////////////////\r
864 //\r
865 //      IN_Ack() - waits for a button or key press.  If a button is down, upon\r
866 // calling, it must be released for it to be recognized\r
867 //\r
868 ///////////////////////////////////////////////////////////////////////////\r
869 \r
870 boolean btnstate[8];\r
871 \r
872 void IN_StartAck(void)\r
873 {\r
874         unsigned        i,buttons;\r
875 \r
876 //\r
877 // get initial state of everything\r
878 //\r
879         IN_ClearKeysDown();\r
880         memset (btnstate,0,sizeof(btnstate));\r
881 \r
882         buttons = IN_JoyButtons () << 4;\r
883         if (MousePresent)\r
884                 buttons |= IN_MouseButtons ();\r
885 \r
886         for (i=0;i<8;i++,buttons>>=1)\r
887                 if (buttons&1)\r
888                         btnstate[i] = true;\r
889 }\r
890 \r
891 \r
892 boolean IN_CheckAck (void)\r
893 {\r
894         unsigned        i,buttons;\r
895 \r
896 //\r
897 // see if something has been pressed\r
898 //\r
899         if (LastScan)\r
900                 return true;\r
901 \r
902         buttons = IN_JoyButtons () << 4;\r
903         if (MousePresent)\r
904                 buttons |= IN_MouseButtons ();\r
905 \r
906         for (i=0;i<8;i++,buttons>>=1)\r
907                 if ( buttons&1 )\r
908                 {\r
909                         if (!btnstate[i])\r
910                                 return true;\r
911                 }\r
912                 else\r
913                         btnstate[i]=false;\r
914 \r
915         return false;\r
916 }\r
917 \r
918 \r
919 void IN_Ack (void)\r
920 {\r
921         IN_StartAck ();\r
922 \r
923         while (!IN_CheckAck ())\r
924         ;\r
925 }\r
926 \r
927 \r
928 ///////////////////////////////////////////////////////////////////////////\r
929 //\r
930 //      IN_UserInput() - Waits for the specified delay time (in ticks) or the\r
931 //              user pressing a key or a mouse button. If the clear flag is set, it\r
932 //              then either clears the key or waits for the user to let the mouse\r
933 //              button up.\r
934 //\r
935 ///////////////////////////////////////////////////////////////////////////\r
936 boolean IN_UserInput(dword delay)\r
937 {\r
938         dword   lasttime;\r
939 \r
940         lasttime = TimeCount;\r
941         IN_StartAck ();\r
942         do\r
943         {\r
944                 if (IN_CheckAck())\r
945                         return true;\r
946         } while (TimeCount - lasttime < delay);\r
947         return(false);\r
948 }\r
949 \r
950 //===========================================================================\r
951 \r
952 /*\r
953 ===================\r
954 =\r
955 = IN_MouseButtons\r
956 =\r
957 ===================\r
958 */\r
959 \r
960 byte    IN_MouseButtons (void)\r
961 {\r
962         if (MousePresent)\r
963         {\r
964                 Mouse(MButtons);\r
965                 return _BX;\r
966         }\r
967         else\r
968                 return 0;\r
969 }\r
970 \r
971 \r
972 /*\r
973 ===================\r
974 =\r
975 = IN_JoyButtons\r
976 =\r
977 ===================\r
978 */\r
979 \r
980 byte    IN_JoyButtons (void)\r
981 {\r
982         unsigned joybits;\r
983 \r
984         joybits = inp(0x201);   // Get all the joystick buttons\r
985         joybits >>= 4;                          // only the high bits are useful\r
986         joybits ^= 15;                          // return with 1=pressed\r
987 \r
988         return joybits;\r
989 }\r
990 \r
991 \r