1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 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
40static fxMesaContext fc = NULL;
41#define stringify(m) { #m, m }
42
43unsigned short	d_8to16table[256];
44unsigned	d_8to24table[256];
45unsigned char d_15to8table[65536];
46
47int num_shades=32;
48
49struct
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
63static unsigned char scantokey[128];
64
65int num_mice = sizeof (mice) / sizeof(mice[0]);
66
67int	d_con_indirect = 0;
68
69int		svgalib_inited=0;
70int		UseMouse = 1;
71int		UseKeyboard = 1;
72
73int		mouserate = MOUSE_DEFAULTSAMPLERATE;
74
75cvar_t		vid_mode = {"vid_mode","5",false};
76cvar_t		vid_redrawfull = {"vid_redrawfull","0",false};
77cvar_t		vid_waitforrefresh = {"vid_waitforrefresh","0",true};
78
79char	*framebuffer_ptr;
80
81cvar_t  mouse_button_commands[3] =
82{
83    {"mouse1","+attack"},
84    {"mouse2","+strafe"},
85    {"mouse3","+forward"},
86};
87
88int     mouse_buttons;
89int     mouse_buttonstate;
90int     mouse_oldbuttonstate;
91float   mouse_x, mouse_y;
92float	old_mouse_x, old_mouse_y;
93int		mx, my;
94
95cvar_t _windowed_mouse = {"_windowed_mouse", "1", true};
96cvar_t	m_filter = {"m_filter","0"};
97
98int 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;
105int		texture_mode = GL_LINEAR;
106//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
107//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
108
109int		texture_extension_number = 1;
110
111float		gldepthmin, gldepthmax;
112
113cvar_t	gl_ztrick = {"gl_ztrick","1"};
114
115const char *gl_vendor;
116const char *gl_renderer;
117const char *gl_version;
118const char *gl_extensions;
119
120qboolean is8bit = false;
121qboolean isPermedia = false;
122qboolean gl_mtexable = false;
123
124/*-----------------------------------------------------------------------*/
125void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
126{
127}
128
129void D_EndDirectRect (int x, int y, int width, int height)
130{
131}
132
133/*
134=================
135VID_Gamma_f
136
137Keybinding command
138=================
139*/
140void 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
167int 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
178void 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
195void 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
206void VID_Shutdown(void)
207{
208	if (!fc)
209		return;
210
211	fxMesaDestroyContext(fc);
212
213	if (UseKeyboard)
214		keyboard_close();
215}
216
217void signal_handler(int sig)
218{
219	printf("Received signal %d, exiting...\n", sig);
220	VID_Shutdown();
221	exit(0);
222}
223
224void 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
237void VID_ShiftPalette(unsigned char *p)
238{
239	VID_SetPalette(p);
240}
241
242void	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===============
321GL_Init
322===============
323*/
324void 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=================
361GL_BeginRendering
362
363=================
364*/
365void 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
380void GL_EndRendering (void)
381{
382	glFlush();
383	fxMesaSwapBuffers();
384}
385
386void 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
513static resolutions[NUM_RESOLUTIONS][3]={
514  { 512, 384, GR_RESOLUTION_512x384 },
515  { 640, 400, GR_RESOLUTION_640x400 },
516  { 640, 480, GR_RESOLUTION_640x480 }
517};
518
519int 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
535qboolean VID_Is8bit(void)
536{
537	return is8bit;
538}
539
540#ifdef GL_EXT_SHARED
541void 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
566extern void gl3DfxSetPaletteEXT(GLuint *pal);
567
568void 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
593void 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
685void Sys_SendKeyEvents(void)
686{
687	if (UseKeyboard)
688		while (keyboard_update());
689}
690
691void Force_CenterView_f (void)
692{
693	cl.viewangles[PITCH] = 0;
694}
695
696
697void mousehandler(int buttonstate, int dx, int dy)
698{
699	mouse_buttonstate = buttonstate;
700	mx += dx;
701	my += dy;
702}
703
704void 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
745void IN_Shutdown(void)
746{
747	if (UseMouse)
748		mouse_close();
749}
750
751/*
752===========
753IN_Commands
754===========
755*/
756void 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===========
792IN_Move
793===========
794*/
795void 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
847void IN_Move (usercmd_t *cmd)
848{
849	IN_MouseMove(cmd);
850}
851
852
853void	VID_LockBuffer (void) {}
854void	VID_UnlockBuffer (void) {}
855
856