ref: 3891487cd9fb5088d99344d33cf4e37e0abf7f9b
dir: /in.c/
#define KeyInt 9 // The keyboard ISR number /* ============================================================================= GLOBAL VARIABLES ============================================================================= */ // // configuration variables // int MousePresent; // Global variables int Keyboard[NumCodes]; int Paused; char LastASCII; u8int LastScan; KeyboardDef KbdDefs = {0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}; ControlType Controls[MaxPlayers]; u32int MouseDownCount; Demo DemoMode = demo_Off; u8int _seg *DemoBuffer; u16int DemoOffset,DemoSize; /* ============================================================================= LOCAL VARIABLES ============================================================================= */ static u8int far ASCIINames[] = // Unshifted ASCII for scan codes { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 }, far ShiftNames[] = // Shifted ASCII for scan codes { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 }, far SpecialNames[] = // ASCII for 0xe0 prefixed codes { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 }; static int CapsLock; static u8int CurCode,LastCode; static Direction DirTable[] = // Quick lookup for total direction { dir_NorthWest, dir_North, dir_NorthEast, dir_West, dir_None, dir_East, dir_SouthWest, dir_South, dir_SouthEast }; static void (*INL_KeyHook)(void); static void interrupt (*OldKeyVect)(void); // Internal routines /////////////////////////////////////////////////////////////////////////// // // INL_KeyService() - Handles a keyboard interrupt (key up/down) // /////////////////////////////////////////////////////////////////////////// static void interrupt INL_KeyService(void) { static int special; u8int k,c, temp; s16int i; k = inportb(0x60); // Get the scan code // Tell the XT keyboard controller to clear the key outportb(0x61,(temp = inportb(0x61)) | 0x80); outportb(0x61,temp); if (k == 0xe0) // Special key prefix special = true; else if (k == 0xe1) // Handle Pause key Paused = true; else { if (k & 0x80) // Break code { k &= 0x7f; // DEBUG - handle special keys: ctl-alt-delete, print scrn Keyboard[k] = false; } else // Make code { LastCode = CurCode; CurCode = LastScan = k; Keyboard[k] = true; if (special) c = SpecialNames[k]; else { if (k == sc_CapsLock) { CapsLock ^= true; // DEBUG - make caps lock light work } if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted { c = ShiftNames[k]; if ((c >= 'A') && (c <= 'Z') && CapsLock) c += 'a' - 'A'; } else { c = ASCIINames[k]; if ((c >= 'a') && (c <= 'z') && CapsLock) c -= 'a' - 'A'; } } if (c) LastASCII = c; } special = false; } if (INL_KeyHook && !special) INL_KeyHook(); outportb(0x20,0x20); } /////////////////////////////////////////////////////////////////////////// // // INL_GetMouseDelta() - Gets the amount that the mouse has moved from the // mouse driver // /////////////////////////////////////////////////////////////////////////// static void INL_GetMouseDelta(s16int *x,s16int *y) { Mouse(MDelta); *x = _CX; *y = _DX; } /////////////////////////////////////////////////////////////////////////// // // INL_GetMouseButtons() - Gets the status of the mouse buttons from the // mouse driver // /////////////////////////////////////////////////////////////////////////// static u16int INL_GetMouseButtons(void) { u16int buttons; Mouse(MButtons); buttons = _BX; return(buttons); } /////////////////////////////////////////////////////////////////////////// // // INL_StartKbd() - Sets up my keyboard stuff for use // /////////////////////////////////////////////////////////////////////////// static void INL_StartKbd(void) { INL_KeyHook = NULL; // no key hook routine IN_ClearKeysDown(); OldKeyVect = getvect(KeyInt); setvect(KeyInt,INL_KeyService); } /////////////////////////////////////////////////////////////////////////// // // IN_Startup() - Starts up the Input Mgr // /////////////////////////////////////////////////////////////////////////// void IN_Startup(void) { INL_StartKbd(); } /////////////////////////////////////////////////////////////////////////// // // IN_Default() - Sets up default conditions for the Input Mgr // /////////////////////////////////////////////////////////////////////////// void IN_Default(int gotit,ControlType in) { if ( (!gotit) || ((in == ctrl_Mouse) && !MousePresent) ) in = ctrl_Keyboard1; IN_SetControlType(0,in); } /////////////////////////////////////////////////////////////////////////// // // IN_Shutdown() - Shuts down the Input Mgr // /////////////////////////////////////////////////////////////////////////// void IN_Shutdown(void) { } /////////////////////////////////////////////////////////////////////////// // // IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService() // everytime a real make/break code gets hit // /////////////////////////////////////////////////////////////////////////// void IN_SetKeyHook(void (*hook)()) { INL_KeyHook = hook; } /////////////////////////////////////////////////////////////////////////// // // IN_ClearKeysDown() - Clears the keyboard array // /////////////////////////////////////////////////////////////////////////// void IN_ClearKeysDown(void) { s16int i; LastScan = sc_None; LastASCII = key_None; memset (Keyboard,0,sizeof(Keyboard)); } /////////////////////////////////////////////////////////////////////////// // // IN_ReadControl() - Reads the device associated with the specified // player and fills in the control info struct // /////////////////////////////////////////////////////////////////////////// void IN_ReadControl(s16int player,ControlInfo *info) { int realdelta; u8int dbyte; u16int buttons; s16int dx,dy; Motion mx,my; ControlType type; register KeyboardDef *def; dx = dy = 0; mx = my = motion_None; buttons = 0; if (DemoMode == demo_Playback) { dbyte = DemoBuffer[DemoOffset + 1]; my = (dbyte & 3) - 1; mx = ((dbyte >> 2) & 3) - 1; buttons = (dbyte >> 4) & 3; if (!(--DemoBuffer[DemoOffset])) { DemoOffset += 2; if (DemoOffset >= DemoSize) DemoMode = demo_PlayDone; } realdelta = false; } else if (DemoMode == demo_PlayDone) Quit("Demo playback exceeded"); else { switch (type = Controls[player]) { case ctrl_Keyboard: def = &KbdDefs; if (Keyboard[def->upleft]) mx = motion_Left,my = motion_Up; else if (Keyboard[def->upright]) mx = motion_Right,my = motion_Up; else if (Keyboard[def->downleft]) mx = motion_Left,my = motion_Down; else if (Keyboard[def->downright]) mx = motion_Right,my = motion_Down; if (Keyboard[def->up]) my = motion_Up; else if (Keyboard[def->down]) my = motion_Down; if (Keyboard[def->left]) mx = motion_Left; else if (Keyboard[def->right]) mx = motion_Right; if (Keyboard[def->button0]) buttons += 1 << 0; if (Keyboard[def->button1]) buttons += 1 << 1; realdelta = false; break; case ctrl_Mouse: INL_GetMouseDelta(&dx,&dy); buttons = INL_GetMouseButtons(); realdelta = true; break; } } if (realdelta) { mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None); my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None); } else { dx = mx * 127; dy = my * 127; } info->x = dx; info->xaxis = mx; info->y = dy; info->yaxis = my; info->button0 = buttons & (1 << 0); info->button1 = buttons & (1 << 1); info->button2 = buttons & (1 << 2); info->button3 = buttons & (1 << 3); info->dir = DirTable[((my + 1) * 3) + (mx + 1)]; if (DemoMode == demo_Record) { // Pack the control info into a byte dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1); if ( (DemoBuffer[DemoOffset + 1] == dbyte) && (DemoBuffer[DemoOffset] < 255) ) (DemoBuffer[DemoOffset])++; else { if (DemoOffset || DemoBuffer[DemoOffset]) DemoOffset += 2; if (DemoOffset >= DemoSize) Quit("Demo buffer overflow"); DemoBuffer[DemoOffset] = 1; DemoBuffer[DemoOffset + 1] = dbyte; } } } /////////////////////////////////////////////////////////////////////////// // // IN_SetControlType() - Sets the control type to be used by the specified // player // /////////////////////////////////////////////////////////////////////////// void IN_SetControlType(s16int player,ControlType type) { // DEBUG - check that requested type is present? Controls[player] = type; } /////////////////////////////////////////////////////////////////////////// // // IN_WaitForKey() - Waits for a scan code, then clears LastScan and // returns the scan code // /////////////////////////////////////////////////////////////////////////// u8int IN_WaitForKey(void) { u8int result; while (!(result = LastScan)) ; LastScan = 0; return(result); } /////////////////////////////////////////////////////////////////////////// // // IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and // returns the ASCII value // /////////////////////////////////////////////////////////////////////////// char IN_WaitForASCII(void) { char result; while (!(result = LastASCII)) ; LastASCII = '\0'; return(result); } /////////////////////////////////////////////////////////////////////////// // // IN_Ack() - waits for a button or key press. If a button is down, upon // calling, it must be released for it to be recognized // /////////////////////////////////////////////////////////////////////////// int btnstate[8]; void IN_StartAck(void) { u16int i,buttons; // // get initial state of everything // IN_ClearKeysDown(); memset (btnstate,0,sizeof(btnstate)); if (MousePresent) buttons |= IN_MouseButtons (); for (i=0;i<8;i++,buttons>>=1) if (buttons&1) btnstate[i] = true; } int IN_CheckAck (void) { u16int i,buttons; // // see if something has been pressed // if (LastScan) return true; if (MousePresent) buttons |= IN_MouseButtons (); for (i=0;i<8;i++,buttons>>=1) if ( buttons&1 ) { if (!btnstate[i]) return true; } else btnstate[i]=false; return false; } void IN_Ack (void) { IN_StartAck (); while (!IN_CheckAck ()) ; } /////////////////////////////////////////////////////////////////////////// // // IN_UserInput() - Waits for the specified delay time (in ticks) or the // user pressing a key or a mouse button. If the clear flag is set, it // then either clears the key or waits for the user to let the mouse // button up. // /////////////////////////////////////////////////////////////////////////// int IN_UserInput(u32int delay) { u32int lasttime; lasttime = TimeCount; IN_StartAck (); do { if (IN_CheckAck()) return true; } while (TimeCount - lasttime < delay); return(false); } //=========================================================================== /* =================== = = IN_MouseButtons = =================== */ u8int IN_MouseButtons (void) { if (MousePresent) { Mouse(MButtons); return _BX; } else return 0; }