OSDN Git Service

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