Home | History | Annotate | Download | only in client
      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 #include <termios.h>
     21 #include <sys/ioctl.h>
     22 #include <sys/stat.h>
     23 #include <sys/vt.h>
     24 #include <stdarg.h>
     25 #include <stdio.h>
     26 #include <signal.h>
     27 
     28 #include <asm/io.h>
     29 
     30 #include "vga.h"
     31 #include "vgakeyboard.h"
     32 #include "vgamouse.h"
     33 
     34 #include "quakedef.h"
     35 #include "GL/fxmesa.h"
     36 
     37 #define WARP_WIDTH              320
     38 #define WARP_HEIGHT             200
     39 
     40 static fxMesaContext fc = NULL;
     41 #define stringify(m) { #m, m }
     42 
     43 unsigned short	d_8to16table[256];
     44 unsigned	d_8to24table[256];
     45 unsigned char d_15to8table[65536];
     46 
     47 int num_shades=32;
     48 
     49 struct
     50 {
     51 	char *name;
     52 	int num;
     53 } mice[] =
     54 {
     55 	stringify(MOUSE_MICROSOFT),
     56 	stringify(MOUSE_MOUSESYSTEMS),
     57 	stringify(MOUSE_MMSERIES),
     58 	stringify(MOUSE_LOGITECH),
     59 	stringify(MOUSE_BUSMOUSE),
     60 	stringify(MOUSE_PS2),
     61 };
     62 
     63 static unsigned char scantokey[128];
     64 
     65 int num_mice = sizeof (mice) / sizeof(mice[0]);
     66 
     67 int	d_con_indirect = 0;
     68 
     69 int		svgalib_inited=0;
     70 int		UseMouse = 1;
     71 int		UseKeyboard = 1;
     72 
     73 int		mouserate = MOUSE_DEFAULTSAMPLERATE;
     74 
     75 cvar_t	_windowed_mouse = {"_windowed_mouse","0", true};
     76 
     77 cvar_t		vid_mode = {"vid_mode","5",false};
     78 cvar_t		vid_redrawfull = {"vid_redrawfull","0",false};
     79 cvar_t		vid_waitforrefresh = {"vid_waitforrefresh","0",true};
     80 
     81 char	*framebuffer_ptr;
     82 
     83 cvar_t  mouse_button_commands[3] =
     84 {
     85     {"mouse1","+attack"},
     86     {"mouse2","+strafe"},
     87     {"mouse3","+forward"},
     88 };
     89 
     90 int     mouse_buttons;
     91 int     mouse_buttonstate;
     92 int     mouse_oldbuttonstate;
     93 float   mouse_x, mouse_y;
     94 float	old_mouse_x, old_mouse_y;
     95 int		mx, my;
     96 
     97 cvar_t	m_filter = {"m_filter","1"};
     98 
     99 int scr_width, scr_height;
    100 
    101 /*-----------------------------------------------------------------------*/
    102 
    103 //int		texture_mode = GL_NEAREST;
    104 //int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
    105 //int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
    106 int		texture_mode = GL_LINEAR;
    107 //int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
    108 //int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
    109 
    110 int		texture_extension_number = 1;
    111 
    112 float		gldepthmin, gldepthmax;
    113 
    114 cvar_t	gl_ztrick = {"gl_ztrick","1"};
    115 
    116 const char *gl_vendor;
    117 const char *gl_renderer;
    118 const char *gl_version;
    119 const char *gl_extensions;
    120 
    121 qboolean is8bit = false;
    122 qboolean isPermedia = false;
    123 qboolean gl_mtexable = false;
    124 
    125 /*-----------------------------------------------------------------------*/
    126 void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
    127 {
    128 }
    129 
    130 void D_EndDirectRect (int x, int y, int width, int height)
    131 {
    132 }
    133 
    134 int matchmouse(int mouse, char *name)
    135 {
    136 	int i;
    137 	for (i=0 ; i<num_mice ; i++)
    138 		if (!strcmp(mice[i].name, name))
    139 			return i;
    140 	return mouse;
    141 }
    142 
    143 #if 0
    144 
    145 void vtswitch(int newconsole)
    146 {
    147 
    148 	int fd;
    149 	struct vt_stat x;
    150 
    151 // switch consoles and wait until reactivated
    152 	fd = open("/dev/console", O_RDONLY);
    153 	ioctl(fd, VT_GETSTATE, &x);
    154 	ioctl(fd, VT_ACTIVATE, newconsole);
    155 	ioctl(fd, VT_WAITACTIVE, x.v_active);
    156 	close(fd);
    157 
    158 }
    159 
    160 #endif
    161 
    162 void keyhandler(int scancode, int state)
    163 {
    164 
    165 	int sc;
    166 
    167 	sc = scancode & 0x7f;
    168 
    169 	Key_Event(scantokey[sc], state == KEY_EVENTPRESS);
    170 
    171 }
    172 
    173 void VID_Shutdown(void)
    174 {
    175 	if (!fc)
    176 		return;
    177 
    178 	fxMesaDestroyContext(fc);
    179 
    180 	if (UseKeyboard)
    181 		keyboard_close();
    182 }
    183 
    184 void signal_handler(int sig)
    185 {
    186 	printf("Received signal %d, exiting...\n", sig);
    187 	Sys_Quit();
    188 	exit(0);
    189 }
    190 
    191 void InitSig(void)
    192 {
    193 	signal(SIGHUP, signal_handler);
    194 	signal(SIGINT, signal_handler);
    195 	signal(SIGQUIT, signal_handler);
    196 	signal(SIGILL, signal_handler);
    197 	signal(SIGTRAP, signal_handler);
    198 	signal(SIGIOT, signal_handler);
    199 	signal(SIGBUS, signal_handler);
    200 	signal(SIGFPE, signal_handler);
    201 	signal(SIGSEGV, signal_handler);
    202 	signal(SIGTERM, signal_handler);
    203 }
    204 
    205 void VID_ShiftPalette(unsigned char *p)
    206 {
    207 //	VID_SetPalette(p);
    208 }
    209 
    210 void	VID_SetPalette (unsigned char *palette)
    211 {
    212 	byte	*pal;
    213 	unsigned r,g,b;
    214 	unsigned v;
    215 	int     r1,g1,b1;
    216 	int		k;
    217 	unsigned short i;
    218 	unsigned	*table;
    219 	FILE *f;
    220 	char s[255];
    221 	float dist, bestdist;
    222 	static qboolean palflag = false;
    223 
    224 //
    225 // 8 8 8 encoding
    226 //
    227 	Con_Printf("Converting 8to24\n");
    228 
    229 	pal = palette;
    230 	table = d_8to24table;
    231 	for (i=0 ; i<256 ; i++)
    232 	{
    233 		r = pal[0];
    234 		g = pal[1];
    235 		b = pal[2];
    236 		pal += 3;
    237 
    238 //		v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
    239 //		v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
    240 		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
    241 		*table++ = v;
    242 	}
    243 	d_8to24table[255] &= 0xffffff;	// 255 is transparent
    244 
    245 	// JACK: 3D distance calcs - k is last closest, l is the distance.
    246 	// FIXME: Precalculate this and cache to disk.
    247 	if (palflag)
    248 		return;
    249 	palflag = true;
    250 
    251 	COM_FOpenFile("glquake/15to8.pal", &f);
    252 	if (f) {
    253 		fread(d_15to8table, 1<<15, 1, f);
    254 		fclose(f);
    255 	} else {
    256 		for (i=0; i < (1<<15); i++) {
    257 			/* Maps
    258  			000000000000000
    259  			000000000011111 = Red  = 0x1F
    260  			000001111100000 = Blue = 0x03E0
    261  			111110000000000 = Grn  = 0x7C00
    262  			*/
    263  			r = ((i & 0x1F) << 3)+4;
    264  			g = ((i & 0x03E0) >> 2)+4;
    265  			b = ((i & 0x7C00) >> 7)+4;
    266 			pal = (unsigned char *)d_8to24table;
    267 			for (v=0,k=0,bestdist=10000.0; v<256; v++,pal+=4) {
    268  				r1 = (int)r - (int)pal[0];
    269  				g1 = (int)g - (int)pal[1];
    270  				b1 = (int)b - (int)pal[2];
    271 				dist = sqrt(((r1*r1)+(g1*g1)+(b1*b1)));
    272 				if (dist < bestdist) {
    273 					k=v;
    274 					bestdist = dist;
    275 				}
    276 			}
    277 			d_15to8table[i]=k;
    278 		}
    279 		sprintf(s, "%s/glquake", com_gamedir);
    280  		Sys_mkdir (s);
    281 		sprintf(s, "%s/glquake/15to8.pal", com_gamedir);
    282 		if ((f = fopen(s, "wb")) != NULL) {
    283 			fwrite(d_15to8table, 1<<15, 1, f);
    284 			fclose(f);
    285 		}
    286 	}
    287 }
    288 
    289 /*
    290 ===============
    291 GL_Init
    292 ===============
    293 */
    294 void GL_Init (void)
    295 {
    296 	gl_vendor = glGetString (GL_VENDOR);
    297 	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
    298 	gl_renderer = glGetString (GL_RENDERER);
    299 	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
    300 
    301 	gl_version = glGetString (GL_VERSION);
    302 	Con_Printf ("GL_VERSION: %s\n", gl_version);
    303 	gl_extensions = glGetString (GL_EXTENSIONS);
    304 	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
    305 
    306 //	Con_Printf ("%s %s\n", gl_renderer, gl_version);
    307 
    308 	glClearColor (1,0,0,0);
    309 	glCullFace(GL_FRONT);
    310 	glEnable(GL_TEXTURE_2D);
    311 
    312 	glEnable(GL_ALPHA_TEST);
    313 	glAlphaFunc(GL_GREATER, 0.666);
    314 
    315 	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
    316 	glShadeModel (GL_FLAT);
    317 
    318 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    319 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    320 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    321 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    322 
    323 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    324 
    325 //	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    326 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    327 }
    328 
    329 /*
    330 =================
    331 GL_BeginRendering
    332 
    333 =================
    334 */
    335 void GL_BeginRendering (int *x, int *y, int *width, int *height)
    336 {
    337 	extern cvar_t gl_clear;
    338 
    339 	*x = *y = 0;
    340 	*width = scr_width;
    341 	*height = scr_height;
    342 
    343 //    if (!wglMakeCurrent( maindc, baseRC ))
    344 //		Sys_Error ("wglMakeCurrent failed");
    345 
    346 //	glViewport (*x, *y, *width, *height);
    347 }
    348 
    349 
    350 void GL_EndRendering (void)
    351 {
    352 	glFlush();
    353 	fxMesaSwapBuffers();
    354 }
    355 
    356 void Init_KBD(void)
    357 {
    358 	int i;
    359 
    360 	if (COM_CheckParm("-nokbd")) UseKeyboard = 0;
    361 
    362 	if (UseKeyboard)
    363 	{
    364 		for (i=0 ; i<128 ; i++)
    365 			scantokey[i] = ' ';
    366 
    367 		scantokey[42] = K_SHIFT;
    368 		scantokey[54] = K_SHIFT;
    369 		scantokey[72] = K_UPARROW;
    370 		scantokey[103] = K_UPARROW;
    371 		scantokey[80] = K_DOWNARROW;
    372 		scantokey[108] = K_DOWNARROW;
    373 		scantokey[75] = K_LEFTARROW;
    374 		scantokey[105] = K_LEFTARROW;
    375 		scantokey[77] = K_RIGHTARROW;
    376 		scantokey[106] = K_RIGHTARROW;
    377 		scantokey[29] = K_CTRL;
    378 		scantokey[97] = K_CTRL;
    379 		scantokey[56] = K_ALT;
    380 		scantokey[100] = K_ALT;
    381 //		scantokey[58] = JK_CAPS;
    382 //		scantokey[69] = JK_NUM_LOCK;
    383 		scantokey[71] = K_HOME;
    384 		scantokey[73] = K_PGUP;
    385 		scantokey[79] = K_END;
    386 		scantokey[81] = K_PGDN;
    387 		scantokey[82] = K_INS;
    388 		scantokey[83] = K_DEL;
    389 		scantokey[1 ] = K_ESCAPE;
    390 		scantokey[28] = K_ENTER;
    391 		scantokey[15] = K_TAB;
    392 		scantokey[14] = K_BACKSPACE;
    393 		scantokey[119] = K_PAUSE;
    394 		scantokey[57] = ' ';
    395 
    396 		scantokey[102] = K_HOME;
    397 		scantokey[104] = K_PGUP;
    398 		scantokey[107] = K_END;
    399 		scantokey[109] = K_PGDN;
    400 		scantokey[110] = K_INS;
    401 		scantokey[111] = K_DEL;
    402 
    403 		scantokey[2] = '1';
    404 		scantokey[3] = '2';
    405 		scantokey[4] = '3';
    406 		scantokey[5] = '4';
    407 		scantokey[6] = '5';
    408 		scantokey[7] = '6';
    409 		scantokey[8] = '7';
    410 		scantokey[9] = '8';
    411 		scantokey[10] = '9';
    412 		scantokey[11] = '0';
    413 		scantokey[12] = '-';
    414 		scantokey[13] = '=';
    415 		scantokey[41] = '`';
    416 		scantokey[26] = '[';
    417 		scantokey[27] = ']';
    418 		scantokey[39] = ';';
    419 		scantokey[40] = '\'';
    420 		scantokey[51] = ',';
    421 		scantokey[52] = '.';
    422 		scantokey[53] = '/';
    423 		scantokey[43] = '\\';
    424 
    425 		scantokey[59] = K_F1;
    426 		scantokey[60] = K_F2;
    427 		scantokey[61] = K_F3;
    428 		scantokey[62] = K_F4;
    429 		scantokey[63] = K_F5;
    430 		scantokey[64] = K_F6;
    431 		scantokey[65] = K_F7;
    432 		scantokey[66] = K_F8;
    433 		scantokey[67] = K_F9;
    434 		scantokey[68] = K_F10;
    435 		scantokey[87] = K_F11;
    436 		scantokey[88] = K_F12;
    437 		scantokey[30] = 'a';
    438 		scantokey[48] = 'b';
    439 		scantokey[46] = 'c';
    440 		scantokey[32] = 'd';
    441 		scantokey[18] = 'e';
    442 		scantokey[33] = 'f';
    443 		scantokey[34] = 'g';
    444 		scantokey[35] = 'h';
    445 		scantokey[23] = 'i';
    446 		scantokey[36] = 'j';
    447 		scantokey[37] = 'k';
    448 		scantokey[38] = 'l';
    449 		scantokey[50] = 'm';
    450 		scantokey[49] = 'n';
    451 		scantokey[24] = 'o';
    452 		scantokey[25] = 'p';
    453 		scantokey[16] = 'q';
    454 		scantokey[19] = 'r';
    455 		scantokey[31] = 's';
    456 		scantokey[20] = 't';
    457 		scantokey[22] = 'u';
    458 		scantokey[47] = 'v';
    459 		scantokey[17] = 'w';
    460 		scantokey[45] = 'x';
    461 		scantokey[21] = 'y';
    462 		scantokey[44] = 'z';
    463 
    464 		scantokey[78] = '+';
    465 		scantokey[74] = '-';
    466 
    467 		if (keyboard_init())
    468 			Sys_Error("keyboard_init() failed");
    469 		keyboard_seteventhandler(keyhandler);
    470 	}
    471 }
    472 
    473 #define NUM_RESOLUTIONS 3
    474 
    475 static resolutions[NUM_RESOLUTIONS][3]={
    476   { 512, 384, GR_RESOLUTION_512x384 },
    477   { 640, 400, GR_RESOLUTION_640x400 },
    478   { 640, 480, GR_RESOLUTION_640x480 }
    479 };
    480 
    481 int findres(int *width, int *height)
    482 {
    483 	int i;
    484 
    485 	for(i=0;i<NUM_RESOLUTIONS;i++)
    486 		if((*width<=resolutions[i][0]) && (*height<=resolutions[i][1])) {
    487 			*width = resolutions[i][0];
    488 			*height = resolutions[i][1];
    489 			return resolutions[i][2];
    490 		}
    491 
    492 	*width = 640;
    493 	*height = 480;
    494 	return GR_RESOLUTION_640x480;
    495 }
    496 
    497 qboolean VID_Is8bit(void)
    498 {
    499 	return is8bit;
    500 }
    501 
    502 #ifdef GL_EXT_SHARED
    503 void VID_Init8bitPalette()
    504 {
    505 	// Check for 8bit Extensions and initialize them.
    506 	int i;
    507 	char thePalette[256*3];
    508 	char *oldPalette, *newPalette;
    509 
    510 	if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") == NULL)
    511 		return;
    512 
    513 	Con_SafePrintf("8-bit GL extensions enabled.\n");
    514 	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
    515 	oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
    516 	newPalette = thePalette;
    517 	for (i=0;i<256;i++) {
    518 		*newPalette++ = *oldPalette++;
    519 		*newPalette++ = *oldPalette++;
    520 		*newPalette++ = *oldPalette++;
    521 		oldPalette++;
    522 	}
    523 	glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
    524 	is8bit = true;
    525 }
    526 
    527 #else
    528 extern void gl3DfxSetPaletteEXT(GLuint *pal);
    529 
    530 void VID_Init8bitPalette(void)
    531 {
    532 	// Check for 8bit Extensions and initialize them.
    533 	int i;
    534 	GLubyte table[256][4];
    535 	char *oldpal;
    536 
    537 	if (strstr(gl_extensions, "3DFX_set_global_palette") == NULL)
    538 		return;
    539 
    540 	Con_SafePrintf("8-bit GL extensions enabled.\n");
    541 	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
    542 	oldpal = (char *) d_8to24table; //d_8to24table3dfx;
    543 	for (i=0;i<256;i++) {
    544 		table[i][2] = *oldpal++;
    545 		table[i][1] = *oldpal++;
    546 		table[i][0] = *oldpal++;
    547 		table[i][3] = 255;
    548 		oldpal++;
    549 	}
    550 	gl3DfxSetPaletteEXT((GLuint *)table);
    551 	is8bit = true;
    552 }
    553 #endif
    554 
    555 void VID_Init(unsigned char *palette)
    556 {
    557 	int i;
    558 	GLint attribs[32];
    559 	char	gldir[MAX_OSPATH];
    560 	int width = 640, height = 480;
    561 
    562 	S_Init();
    563 
    564 	Init_KBD();
    565 
    566 	Cvar_RegisterVariable (&vid_mode);
    567 	Cvar_RegisterVariable (&vid_redrawfull);
    568 	Cvar_RegisterVariable (&vid_waitforrefresh);
    569 	Cvar_RegisterVariable (&gl_ztrick);
    570 
    571         vid.maxwarpwidth = WARP_WIDTH;
    572         vid.maxwarpheight = WARP_HEIGHT;
    573         vid.colormap = host_colormap;
    574         vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
    575 
    576 // interpret command-line params
    577 
    578 // set vid parameters
    579 	attribs[0] = FXMESA_DOUBLEBUFFER;
    580 	attribs[1] = FXMESA_ALPHA_SIZE;
    581 	attribs[2] = 1;
    582 	attribs[3] = FXMESA_DEPTH_SIZE;
    583 	attribs[4] = 1;
    584 	attribs[5] = FXMESA_NONE;
    585 
    586 	if ((i = COM_CheckParm("-width")) != 0)
    587 		width = atoi(com_argv[i+1]);
    588 	if ((i = COM_CheckParm("-height")) != 0)
    589 		height = atoi(com_argv[i+1]);
    590 
    591 	if ((i = COM_CheckParm("-conwidth")) != 0)
    592 		vid.conwidth = Q_atoi(com_argv[i+1]);
    593 	else
    594 		vid.conwidth = 640;
    595 
    596 	vid.conwidth &= 0xfff8; // make it a multiple of eight
    597 
    598 	if (vid.conwidth < 320)
    599 		vid.conwidth = 320;
    600 
    601 	// pick a conheight that matches with correct aspect
    602 	vid.conheight = vid.conwidth*3 / 4;
    603 
    604 	if ((i = COM_CheckParm("-conheight")) != 0)
    605 		vid.conheight = Q_atoi(com_argv[i+1]);
    606 	if (vid.conheight < 200)
    607 		vid.conheight = 200;
    608 
    609 	fc = fxMesaCreateContext(0, findres(&width, &height), GR_REFRESH_75Hz,
    610 		attribs);
    611 	if (!fc)
    612 		Sys_Error("Unable to create 3DFX context.\n");
    613 
    614 	scr_width = width;
    615 	scr_height = height;
    616 
    617 	fxMesaMakeCurrent(fc);
    618 
    619 	if (vid.conheight > height)
    620 		vid.conheight = height;
    621 	if (vid.conwidth > width)
    622 		vid.conwidth = width;
    623 	vid.width = vid.conwidth;
    624 	vid.height = vid.conheight;
    625 
    626 	vid.aspect = ((float)vid.height / (float)vid.width) *
    627 				(320.0 / 240.0);
    628 	vid.numpages = 2;
    629 
    630 	InitSig(); // trap evil signals
    631 
    632 	GL_Init();
    633 
    634 	sprintf (gldir, "%s/glquake", com_gamedir);
    635 	Sys_mkdir (gldir);
    636 
    637 	VID_SetPalette(palette);
    638 
    639 	// Check for 3DFX Extensions and initialize them.
    640 	VID_Init8bitPalette();
    641 
    642 	Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
    643 
    644 	vid.recalc_refdef = 1;				// force a surface cache flush
    645 }
    646 
    647 void Sys_SendKeyEvents(void)
    648 {
    649 	if (UseKeyboard)
    650 		while (keyboard_update());
    651 }
    652 
    653 void Force_CenterView_f (void)
    654 {
    655 	cl.viewangles[PITCH] = 0;
    656 }
    657 
    658 
    659 void mousehandler(int buttonstate, int dx, int dy)
    660 {
    661 	mouse_buttonstate = buttonstate;
    662 	mx += dx;
    663 	my += dy;
    664 }
    665 
    666 void IN_Init(void)
    667 {
    668 
    669 	int mtype;
    670 	char *mousedev;
    671 	int mouserate;
    672 
    673 	if (UseMouse)
    674 	{
    675 
    676 		Cvar_RegisterVariable (&mouse_button_commands[0]);
    677 		Cvar_RegisterVariable (&mouse_button_commands[1]);
    678 		Cvar_RegisterVariable (&mouse_button_commands[2]);
    679 		Cmd_AddCommand ("force_centerview", Force_CenterView_f);
    680 
    681 		mouse_buttons = 3;
    682 
    683 		mtype = vga_getmousetype();
    684 
    685 		mousedev = "/dev/mouse";
    686 		if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV");
    687 		if (COM_CheckParm("-mdev"))
    688 			mousedev = com_argv[COM_CheckParm("-mdev")+1];
    689 
    690 		mouserate = 1200;
    691 		if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE"));
    692 		if (COM_CheckParm("-mrate"))
    693 			mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]);
    694 
    695 		if (mouse_init(mousedev, mtype, mouserate))
    696 		{
    697 			Con_Printf("No mouse found\n");
    698 			UseMouse = 0;
    699 		}
    700 		else
    701 			mouse_seteventhandler(mousehandler);
    702 
    703 	}
    704 
    705 }
    706 
    707 void IN_Shutdown(void)
    708 {
    709 	if (UseMouse)
    710 		mouse_close();
    711 }
    712 
    713 /*
    714 ===========
    715 IN_Commands
    716 ===========
    717 */
    718 void IN_Commands (void)
    719 {
    720 	if (UseMouse)
    721 	{
    722 		// poll mouse values
    723 		while (mouse_update())
    724 			;
    725 
    726 		// perform button actions
    727 		if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
    728 			!(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
    729 			Key_Event (K_MOUSE1, true);
    730 		else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
    731 			(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
    732 			Key_Event (K_MOUSE1, false);
    733 
    734 		if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
    735 			!(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
    736 			Key_Event (K_MOUSE2, true);
    737 		else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
    738 			(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
    739 			Key_Event (K_MOUSE2, false);
    740 
    741 		if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
    742 			!(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
    743 			Key_Event (K_MOUSE3, true);
    744 		else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
    745 			(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
    746 			Key_Event (K_MOUSE3, false);
    747 
    748 		mouse_oldbuttonstate = mouse_buttonstate;
    749 	}
    750 }
    751 
    752 /*
    753 ===========
    754 IN_Move
    755 ===========
    756 */
    757 void IN_MouseMove (usercmd_t *cmd)
    758 {
    759 	if (!UseMouse)
    760 		return;
    761 
    762 	// poll mouse values
    763 	while (mouse_update())
    764 		;
    765 
    766 	if (m_filter.value)
    767 	{
    768 		mouse_x = (mx + old_mouse_x) * 0.5;
    769 		mouse_y = (my + old_mouse_y) * 0.5;
    770 	}
    771 	else
    772 	{
    773 		mouse_x = mx;
    774 		mouse_y = my;
    775 	}
    776 	old_mouse_x = mx;
    777 	old_mouse_y = my;
    778 	mx = my = 0; // clear for next update
    779 
    780 	mouse_x *= sensitivity.value;
    781 	mouse_y *= sensitivity.value;
    782 
    783 // add mouse X/Y movement to cmd
    784 	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
    785 		cmd->sidemove += m_side.value * mouse_x;
    786 	else
    787 		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
    788 
    789 	if (in_mlook.state & 1)
    790 		V_StopPitchDrift ();
    791 
    792 	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
    793 	{
    794 		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
    795 		if (cl.viewangles[PITCH] > 80)
    796 			cl.viewangles[PITCH] = 80;
    797 		if (cl.viewangles[PITCH] < -70)
    798 			cl.viewangles[PITCH] = -70;
    799 	}
    800 	else
    801 	{
    802 		if ((in_strafe.state & 1) && noclip_anglehack)
    803 			cmd->upmove -= m_forward.value * mouse_y;
    804 		else
    805 			cmd->forwardmove -= m_forward.value * mouse_y;
    806 	}
    807 }
    808 
    809 void IN_Move (usercmd_t *cmd)
    810 {
    811 	IN_MouseMove(cmd);
    812 }
    813 
    814 void VID_UnlockBuffer() {}
    815 void VID_LockBuffer() {}
    816 
    817