ID_IN.C (22314B)
1 // 2 // ID Engine 3 // ID_IN.c - Input Manager 4 // v1.0d1 5 // By Jason Blochowiak 6 // 7 8 // 9 // This module handles dealing with the various input devices 10 // 11 // Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff), 12 // User Mgr (for command line parms) 13 // 14 // Globals: 15 // LastScan - The keyboard scan code of the last key pressed 16 // LastASCII - The ASCII value of the last key pressed 17 // DEBUG - there are more globals 18 // 19 20 #include "ID_HEADS.H" 21 #pragma hdrstop 22 23 #define KeyInt 9 // The keyboard ISR number 24 25 // 26 // mouse constants 27 // 28 #define MReset 0 29 #define MButtons 3 30 #define MDelta 11 31 32 #define MouseInt 0x33 33 #define Mouse(x) _AX = x,geninterrupt(MouseInt) 34 35 // 36 // joystick constants 37 // 38 #define JoyScaleMax 32768 39 #define JoyScaleShift 8 40 #define MaxJoyValue 5000 41 42 /* 43 ============================================================================= 44 45 GLOBAL VARIABLES 46 47 ============================================================================= 48 */ 49 50 // 51 // configuration variables 52 // 53 boolean MousePresent; 54 boolean JoysPresent[MaxJoys]; 55 boolean JoyPadPresent; 56 57 58 // Global variables 59 boolean Keyboard[NumCodes]; 60 boolean Paused; 61 char LastASCII; 62 ScanCode LastScan; 63 64 KeyboardDef KbdDefs = {0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}; 65 JoystickDef JoyDefs[MaxJoys]; 66 ControlType Controls[MaxPlayers]; 67 68 longword MouseDownCount; 69 70 Demo DemoMode = demo_Off; 71 byte _seg *DemoBuffer; 72 word DemoOffset,DemoSize; 73 74 /* 75 ============================================================================= 76 77 LOCAL VARIABLES 78 79 ============================================================================= 80 */ 81 static byte far ASCIINames[] = // Unshifted ASCII for scan codes 82 { 83 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 84 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0 85 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1 86 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2 87 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3 88 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4 89 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 90 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 91 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 92 }, 93 far ShiftNames[] = // Shifted ASCII for scan codes 94 { 95 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 96 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0 97 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1 98 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2 99 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3 100 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4 101 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 102 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 103 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 104 }, 105 far SpecialNames[] = // ASCII for 0xe0 prefixed codes 106 { 107 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 108 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0 109 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1 110 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2 111 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3 112 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4 113 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 114 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 115 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 116 }; 117 118 119 static boolean IN_Started; 120 static boolean CapsLock; 121 static ScanCode CurCode,LastCode; 122 123 static Direction DirTable[] = // Quick lookup for total direction 124 { 125 dir_NorthWest, dir_North, dir_NorthEast, 126 dir_West, dir_None, dir_East, 127 dir_SouthWest, dir_South, dir_SouthEast 128 }; 129 130 static void (*INL_KeyHook)(void); 131 static void interrupt (*OldKeyVect)(void); 132 133 static char *ParmStrings[] = {"nojoys","nomouse",nil}; 134 135 // Internal routines 136 137 /////////////////////////////////////////////////////////////////////////// 138 // 139 // INL_KeyService() - Handles a keyboard interrupt (key up/down) 140 // 141 /////////////////////////////////////////////////////////////////////////// 142 static void interrupt 143 INL_KeyService(void) 144 { 145 static boolean special; 146 byte k,c, 147 temp; 148 int i; 149 150 k = inportb(0x60); // Get the scan code 151 152 // Tell the XT keyboard controller to clear the key 153 outportb(0x61,(temp = inportb(0x61)) | 0x80); 154 outportb(0x61,temp); 155 156 if (k == 0xe0) // Special key prefix 157 special = true; 158 else if (k == 0xe1) // Handle Pause key 159 Paused = true; 160 else 161 { 162 if (k & 0x80) // Break code 163 { 164 k &= 0x7f; 165 166 // DEBUG - handle special keys: ctl-alt-delete, print scrn 167 168 Keyboard[k] = false; 169 } 170 else // Make code 171 { 172 LastCode = CurCode; 173 CurCode = LastScan = k; 174 Keyboard[k] = true; 175 176 if (special) 177 c = SpecialNames[k]; 178 else 179 { 180 if (k == sc_CapsLock) 181 { 182 CapsLock ^= true; 183 // DEBUG - make caps lock light work 184 } 185 186 if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted 187 { 188 c = ShiftNames[k]; 189 if ((c >= 'A') && (c <= 'Z') && CapsLock) 190 c += 'a' - 'A'; 191 } 192 else 193 { 194 c = ASCIINames[k]; 195 if ((c >= 'a') && (c <= 'z') && CapsLock) 196 c -= 'a' - 'A'; 197 } 198 } 199 if (c) 200 LastASCII = c; 201 } 202 203 special = false; 204 } 205 206 if (INL_KeyHook && !special) 207 INL_KeyHook(); 208 outportb(0x20,0x20); 209 } 210 211 /////////////////////////////////////////////////////////////////////////// 212 // 213 // INL_GetMouseDelta() - Gets the amount that the mouse has moved from the 214 // mouse driver 215 // 216 /////////////////////////////////////////////////////////////////////////// 217 static void 218 INL_GetMouseDelta(int *x,int *y) 219 { 220 Mouse(MDelta); 221 *x = _CX; 222 *y = _DX; 223 } 224 225 /////////////////////////////////////////////////////////////////////////// 226 // 227 // INL_GetMouseButtons() - Gets the status of the mouse buttons from the 228 // mouse driver 229 // 230 /////////////////////////////////////////////////////////////////////////// 231 static word 232 INL_GetMouseButtons(void) 233 { 234 word buttons; 235 236 Mouse(MButtons); 237 buttons = _BX; 238 return(buttons); 239 } 240 241 /////////////////////////////////////////////////////////////////////////// 242 // 243 // IN_GetJoyAbs() - Reads the absolute position of the specified joystick 244 // 245 /////////////////////////////////////////////////////////////////////////// 246 void 247 IN_GetJoyAbs(word joy,word *xp,word *yp) 248 { 249 byte xb,yb, 250 xs,ys; 251 word x,y; 252 253 x = y = 0; 254 xs = joy? 2 : 0; // Find shift value for x axis 255 xb = 1 << xs; // Use shift value to get x bit mask 256 ys = joy? 3 : 1; // Do the same for y axis 257 yb = 1 << ys; 258 259 // Read the absolute joystick values 260 asm pushf // Save some registers 261 asm push si 262 asm push di 263 asm cli // Make sure an interrupt doesn't screw the timings 264 265 266 asm mov dx,0x201 267 asm in al,dx 268 asm out dx,al // Clear the resistors 269 270 asm mov ah,[xb] // Get masks into registers 271 asm mov ch,[yb] 272 273 asm xor si,si // Clear count registers 274 asm xor di,di 275 asm xor bh,bh // Clear high byte of bx for later 276 277 asm push bp // Don't mess up stack frame 278 asm mov bp,MaxJoyValue 279 280 loop: 281 asm in al,dx // Get bits indicating whether all are finished 282 283 asm dec bp // Check bounding register 284 asm jz done // We have a silly value - abort 285 286 asm mov bl,al // Duplicate the bits 287 asm and bl,ah // Mask off useless bits (in [xb]) 288 asm add si,bx // Possibly increment count register 289 asm mov cl,bl // Save for testing later 290 291 asm mov bl,al 292 asm and bl,ch // [yb] 293 asm add di,bx 294 295 asm add cl,bl 296 asm jnz loop // If both bits were 0, drop out 297 298 done: 299 asm pop bp 300 301 asm mov cl,[xs] // Get the number of bits to shift 302 asm shr si,cl // and shift the count that many times 303 304 asm mov cl,[ys] 305 asm shr di,cl 306 307 asm mov [x],si // Store the values into the variables 308 asm mov [y],di 309 310 asm pop di 311 asm pop si 312 asm popf // Restore the registers 313 314 *xp = x; 315 *yp = y; 316 } 317 318 /////////////////////////////////////////////////////////////////////////// 319 // 320 // INL_GetJoyDelta() - Returns the relative movement of the specified 321 // joystick (from +/-127) 322 // 323 /////////////////////////////////////////////////////////////////////////// 324 void INL_GetJoyDelta(word joy,int *dx,int *dy) 325 { 326 word x,y; 327 longword time; 328 JoystickDef *def; 329 static longword lasttime; 330 331 IN_GetJoyAbs(joy,&x,&y); 332 def = JoyDefs + joy; 333 334 if (x < def->threshMinX) 335 { 336 if (x < def->joyMinX) 337 x = def->joyMinX; 338 339 x = -(x - def->threshMinX); 340 x *= def->joyMultXL; 341 x >>= JoyScaleShift; 342 *dx = (x > 127)? -127 : -x; 343 } 344 else if (x > def->threshMaxX) 345 { 346 if (x > def->joyMaxX) 347 x = def->joyMaxX; 348 349 x = x - def->threshMaxX; 350 x *= def->joyMultXH; 351 x >>= JoyScaleShift; 352 *dx = (x > 127)? 127 : x; 353 } 354 else 355 *dx = 0; 356 357 if (y < def->threshMinY) 358 { 359 if (y < def->joyMinY) 360 y = def->joyMinY; 361 362 y = -(y - def->threshMinY); 363 y *= def->joyMultYL; 364 y >>= JoyScaleShift; 365 *dy = (y > 127)? -127 : -y; 366 } 367 else if (y > def->threshMaxY) 368 { 369 if (y > def->joyMaxY) 370 y = def->joyMaxY; 371 372 y = y - def->threshMaxY; 373 y *= def->joyMultYH; 374 y >>= JoyScaleShift; 375 *dy = (y > 127)? 127 : y; 376 } 377 else 378 *dy = 0; 379 380 lasttime = TimeCount; 381 } 382 383 /////////////////////////////////////////////////////////////////////////// 384 // 385 // INL_GetJoyButtons() - Returns the button status of the specified 386 // joystick 387 // 388 /////////////////////////////////////////////////////////////////////////// 389 static word 390 INL_GetJoyButtons(word joy) 391 { 392 register word result; 393 394 result = inportb(0x201); // Get all the joystick buttons 395 result >>= joy? 6 : 4; // Shift into bits 0-1 396 result &= 3; // Mask off the useless bits 397 result ^= 3; 398 return(result); 399 } 400 401 /////////////////////////////////////////////////////////////////////////// 402 // 403 // IN_GetJoyButtonsDB() - Returns the de-bounced button status of the 404 // specified joystick 405 // 406 /////////////////////////////////////////////////////////////////////////// 407 word 408 IN_GetJoyButtonsDB(word joy) 409 { 410 longword lasttime; 411 word result1,result2; 412 413 do 414 { 415 result1 = INL_GetJoyButtons(joy); 416 lasttime = TimeCount; 417 while (TimeCount == lasttime) 418 ; 419 result2 = INL_GetJoyButtons(joy); 420 } while (result1 != result2); 421 return(result1); 422 } 423 424 /////////////////////////////////////////////////////////////////////////// 425 // 426 // INL_StartKbd() - Sets up my keyboard stuff for use 427 // 428 /////////////////////////////////////////////////////////////////////////// 429 static void 430 INL_StartKbd(void) 431 { 432 INL_KeyHook = NULL; // no key hook routine 433 434 IN_ClearKeysDown(); 435 436 OldKeyVect = getvect(KeyInt); 437 setvect(KeyInt,INL_KeyService); 438 } 439 440 /////////////////////////////////////////////////////////////////////////// 441 // 442 // INL_ShutKbd() - Restores keyboard control to the BIOS 443 // 444 /////////////////////////////////////////////////////////////////////////// 445 static void 446 INL_ShutKbd(void) 447 { 448 poke(0x40,0x17,peek(0x40,0x17) & 0xfaf0); // Clear ctrl/alt/shift flags 449 450 setvect(KeyInt,OldKeyVect); 451 } 452 453 /////////////////////////////////////////////////////////////////////////// 454 // 455 // INL_StartMouse() - Detects and sets up the mouse 456 // 457 /////////////////////////////////////////////////////////////////////////// 458 static boolean 459 INL_StartMouse(void) 460 { 461 #if 0 462 if (getvect(MouseInt)) 463 { 464 Mouse(MReset); 465 if (_AX == 0xffff) 466 return(true); 467 } 468 return(false); 469 #endif 470 union REGS regs; 471 unsigned char far *vector; 472 473 474 if ((vector=MK_FP(peek(0,0x33*4+2),peek(0,0x33*4)))==NULL) 475 return false; 476 477 if (*vector == 207) 478 return false; 479 480 Mouse(MReset); 481 return true; 482 } 483 484 /////////////////////////////////////////////////////////////////////////// 485 // 486 // INL_ShutMouse() - Cleans up after the mouse 487 // 488 /////////////////////////////////////////////////////////////////////////// 489 static void 490 INL_ShutMouse(void) 491 { 492 } 493 494 // 495 // INL_SetJoyScale() - Sets up scaling values for the specified joystick 496 // 497 static void 498 INL_SetJoyScale(word joy) 499 { 500 JoystickDef *def; 501 502 def = &JoyDefs[joy]; 503 def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX); 504 def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX); 505 def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY); 506 def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY); 507 } 508 509 /////////////////////////////////////////////////////////////////////////// 510 // 511 // IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale() 512 // to set up scaling values 513 // 514 /////////////////////////////////////////////////////////////////////////// 515 void 516 IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy) 517 { 518 word d,r; 519 JoystickDef *def; 520 521 def = &JoyDefs[joy]; 522 523 def->joyMinX = minx; 524 def->joyMaxX = maxx; 525 r = maxx - minx; 526 d = r / 3; 527 def->threshMinX = ((r / 2) - d) + minx; 528 def->threshMaxX = ((r / 2) + d) + minx; 529 530 def->joyMinY = miny; 531 def->joyMaxY = maxy; 532 r = maxy - miny; 533 d = r / 3; 534 def->threshMinY = ((r / 2) - d) + miny; 535 def->threshMaxY = ((r / 2) + d) + miny; 536 537 INL_SetJoyScale(joy); 538 } 539 540 /////////////////////////////////////////////////////////////////////////// 541 // 542 // INL_StartJoy() - Detects & auto-configures the specified joystick 543 // The auto-config assumes the joystick is centered 544 // 545 /////////////////////////////////////////////////////////////////////////// 546 static boolean 547 INL_StartJoy(word joy) 548 { 549 word x,y; 550 551 IN_GetJoyAbs(joy,&x,&y); 552 553 if 554 ( 555 ((x == 0) || (x > MaxJoyValue - 10)) 556 || ((y == 0) || (y > MaxJoyValue - 10)) 557 ) 558 return(false); 559 else 560 { 561 IN_SetupJoy(joy,0,x * 2,0,y * 2); 562 return(true); 563 } 564 } 565 566 /////////////////////////////////////////////////////////////////////////// 567 // 568 // INL_ShutJoy() - Cleans up the joystick stuff 569 // 570 /////////////////////////////////////////////////////////////////////////// 571 static void 572 INL_ShutJoy(word joy) 573 { 574 JoysPresent[joy] = false; 575 } 576 577 578 /////////////////////////////////////////////////////////////////////////// 579 // 580 // IN_Startup() - Starts up the Input Mgr 581 // 582 /////////////////////////////////////////////////////////////////////////// 583 void 584 IN_Startup(void) 585 { 586 boolean checkjoys,checkmouse; 587 word i; 588 589 if (IN_Started) 590 return; 591 592 checkjoys = true; 593 checkmouse = true; 594 for (i = 1;i < _argc;i++) 595 { 596 switch (US_CheckParm(_argv[i],ParmStrings)) 597 { 598 case 0: 599 checkjoys = false; 600 break; 601 case 1: 602 checkmouse = false; 603 break; 604 } 605 } 606 607 INL_StartKbd(); 608 MousePresent = checkmouse? INL_StartMouse() : false; 609 610 for (i = 0;i < MaxJoys;i++) 611 JoysPresent[i] = checkjoys? INL_StartJoy(i) : false; 612 613 IN_Started = true; 614 } 615 616 /////////////////////////////////////////////////////////////////////////// 617 // 618 // IN_Default() - Sets up default conditions for the Input Mgr 619 // 620 /////////////////////////////////////////////////////////////////////////// 621 void 622 IN_Default(boolean gotit,ControlType in) 623 { 624 if 625 ( 626 (!gotit) 627 || ((in == ctrl_Joystick1) && !JoysPresent[0]) 628 || ((in == ctrl_Joystick2) && !JoysPresent[1]) 629 || ((in == ctrl_Mouse) && !MousePresent) 630 ) 631 in = ctrl_Keyboard1; 632 IN_SetControlType(0,in); 633 } 634 635 /////////////////////////////////////////////////////////////////////////// 636 // 637 // IN_Shutdown() - Shuts down the Input Mgr 638 // 639 /////////////////////////////////////////////////////////////////////////// 640 void 641 IN_Shutdown(void) 642 { 643 word i; 644 645 if (!IN_Started) 646 return; 647 648 INL_ShutMouse(); 649 for (i = 0;i < MaxJoys;i++) 650 INL_ShutJoy(i); 651 INL_ShutKbd(); 652 653 IN_Started = false; 654 } 655 656 /////////////////////////////////////////////////////////////////////////// 657 // 658 // IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService() 659 // everytime a real make/break code gets hit 660 // 661 /////////////////////////////////////////////////////////////////////////// 662 void 663 IN_SetKeyHook(void (*hook)()) 664 { 665 INL_KeyHook = hook; 666 } 667 668 /////////////////////////////////////////////////////////////////////////// 669 // 670 // IN_ClearKeysDown() - Clears the keyboard array 671 // 672 /////////////////////////////////////////////////////////////////////////// 673 void 674 IN_ClearKeysDown(void) 675 { 676 int i; 677 678 LastScan = sc_None; 679 LastASCII = key_None; 680 memset (Keyboard,0,sizeof(Keyboard)); 681 } 682 683 684 /////////////////////////////////////////////////////////////////////////// 685 // 686 // IN_ReadControl() - Reads the device associated with the specified 687 // player and fills in the control info struct 688 // 689 /////////////////////////////////////////////////////////////////////////// 690 void 691 IN_ReadControl(int player,ControlInfo *info) 692 { 693 boolean realdelta; 694 byte dbyte; 695 word buttons; 696 int dx,dy; 697 Motion mx,my; 698 ControlType type; 699 register KeyboardDef *def; 700 701 dx = dy = 0; 702 mx = my = motion_None; 703 buttons = 0; 704 705 if (DemoMode == demo_Playback) 706 { 707 dbyte = DemoBuffer[DemoOffset + 1]; 708 my = (dbyte & 3) - 1; 709 mx = ((dbyte >> 2) & 3) - 1; 710 buttons = (dbyte >> 4) & 3; 711 712 if (!(--DemoBuffer[DemoOffset])) 713 { 714 DemoOffset += 2; 715 if (DemoOffset >= DemoSize) 716 DemoMode = demo_PlayDone; 717 } 718 719 realdelta = false; 720 } 721 else if (DemoMode == demo_PlayDone) 722 Quit("Demo playback exceeded"); 723 else 724 { 725 switch (type = Controls[player]) 726 { 727 case ctrl_Keyboard: 728 def = &KbdDefs; 729 730 if (Keyboard[def->upleft]) 731 mx = motion_Left,my = motion_Up; 732 else if (Keyboard[def->upright]) 733 mx = motion_Right,my = motion_Up; 734 else if (Keyboard[def->downleft]) 735 mx = motion_Left,my = motion_Down; 736 else if (Keyboard[def->downright]) 737 mx = motion_Right,my = motion_Down; 738 739 if (Keyboard[def->up]) 740 my = motion_Up; 741 else if (Keyboard[def->down]) 742 my = motion_Down; 743 744 if (Keyboard[def->left]) 745 mx = motion_Left; 746 else if (Keyboard[def->right]) 747 mx = motion_Right; 748 749 if (Keyboard[def->button0]) 750 buttons += 1 << 0; 751 if (Keyboard[def->button1]) 752 buttons += 1 << 1; 753 realdelta = false; 754 break; 755 case ctrl_Joystick1: 756 case ctrl_Joystick2: 757 INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy); 758 buttons = INL_GetJoyButtons(type - ctrl_Joystick); 759 realdelta = true; 760 break; 761 case ctrl_Mouse: 762 INL_GetMouseDelta(&dx,&dy); 763 buttons = INL_GetMouseButtons(); 764 realdelta = true; 765 break; 766 } 767 } 768 769 if (realdelta) 770 { 771 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None); 772 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None); 773 } 774 else 775 { 776 dx = mx * 127; 777 dy = my * 127; 778 } 779 780 info->x = dx; 781 info->xaxis = mx; 782 info->y = dy; 783 info->yaxis = my; 784 info->button0 = buttons & (1 << 0); 785 info->button1 = buttons & (1 << 1); 786 info->button2 = buttons & (1 << 2); 787 info->button3 = buttons & (1 << 3); 788 info->dir = DirTable[((my + 1) * 3) + (mx + 1)]; 789 790 if (DemoMode == demo_Record) 791 { 792 // Pack the control info into a byte 793 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1); 794 795 if 796 ( 797 (DemoBuffer[DemoOffset + 1] == dbyte) 798 && (DemoBuffer[DemoOffset] < 255) 799 ) 800 (DemoBuffer[DemoOffset])++; 801 else 802 { 803 if (DemoOffset || DemoBuffer[DemoOffset]) 804 DemoOffset += 2; 805 806 if (DemoOffset >= DemoSize) 807 Quit("Demo buffer overflow"); 808 809 DemoBuffer[DemoOffset] = 1; 810 DemoBuffer[DemoOffset + 1] = dbyte; 811 } 812 } 813 } 814 815 /////////////////////////////////////////////////////////////////////////// 816 // 817 // IN_SetControlType() - Sets the control type to be used by the specified 818 // player 819 // 820 /////////////////////////////////////////////////////////////////////////// 821 void 822 IN_SetControlType(int player,ControlType type) 823 { 824 // DEBUG - check that requested type is present? 825 Controls[player] = type; 826 } 827 828 /////////////////////////////////////////////////////////////////////////// 829 // 830 // IN_WaitForKey() - Waits for a scan code, then clears LastScan and 831 // returns the scan code 832 // 833 /////////////////////////////////////////////////////////////////////////// 834 ScanCode 835 IN_WaitForKey(void) 836 { 837 ScanCode result; 838 839 while (!(result = LastScan)) 840 ; 841 LastScan = 0; 842 return(result); 843 } 844 845 /////////////////////////////////////////////////////////////////////////// 846 // 847 // IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and 848 // returns the ASCII value 849 // 850 /////////////////////////////////////////////////////////////////////////// 851 char 852 IN_WaitForASCII(void) 853 { 854 char result; 855 856 while (!(result = LastASCII)) 857 ; 858 LastASCII = '\0'; 859 return(result); 860 } 861 862 /////////////////////////////////////////////////////////////////////////// 863 // 864 // IN_Ack() - waits for a button or key press. If a button is down, upon 865 // calling, it must be released for it to be recognized 866 // 867 /////////////////////////////////////////////////////////////////////////// 868 869 boolean btnstate[8]; 870 871 void IN_StartAck(void) 872 { 873 unsigned i,buttons; 874 875 // 876 // get initial state of everything 877 // 878 IN_ClearKeysDown(); 879 memset (btnstate,0,sizeof(btnstate)); 880 881 buttons = IN_JoyButtons () << 4; 882 if (MousePresent) 883 buttons |= IN_MouseButtons (); 884 885 for (i=0;i<8;i++,buttons>>=1) 886 if (buttons&1) 887 btnstate[i] = true; 888 } 889 890 891 boolean IN_CheckAck (void) 892 { 893 unsigned i,buttons; 894 895 // 896 // see if something has been pressed 897 // 898 if (LastScan) 899 return true; 900 901 buttons = IN_JoyButtons () << 4; 902 if (MousePresent) 903 buttons |= IN_MouseButtons (); 904 905 for (i=0;i<8;i++,buttons>>=1) 906 if ( buttons&1 ) 907 { 908 if (!btnstate[i]) 909 return true; 910 } 911 else 912 btnstate[i]=false; 913 914 return false; 915 } 916 917 918 void IN_Ack (void) 919 { 920 IN_StartAck (); 921 922 while (!IN_CheckAck ()) 923 ; 924 } 925 926 927 /////////////////////////////////////////////////////////////////////////// 928 // 929 // IN_UserInput() - Waits for the specified delay time (in ticks) or the 930 // user pressing a key or a mouse button. If the clear flag is set, it 931 // then either clears the key or waits for the user to let the mouse 932 // button up. 933 // 934 /////////////////////////////////////////////////////////////////////////// 935 boolean IN_UserInput(longword delay) 936 { 937 longword lasttime; 938 939 lasttime = TimeCount; 940 IN_StartAck (); 941 do 942 { 943 if (IN_CheckAck()) 944 return true; 945 } while (TimeCount - lasttime < delay); 946 return(false); 947 } 948 949 //=========================================================================== 950 951 /* 952 =================== 953 = 954 = IN_MouseButtons 955 = 956 =================== 957 */ 958 959 byte IN_MouseButtons (void) 960 { 961 if (MousePresent) 962 { 963 Mouse(MButtons); 964 return _BX; 965 } 966 else 967 return 0; 968 } 969 970 971 /* 972 =================== 973 = 974 = IN_JoyButtons 975 = 976 =================== 977 */ 978 979 byte IN_JoyButtons (void) 980 { 981 unsigned joybits; 982 983 joybits = inportb(0x201); // Get all the joystick buttons 984 joybits >>= 4; // only the high bits are useful 985 joybits ^= 15; // return with 1=pressed 986 987 return joybits; 988 } 989 990