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