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	_windowed_mouse = {"_windowed_mouse","0", true};
76
77cvar_t		vid_mode = {"vid_mode","5",false};
78cvar_t		vid_redrawfull = {"vid_redrawfull","0",false};
79cvar_t		vid_waitforrefresh = {"vid_waitforrefresh","0",true};
80
81char	*framebuffer_ptr;
82
83cvar_t  mouse_button_commands[3] =
84{
85    {"mouse1","+attack"},
86    {"mouse2","+strafe"},
87    {"mouse3","+forward"},
88};
89
90int     mouse_buttons;
91int     mouse_buttonstate;
92int     mouse_oldbuttonstate;
93float   mouse_x, mouse_y;
94float	old_mouse_x, old_mouse_y;
95int		mx, my;
96
97cvar_t	m_filter = {"m_filter","1"};
98
99int 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;
106int		texture_mode = GL_LINEAR;
107//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
108//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
109
110int		texture_extension_number = 1;
111
112float		gldepthmin, gldepthmax;
113
114cvar_t	gl_ztrick = {"gl_ztrick","1"};
115
116const char *gl_vendor;
117const char *gl_renderer;
118const char *gl_version;
119const char *gl_extensions;
120
121qboolean is8bit = false;
122qboolean isPermedia = false;
123qboolean gl_mtexable = false;
124
125/*-----------------------------------------------------------------------*/
126void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
127{
128}
129
130void D_EndDirectRect (int x, int y, int width, int height)
131{
132}
133
134int 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
145void 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
162void 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
173void VID_Shutdown(void)
174{
175	if (!fc)
176		return;
177
178	fxMesaDestroyContext(fc);
179
180	if (UseKeyboard)
181		keyboard_close();
182}
183
184void signal_handler(int sig)
185{
186	printf("Received signal %d, exiting...\n", sig);
187	Sys_Quit();
188	exit(0);
189}
190
191void 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
205void VID_ShiftPalette(unsigned char *p)
206{
207//	VID_SetPalette(p);
208}
209
210void	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===============
291GL_Init
292===============
293*/
294void 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=================
331GL_BeginRendering
332
333=================
334*/
335void 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
350void GL_EndRendering (void)
351{
352	glFlush();
353	fxMesaSwapBuffers();
354}
355
356void 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
475static resolutions[NUM_RESOLUTIONS][3]={
476  { 512, 384, GR_RESOLUTION_512x384 },
477  { 640, 400, GR_RESOLUTION_640x400 },
478  { 640, 480, GR_RESOLUTION_640x480 }
479};
480
481int 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
497qboolean VID_Is8bit(void)
498{
499	return is8bit;
500}
501
502#ifdef GL_EXT_SHARED
503void 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
528extern void gl3DfxSetPaletteEXT(GLuint *pal);
529
530void 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
555void 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
647void Sys_SendKeyEvents(void)
648{
649	if (UseKeyboard)
650		while (keyboard_update());
651}
652
653void Force_CenterView_f (void)
654{
655	cl.viewangles[PITCH] = 0;
656}
657
658
659void mousehandler(int buttonstate, int dx, int dy)
660{
661	mouse_buttonstate = buttonstate;
662	mx += dx;
663	my += dy;
664}
665
666void 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
707void IN_Shutdown(void)
708{
709	if (UseMouse)
710		mouse_close();
711}
712
713/*
714===========
715IN_Commands
716===========
717*/
718void 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===========
754IN_Move
755===========
756*/
757void 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
809void IN_Move (usercmd_t *cmd)
810{
811	IN_MouseMove(cmd);
812}
813
814void VID_UnlockBuffer() {}
815void VID_LockBuffer() {}
816
817