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