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