quakeforge-old/common/in_dos.c
2000-01-06 13:48:07 +00:00

617 lines
12 KiB
C

/*
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 1999,2000 contributors of the QuakeForge project
Please see the file "AUTHORS" for a list of contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// in_mouse.c -- dos mouse code
#include "quakedef.h"
#include "dosisms.h"
#define AUX_FLAG_FREELOOK 0x00000001
typedef struct
{
long interruptVector;
char deviceName[16];
long numAxes;
long numButtons;
long flags;
vec3_t viewangles;
// intended velocities
float forwardmove;
float sidemove;
float upmove;
long buttons;
} externControl_t;
/*
#define AUX_FLAG_FORCEFREELOOK 0x00000001 // r/o
#define AUX_FLAG_EXTENDED 0x00000002 // r/o
#define AUX_FLAG_RUN 0x00000004 // w/o
#define AUX_FLAG_STRAFE 0x00000008 // w/o
#define AUX_FLAG_FREELOOK 0x00000010 // w/o
#define AUX_MAP_UNDEFINED 0
#define AUX_MAP_PITCH 1
#define AUX_MAP_YAW 2
#define AUX_MAP_ROLL 3
#define AUX_MAP_FORWARD 4
#define AUX_MAP_SIDE 5
#define AUX_MAP_UP 6
typedef struct
{
long interruptVector;
// r/o
char deviceName[16];
// r/o
long numAxes;
// r/o 1-6
long numButtons; // r/o 0-32
long flags; // see above
byte axisMapping[6]; // w/o default = p,y,r,f,s,u
float axisValue[6]; // r/w
float sensitivity[6]; // w/o default = 1.0
long buttons; // r/o
float last_frame_time; // w/o
} externControl_t;
*/
cvar_t m_filter = {"m_filter","1"};
qboolean mouse_avail;
int mouse_buttons;
int mouse_oldbuttonstate;
int mouse_buttonstate;
float mouse_x, mouse_y;
float old_mouse_x, old_mouse_y;
cvar_t in_joystick = {"joystick","1"};
cvar_t joy_numbuttons = {"joybuttons","4", true};
qboolean joy_avail;
int joy_oldbuttonstate;
int joy_buttonstate;
int joyxl, joyxh, joyyl, joyyh;
int joystickx, joysticky;
qboolean need_center;
qboolean extern_avail;
int extern_buttons;
int extern_oldbuttonstate;
int extern_buttonstate;
cvar_t aux_look = {"auxlook","1", true};
externControl_t *extern_control;
void IN_StartupExternal (void);
void IN_ExternalMove (usercmd_t *cmd);
void IN_StartupJoystick (void);
qboolean IN_ReadJoystick (void);
void Toggle_AuxLook_f (void)
{
if (aux_look.value)
Cvar_Set ("auxlook","0");
else
Cvar_Set ("auxlook","1");
}
void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
}
/*
===========
IN_StartupMouse
===========
*/
void IN_StartupMouse (void)
{
if ( COM_CheckParm ("-nomouse") )
return;
// check for mouse
regs.x.ax = 0;
dos_int86(0x33);
mouse_avail = regs.x.ax;
if (!mouse_avail)
{
Con_Printf ("No mouse found\n");
return;
}
mouse_buttons = regs.x.bx;
if (mouse_buttons > 3)
mouse_buttons = 3;
Con_Printf("%d-button mouse available\n", mouse_buttons);
}
/*
===========
IN_Init
===========
*/
void IN_Init (void)
{
int i;
Cvar_RegisterVariable (&m_filter);
Cvar_RegisterVariable (&in_joystick);
Cvar_RegisterVariable (&joy_numbuttons);
Cvar_RegisterVariable (&aux_look);
Cmd_AddCommand ("toggle_auxlook", Toggle_AuxLook_f);
Cmd_AddCommand ("force_centerview", Force_CenterView_f);
IN_StartupMouse ();
IN_StartupJoystick ();
i = COM_CheckParm ("-control");
if (i)
{
extern_control = real2ptr(Q_atoi (com_argv[i+1]));
IN_StartupExternal ();
}
}
/*
===========
IN_Shutdown
===========
*/
void IN_Shutdown (void)
{
}
/*
===========
IN_Commands
===========
*/
void IN_Commands (void)
{
int i;
if (mouse_avail)
{
regs.x.ax = 3; // read buttons
dos_int86(0x33);
mouse_buttonstate = regs.x.bx;
// perform button actions
for (i=0 ; i<mouse_buttons ; i++)
{
if ( (mouse_buttonstate & (1<<i)) &&
!(mouse_oldbuttonstate & (1<<i)) )
{
Key_Event (K_MOUSE1 + i, true);
}
if ( !(mouse_buttonstate & (1<<i)) &&
(mouse_oldbuttonstate & (1<<i)) )
{
Key_Event (K_MOUSE1 + i, false);
}
}
mouse_oldbuttonstate = mouse_buttonstate;
}
if (joy_avail)
{
joy_buttonstate = ((dos_inportb(0x201) >> 4)&15)^15;
// perform button actions
for (i=0 ; i<joy_numbuttons.value ; i++)
{
if ( (joy_buttonstate & (1<<i)) &&
!(joy_oldbuttonstate & (1<<i)) )
{
Key_Event (K_JOY1 + i, true);
}
if ( !(joy_buttonstate & (1<<i)) &&
(joy_oldbuttonstate & (1<<i)) )
{
Key_Event (K_JOY1 + i, false);
}
}
joy_oldbuttonstate = joy_buttonstate;
}
if (extern_avail)
{
extern_buttonstate = extern_control->buttons;
// perform button actions
for (i=0 ; i<extern_buttons ; i++)
{
if ( (extern_buttonstate & (1<<i)) &&
!(extern_oldbuttonstate & (1<<i)) )
{
Key_Event (K_AUX1 + i, true);
}
if ( !(extern_buttonstate & (1<<i)) &&
(extern_oldbuttonstate & (1<<i)) )
{
Key_Event (K_AUX1 + i, false);
}
}
extern_oldbuttonstate = extern_buttonstate;
}
}
/*
===========
IN_Move
===========
*/
void IN_MouseMove (usercmd_t *cmd)
{
int mx, my;
if (!mouse_avail)
return;
regs.x.ax = 11; // read move
dos_int86(0x33);
mx = (short)regs.x.cx;
my = (short)regs.x.dx;
if (m_filter.value)
{
mouse_x = (mx + old_mouse_x) * 0.5;
mouse_y = (my + old_mouse_y) * 0.5;
}
else
{
mouse_x = mx;
mouse_y = my;
}
old_mouse_x = mx;
old_mouse_y = my;
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
// add mouse X/Y movement to cmd
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
{
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
}
else
{
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
}
/*
===========
IN_JoyMove
===========
*/
void IN_JoyMove (usercmd_t *cmd)
{
float speed, aspeed;
if (!joy_avail || !in_joystick.value)
return;
IN_ReadJoystick ();
if (joysticky > joyyh*2 || joystickx > joyxh*2)
return; // assume something jumped in and messed up the joystick
// reading time (win 95)
if (in_speed.state & 1)
speed = cl_movespeedkey.value;
else
speed = 1;
aspeed = speed*host_frametime;
if (in_strafe.state & 1)
{
if (joystickx < joyxl)
cmd->sidemove -= speed*cl_sidespeed.value;
else if (joystickx > joyxh)
cmd->sidemove += speed*cl_sidespeed.value;
}
else
{
if (joystickx < joyxl)
cl.viewangles[YAW] += aspeed*cl_yawspeed.value;
else if (joystickx > joyxh)
cl.viewangles[YAW] -= aspeed*cl_yawspeed.value;
cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
}
if (in_mlook.state & 1)
{
if (m_pitch.value < 0)
speed *= -1;
if (joysticky < joyyl)
cl.viewangles[PITCH] += aspeed*cl_pitchspeed.value;
else if (joysticky > joyyh)
cl.viewangles[PITCH] -= aspeed*cl_pitchspeed.value;
}
else
{
if (joysticky < joyyl)
cmd->forwardmove += speed*cl_forwardspeed.value;
else if (joysticky > joyyh)
cmd->forwardmove -= speed*cl_backspeed.value;
}
}
/*
===========
IN_Move
===========
*/
void IN_Move (usercmd_t *cmd)
{
IN_MouseMove (cmd);
IN_JoyMove (cmd);
IN_ExternalMove (cmd);
}
/*
============================================================================
JOYSTICK
============================================================================
*/
qboolean IN_ReadJoystick (void)
{
int b;
int count;
joystickx = 0;
joysticky = 0;
count = 0;
b = dos_inportb(0x201);
dos_outportb(0x201, b);
// clear counters
while (++count < 10000)
{
b = dos_inportb(0x201);
joystickx += b&1;
joysticky += (b&2)>>1;
if ( !(b&3) )
return true;
}
Con_Printf ("IN_ReadJoystick: no response\n");
joy_avail = false;
return false;
}
/*
=============
WaitJoyButton
=============
*/
qboolean WaitJoyButton (void)
{
int oldbuttons, buttons;
oldbuttons = 0;
do
{
key_count = -1;
Sys_SendKeyEvents ();
key_count = 0;
if (key_lastpress == K_ESCAPE)
{
Con_Printf ("aborted.\n");
return false;
}
key_lastpress = 0;
SCR_UpdateScreen ();
buttons = ((dos_inportb(0x201) >> 4)&1)^1;
if (buttons != oldbuttons)
{
oldbuttons = buttons;
continue;
}
} while ( !buttons);
do
{
key_count = -1;
Sys_SendKeyEvents ();
key_count = 0;
if (key_lastpress == K_ESCAPE)
{
Con_Printf ("aborted.\n");
return false;
}
key_lastpress = 0;
SCR_UpdateScreen ();
buttons = ((dos_inportb(0x201) >> 4)&1)^1;
if (buttons != oldbuttons)
{
oldbuttons = buttons;
continue;
}
} while ( buttons);
return true;
}
/*
===============
IN_StartupJoystick
===============
*/
void IN_StartupJoystick (void)
{
int centerx, centery;
Con_Printf ("\n");
joy_avail = false;
if ( COM_CheckParm ("-nojoy") )
return;
if (!IN_ReadJoystick ())
{
joy_avail = false;
Con_Printf ("joystick not found\n");
return;
}
Con_Printf ("joystick found\n");
Con_Printf ("CENTER the joystick\nand press button 1 (ESC to skip):\n");
if (!WaitJoyButton ())
return;
IN_ReadJoystick ();
centerx = joystickx;
centery = joysticky;
Con_Printf ("Push the joystick to the UPPER LEFT\nand press button 1 (ESC to skip):\n");
if (!WaitJoyButton ())
return;
IN_ReadJoystick ();
joyxl = (centerx + joystickx)/2;
joyyl = (centerx + joysticky)/2;
Con_Printf ("Push the joystick to the LOWER RIGHT\nand press button 1 (ESC to skip):\n");
if (!WaitJoyButton ())
return;
IN_ReadJoystick ();
joyxh = (centerx + joystickx)/2;
joyyh = (centery + joysticky)/2;
joy_avail = true;
Con_Printf ("joystick configured.\n");
Con_Printf ("\n");
}
/*
============================================================================
EXTERNAL
============================================================================
*/
/*
===============
IN_StartupExternal
===============
*/
void IN_StartupExternal (void)
{
if (extern_control->numButtons > 32)
extern_control->numButtons = 32;
Con_Printf("%s Initialized\n", extern_control->deviceName);
Con_Printf(" %u axes %u buttons\n", extern_control->numAxes, extern_control->numButtons);
extern_avail = true;
extern_buttons = extern_control->numButtons;
}
/*
===========
IN_ExternalMove
===========
*/
void IN_ExternalMove (usercmd_t *cmd)
{
qboolean freelook;
if (! extern_avail)
return;
extern_control->viewangles[YAW] = cl.viewangles[YAW];
extern_control->viewangles[PITCH] = cl.viewangles[PITCH];
extern_control->viewangles[ROLL] = cl.viewangles[ROLL];
extern_control->forwardmove = cmd->forwardmove;
extern_control->sidemove = cmd->sidemove;
extern_control->upmove = cmd->upmove;
Con_DPrintf("IN: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove);
dos_int86(extern_control->interruptVector);
Con_DPrintf("OUT: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove);
cl.viewangles[YAW] = extern_control->viewangles[YAW];
cl.viewangles[PITCH] = extern_control->viewangles[PITCH];
cl.viewangles[ROLL] = extern_control->viewangles[ROLL];
cmd->forwardmove = extern_control->forwardmove;
cmd->sidemove = extern_control->sidemove;
cmd->upmove = extern_control->upmove;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
freelook = (extern_control->flags & AUX_FLAG_FREELOOK || aux_look.value || in_mlook.state & 1);
if (freelook)
V_StopPitchDrift ();
}