Home | History | Annotate | Download | only in WinQuake
      1 /*
      2 Copyright (C) 1996-1997 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // in_mouse.c -- dos mouse code
     21 
     22 #include "quakedef.h"
     23 #include "dosisms.h"
     24 
     25 #define AUX_FLAG_FREELOOK	0x00000001
     26 
     27 typedef struct
     28 {
     29 	long    interruptVector;
     30 	char    deviceName[16];
     31 	long    numAxes;
     32 	long	numButtons;
     33 	long	flags;
     34 
     35 	vec3_t  viewangles;
     36 
     37 // intended velocities
     38 	float   forwardmove;
     39 	float   sidemove;
     40 	float   upmove;
     41 
     42 	long	buttons;
     43 } externControl_t;
     44 
     45 /*
     46 #define AUX_FLAG_FORCEFREELOOK	0x00000001	// r/o
     47 #define AUX_FLAG_EXTENDED		0x00000002	// r/o
     48 #define AUX_FLAG_RUN			0x00000004	// w/o
     49 #define AUX_FLAG_STRAFE			0x00000008	// w/o
     50 #define AUX_FLAG_FREELOOK		0x00000010	// w/o
     51 
     52 #define AUX_MAP_UNDEFINED	0
     53 #define AUX_MAP_PITCH		1
     54 #define AUX_MAP_YAW			2
     55 #define AUX_MAP_ROLL		3
     56 #define AUX_MAP_FORWARD		4
     57 #define AUX_MAP_SIDE		5
     58 #define AUX_MAP_UP			6
     59 
     60 typedef struct
     61 {
     62 	long    interruptVector;
     63 	// r/o
     64 	char    deviceName[16];
     65 	// r/o
     66 	long    numAxes;
     67 			// r/o	1-6
     68 	long	numButtons;			// r/o	0-32
     69 	long	flags;				// see above
     70 	byte	axisMapping[6];		// w/o	default = p,y,r,f,s,u
     71 	float	axisValue[6];		// r/w
     72 	float	sensitivity[6];		// w/o	default = 1.0
     73 	long	buttons;			// r/o
     74 	float	last_frame_time;	// w/o
     75 } externControl_t;
     76 */
     77 
     78 cvar_t	m_filter = {"m_filter","1"};
     79 
     80 qboolean	mouse_avail;
     81 int		mouse_buttons;
     82 int		mouse_oldbuttonstate;
     83 int		mouse_buttonstate;
     84 float	mouse_x, mouse_y;
     85 float	old_mouse_x, old_mouse_y;
     86 
     87 
     88 cvar_t	in_joystick = {"joystick","1"};
     89 cvar_t	joy_numbuttons = {"joybuttons","4", true};
     90 
     91 qboolean	joy_avail;
     92 int		joy_oldbuttonstate;
     93 int		joy_buttonstate;
     94 
     95 int     joyxl, joyxh, joyyl, joyyh;
     96 int		joystickx, joysticky;
     97 
     98 qboolean		need_center;
     99 
    100 qboolean		extern_avail;
    101 int				extern_buttons;
    102 int				extern_oldbuttonstate;
    103 int				extern_buttonstate;
    104 cvar_t	aux_look = {"auxlook","1", true};
    105 externControl_t	*extern_control;
    106 void IN_StartupExternal (void);
    107 void IN_ExternalMove (usercmd_t *cmd);
    108 
    109 void IN_StartupJoystick (void);
    110 qboolean IN_ReadJoystick (void);
    111 
    112 
    113 void Toggle_AuxLook_f (void)
    114 {
    115 	if (aux_look.value)
    116 		Cvar_Set ("auxlook","0");
    117 	else
    118 		Cvar_Set ("auxlook","1");
    119 }
    120 
    121 
    122 void Force_CenterView_f (void)
    123 {
    124 	cl.viewangles[PITCH] = 0;
    125 }
    126 
    127 
    128 /*
    129 ===========
    130 IN_StartupMouse
    131 ===========
    132 */
    133 void IN_StartupMouse (void)
    134 {
    135 	if ( COM_CheckParm ("-nomouse") )
    136 		return;
    137 
    138 // check for mouse
    139 	regs.x.ax = 0;
    140 	dos_int86(0x33);
    141 	mouse_avail = regs.x.ax;
    142 	if (!mouse_avail)
    143 	{
    144 		Con_Printf ("No mouse found\n");
    145 		return;
    146 	}
    147 
    148 	mouse_buttons = regs.x.bx;
    149 	if (mouse_buttons > 3)
    150 		mouse_buttons = 3;
    151 	Con_Printf("%d-button mouse available\n", mouse_buttons);
    152 }
    153 
    154 /*
    155 ===========
    156 IN_Init
    157 ===========
    158 */
    159 void IN_Init (void)
    160 {
    161 	int i;
    162 
    163 	Cvar_RegisterVariable (&m_filter);
    164 	Cvar_RegisterVariable (&in_joystick);
    165 	Cvar_RegisterVariable (&joy_numbuttons);
    166 	Cvar_RegisterVariable (&aux_look);
    167 	Cmd_AddCommand ("toggle_auxlook", Toggle_AuxLook_f);
    168 	Cmd_AddCommand ("force_centerview", Force_CenterView_f);
    169 
    170 	IN_StartupMouse ();
    171 	IN_StartupJoystick ();
    172 
    173 	i = COM_CheckParm ("-control");
    174 	if (i)
    175 	{
    176 		extern_control = real2ptr(Q_atoi (com_argv[i+1]));
    177 		IN_StartupExternal ();
    178 	}
    179 }
    180 
    181 /*
    182 ===========
    183 IN_Shutdown
    184 ===========
    185 */
    186 void IN_Shutdown (void)
    187 {
    188 
    189 }
    190 
    191 
    192 /*
    193 ===========
    194 IN_Commands
    195 ===========
    196 */
    197 void IN_Commands (void)
    198 {
    199 	int		i;
    200 
    201 	if (mouse_avail)
    202 	{
    203 		regs.x.ax = 3;		// read buttons
    204 		dos_int86(0x33);
    205 		mouse_buttonstate = regs.x.bx;
    206 
    207 	// perform button actions
    208 		for (i=0 ; i<mouse_buttons ; i++)
    209 		{
    210 			if ( (mouse_buttonstate & (1<<i)) &&
    211 			!(mouse_oldbuttonstate & (1<<i)) )
    212 			{
    213 				Key_Event (K_MOUSE1 + i, true);
    214 			}
    215 			if ( !(mouse_buttonstate & (1<<i)) &&
    216 			(mouse_oldbuttonstate & (1<<i)) )
    217 			{
    218 				Key_Event (K_MOUSE1 + i, false);
    219 			}
    220 		}
    221 
    222 		mouse_oldbuttonstate = mouse_buttonstate;
    223 	}
    224 
    225 	if (joy_avail)
    226 	{
    227 		joy_buttonstate = ((dos_inportb(0x201) >> 4)&15)^15;
    228 	// perform button actions
    229 		for (i=0 ; i<joy_numbuttons.value ; i++)
    230 		{
    231 			if ( (joy_buttonstate & (1<<i)) &&
    232 			!(joy_oldbuttonstate & (1<<i)) )
    233 			{
    234 				Key_Event (K_JOY1 + i, true);
    235 			}
    236 			if ( !(joy_buttonstate & (1<<i)) &&
    237 			(joy_oldbuttonstate & (1<<i)) )
    238 			{
    239 				Key_Event (K_JOY1 + i, false);
    240 			}
    241 		}
    242 
    243 		joy_oldbuttonstate = joy_buttonstate;
    244 	}
    245 
    246 	if (extern_avail)
    247 	{
    248 		extern_buttonstate = extern_control->buttons;
    249 
    250 	// perform button actions
    251 		for (i=0 ; i<extern_buttons ; i++)
    252 		{
    253 			if ( (extern_buttonstate & (1<<i)) &&
    254 			!(extern_oldbuttonstate & (1<<i)) )
    255 			{
    256 				Key_Event (K_AUX1 + i, true);
    257 			}
    258 			if ( !(extern_buttonstate & (1<<i)) &&
    259 			(extern_oldbuttonstate & (1<<i)) )
    260 			{
    261 				Key_Event (K_AUX1 + i, false);
    262 			}
    263 		}
    264 
    265 		extern_oldbuttonstate = extern_buttonstate;
    266 	}
    267 
    268 }
    269 
    270 
    271 /*
    272 ===========
    273 IN_Move
    274 ===========
    275 */
    276 void IN_MouseMove (usercmd_t *cmd)
    277 {
    278 	int		mx, my;
    279 
    280 	if (!mouse_avail)
    281 		return;
    282 
    283 	regs.x.ax = 11;		// read move
    284 	dos_int86(0x33);
    285 	mx = (short)regs.x.cx;
    286 	my = (short)regs.x.dx;
    287 
    288 	if (m_filter.value)
    289 	{
    290 		mouse_x = (mx + old_mouse_x) * 0.5;
    291 		mouse_y = (my + old_mouse_y) * 0.5;
    292 	}
    293 	else
    294 	{
    295 		mouse_x = mx;
    296 		mouse_y = my;
    297 	}
    298 	old_mouse_x = mx;
    299 	old_mouse_y = my;
    300 
    301 	mouse_x *= sensitivity.value;
    302 	mouse_y *= sensitivity.value;
    303 
    304 // add mouse X/Y movement to cmd
    305 	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
    306 		cmd->sidemove += m_side.value * mouse_x;
    307 	else
    308 		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
    309 
    310 	if (in_mlook.state & 1)
    311 		V_StopPitchDrift ();
    312 
    313 	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
    314 	{
    315 		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
    316 		if (cl.viewangles[PITCH] > 80)
    317 			cl.viewangles[PITCH] = 80;
    318 		if (cl.viewangles[PITCH] < -70)
    319 			cl.viewangles[PITCH] = -70;
    320 	}
    321 	else
    322 	{
    323 		if ((in_strafe.state & 1) && noclip_anglehack)
    324 			cmd->upmove -= m_forward.value * mouse_y;
    325 		else
    326 			cmd->forwardmove -= m_forward.value * mouse_y;
    327 	}
    328 }
    329 
    330 /*
    331 ===========
    332 IN_JoyMove
    333 ===========
    334 */
    335 void IN_JoyMove (usercmd_t *cmd)
    336 {
    337 	float	speed, aspeed;
    338 
    339 	if (!joy_avail || !in_joystick.value)
    340 		return;
    341 
    342 	IN_ReadJoystick ();
    343 	if (joysticky > joyyh*2 || joystickx > joyxh*2)
    344 		return;		// assume something jumped in and messed up the joystick
    345 					// reading time (win 95)
    346 
    347 	if (in_speed.state & 1)
    348 		speed = cl_movespeedkey.value;
    349 	else
    350 		speed = 1;
    351 	aspeed = speed*host_frametime;
    352 
    353 	if (in_strafe.state & 1)
    354 	{
    355 		if (joystickx < joyxl)
    356 			cmd->sidemove -= speed*cl_sidespeed.value;
    357 		else if (joystickx > joyxh)
    358 			cmd->sidemove += speed*cl_sidespeed.value;
    359 	}
    360 	else
    361 	{
    362 		if (joystickx < joyxl)
    363 			cl.viewangles[YAW] += aspeed*cl_yawspeed.value;
    364 		else if (joystickx > joyxh)
    365 			cl.viewangles[YAW] -= aspeed*cl_yawspeed.value;
    366 		cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
    367 	}
    368 
    369 	if (in_mlook.state & 1)
    370 	{
    371 		if (m_pitch.value < 0)
    372 			speed *= -1;
    373 
    374 		if (joysticky < joyyl)
    375 			cl.viewangles[PITCH] += aspeed*cl_pitchspeed.value;
    376 		else if (joysticky > joyyh)
    377 			cl.viewangles[PITCH] -= aspeed*cl_pitchspeed.value;
    378 	}
    379 	else
    380 	{
    381 		if (joysticky < joyyl)
    382 			cmd->forwardmove += speed*cl_forwardspeed.value;
    383 		else if (joysticky > joyyh)
    384 			cmd->forwardmove -= speed*cl_backspeed.value;
    385 	}
    386 }
    387 
    388 /*
    389 ===========
    390 IN_Move
    391 ===========
    392 */
    393 void IN_Move (usercmd_t *cmd)
    394 {
    395 	IN_MouseMove (cmd);
    396 	IN_JoyMove (cmd);
    397 	IN_ExternalMove (cmd);
    398 }
    399 
    400 /*
    401 ============================================================================
    402 
    403 					JOYSTICK
    404 
    405 ============================================================================
    406 */
    407 
    408 
    409 
    410 qboolean IN_ReadJoystick (void)
    411 {
    412 	int		b;
    413 	int		count;
    414 
    415 	joystickx = 0;
    416 	joysticky = 0;
    417 
    418 	count = 0;
    419 
    420 	b = dos_inportb(0x201);
    421 	dos_outportb(0x201, b);
    422 
    423 // clear counters
    424 	while (++count < 10000)
    425 	{
    426 		b = dos_inportb(0x201);
    427 
    428 		joystickx += b&1;
    429 		joysticky += (b&2)>>1;
    430 		if ( !(b&3) )
    431 			return true;
    432 	}
    433 
    434 	Con_Printf ("IN_ReadJoystick: no response\n");
    435 	joy_avail = false;
    436 	return false;
    437 }
    438 
    439 /*
    440 =============
    441 WaitJoyButton
    442 =============
    443 */
    444 qboolean WaitJoyButton (void)
    445 {
    446 	int             oldbuttons, buttons;
    447 
    448 	oldbuttons = 0;
    449 	do
    450 	{
    451 		key_count = -1;
    452 		Sys_SendKeyEvents ();
    453 		key_count = 0;
    454 		if (key_lastpress == K_ESCAPE)
    455 		{
    456 			Con_Printf ("aborted.\n");
    457 			return false;
    458 		}
    459 		key_lastpress = 0;
    460 		SCR_UpdateScreen ();
    461 		buttons =  ((dos_inportb(0x201) >> 4)&1)^1;
    462 		if (buttons != oldbuttons)
    463 		{
    464 			oldbuttons = buttons;
    465 			continue;
    466 		}
    467 	} while ( !buttons);
    468 
    469 	do
    470 	{
    471 		key_count = -1;
    472 		Sys_SendKeyEvents ();
    473 		key_count = 0;
    474 		if (key_lastpress == K_ESCAPE)
    475 		{
    476 			Con_Printf ("aborted.\n");
    477 			return false;
    478 		}
    479 		key_lastpress = 0;
    480 		SCR_UpdateScreen ();
    481 		buttons =  ((dos_inportb(0x201) >> 4)&1)^1;
    482 		if (buttons != oldbuttons)
    483 		{
    484 			oldbuttons = buttons;
    485 			continue;
    486 		}
    487 	} while ( buttons);
    488 
    489 	return true;
    490 }
    491 
    492 
    493 
    494 /*
    495 ===============
    496 IN_StartupJoystick
    497 ===============
    498 */
    499 void IN_StartupJoystick (void)
    500 {
    501 	int     centerx, centery;
    502 
    503  	Con_Printf ("\n");
    504 
    505 	joy_avail = false;
    506 	if ( COM_CheckParm ("-nojoy") )
    507 		return;
    508 
    509 	if (!IN_ReadJoystick ())
    510 	{
    511 		joy_avail = false;
    512 		Con_Printf ("joystick not found\n");
    513 		return;
    514 	}
    515 
    516 	Con_Printf ("joystick found\n");
    517 
    518 	Con_Printf ("CENTER the joystick\nand press button 1 (ESC to skip):\n");
    519 	if (!WaitJoyButton ())
    520 		return;
    521 	IN_ReadJoystick ();
    522 	centerx = joystickx;
    523 	centery = joysticky;
    524 
    525 	Con_Printf ("Push the joystick to the UPPER LEFT\nand press button 1 (ESC to skip):\n");
    526 	if (!WaitJoyButton ())
    527 		return;
    528 	IN_ReadJoystick ();
    529 	joyxl = (centerx + joystickx)/2;
    530 	joyyl = (centerx + joysticky)/2;
    531 
    532 	Con_Printf ("Push the joystick to the LOWER RIGHT\nand press button 1 (ESC to skip):\n");
    533 	if (!WaitJoyButton ())
    534 		return;
    535 	IN_ReadJoystick ();
    536 	joyxh = (centerx + joystickx)/2;
    537 	joyyh = (centery + joysticky)/2;
    538 
    539 	joy_avail = true;
    540 	Con_Printf ("joystick configured.\n");
    541 
    542  	Con_Printf ("\n");
    543 }
    544 
    545 
    546 /*
    547 ============================================================================
    548 
    549 					EXTERNAL
    550 
    551 ============================================================================
    552 */
    553 
    554 
    555 /*
    556 ===============
    557 IN_StartupExternal
    558 ===============
    559 */
    560 void IN_StartupExternal (void)
    561 {
    562 	if (extern_control->numButtons > 32)
    563 		extern_control->numButtons = 32;
    564 
    565 	Con_Printf("%s Initialized\n", extern_control->deviceName);
    566 	Con_Printf("  %u axes  %u buttons\n", extern_control->numAxes, extern_control->numButtons);
    567 
    568 	extern_avail = true;
    569 	extern_buttons = extern_control->numButtons;
    570 }
    571 
    572 
    573 /*
    574 ===========
    575 IN_ExternalMove
    576 ===========
    577 */
    578 void IN_ExternalMove (usercmd_t *cmd)
    579 {
    580 	qboolean freelook;
    581 
    582 	if (! extern_avail)
    583 		return;
    584 
    585 	extern_control->viewangles[YAW] = cl.viewangles[YAW];
    586 	extern_control->viewangles[PITCH] = cl.viewangles[PITCH];
    587 	extern_control->viewangles[ROLL] = cl.viewangles[ROLL];
    588 	extern_control->forwardmove = cmd->forwardmove;
    589 	extern_control->sidemove = cmd->sidemove;
    590 	extern_control->upmove = cmd->upmove;
    591 
    592 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);
    593 
    594 	dos_int86(extern_control->interruptVector);
    595 
    596 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);
    597 
    598 	cl.viewangles[YAW] = extern_control->viewangles[YAW];
    599 	cl.viewangles[PITCH] = extern_control->viewangles[PITCH];
    600 	cl.viewangles[ROLL] = extern_control->viewangles[ROLL];
    601 	cmd->forwardmove = extern_control->forwardmove;
    602 	cmd->sidemove = extern_control->sidemove;
    603 	cmd->upmove = extern_control->upmove;
    604 
    605 	if (cl.viewangles[PITCH] > 80)
    606 		cl.viewangles[PITCH] = 80;
    607 	if (cl.viewangles[PITCH] < -70)
    608 		cl.viewangles[PITCH] = -70;
    609 
    610 	freelook = (extern_control->flags & AUX_FLAG_FREELOOK || aux_look.value || in_mlook.state & 1);
    611 
    612 	if (freelook)
    613 		V_StopPitchDrift ();
    614 }
    615 
    616