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