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