mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-11 07:42:18 +00:00
614 lines
12 KiB
C
614 lines
12 KiB
C
/*
|
|
in_dos.c
|
|
|
|
@description@
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
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:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
$Id$
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#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;
|
|
|
|
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;
|
|
cvar_t *joy_numbuttons;
|
|
|
|
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;
|
|
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->int_val)
|
|
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;
|
|
|
|
m_filter = Cvar_Get ("m_filter", "0", CVAR_ARCHIVE, NULL, "None");
|
|
in_joystick = Cvar_Get ("joystick", "0", CVAR_ARCHIVE, NULL, "None");
|
|
joy_numbuttons = Cvar_Get ("joybuttons", "4", CVAR_ARCHIVE, NULL, "None");
|
|
aux_look = Cvar_Get ("auxlook", "1", CVAR_ARCHIVE, NULL, "None");
|
|
Cmd_AddCommand ("toggle_auxlook", Toggle_AuxLook_f, "No Description");
|
|
Cmd_AddCommand ("force_centerview", Force_CenterView_f, "No Description");
|
|
|
|
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->int_val; 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 (void)
|
|
{
|
|
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->int_val) {
|
|
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->int_val && (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) && !(in_strafe.state & 1)) {
|
|
viewdelta.angles[PITCH] += mouse_y;
|
|
} else {
|
|
if (in_strafe.state & 1)
|
|
viewdelta.position[1] -= mouse_y;
|
|
else
|
|
viewdelta.position[2] -= mouse_y;
|
|
}
|
|
}
|
|
|
|
/*
|
|
===========
|
|
IN_JoyMove
|
|
===========
|
|
*/
|
|
void
|
|
IN_JoyMove (void)
|
|
{
|
|
float speed, aspeed;
|
|
|
|
if (!joy_avail || !in_joystick->int_val)
|
|
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 (void)
|
|
{
|
|
IN_MouseMove ();
|
|
IN_JoyMove ();
|
|
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;
|
|
IN_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;
|
|
IN_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->int_val
|
|
|| in_mlook.state & 1);
|
|
|
|
if (freelook)
|
|
V_StopPitchDrift ();
|
|
}
|
|
|
|
void
|
|
IN_HandlePause (qboolean pause)
|
|
{
|
|
}
|