ref: 0441e14568c0254ba99e516d1282fd196cb1e0a3
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;
}