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