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 "d_local.h"
36
37#define stringify(m) { #m, m }
38
39unsigned short       d_8to16table[256];
40static byte		*vid_surfcache;
41static int		VID_highhunkmark;
42
43int num_modes;
44vga_modeinfo *modes;
45int current_mode;
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];
64static byte vid_current_palette[768];
65
66int num_mice = sizeof (mice) / sizeof(mice[0]);
67
68int	d_con_indirect = 0;
69
70int		svgalib_inited=0;
71int		UseMouse = 1;
72int		UseDisplay = 1;
73int		UseKeyboard = 1;
74
75int		mouserate = MOUSE_DEFAULTSAMPLERATE;
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 _windowed_mouse = {"_windowed_mouse", "1", true};
98cvar_t	m_filter = {"m_filter","0"};
99
100static byte     backingbuf[48*24];
101
102int		VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
103byte	*VGA_pagebase;
104
105void VGA_UpdatePlanarScreen (void *srcbuffer);
106
107void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
108{
109	int i, j, k, plane, reps, repshift, offset, vidpage, off;
110
111	if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return;
112
113	if (vid.aspect > 1.5)
114	{
115		reps = 2;
116		repshift = 1;
117	} else {
118		reps = 1;
119		repshift = 0;
120	}
121
122	vidpage = 0;
123	vga_setpage(0);
124
125	if (VGA_planar)
126	{
127		for (plane=0 ; plane<4 ; plane++)
128		{
129		// select the correct plane for reading and writing
130			outb(0x02, 0x3C4);
131			outb(1 << plane, 0x3C5);
132			outb(4, 0x3CE);
133			outb(plane, 0x3CF);
134
135			for (i=0 ; i<(height << repshift) ; i += reps)
136			{
137				for (k=0 ; k<reps ; k++)
138				{
139					for (j=0 ; j<(width >> 2) ; j++)
140					{
141						backingbuf[(i + k) * 24 + (j << 2) + plane] =
142								vid.direct[(y + i + k) * VGA_rowbytes +
143								(x >> 2) + j];
144						vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
145								pbitmap[(i >> repshift) * 24 +
146								(j << 2) + plane];
147					}
148				}
149			}
150		}
151	} else {
152		for (i=0 ; i<(height << repshift) ; i += reps)
153		{
154			for (j=0 ; j<reps ; j++)
155			{
156				offset = x + ((y << repshift) + i + j) * vid.rowbytes;
157				off = offset % 0x10000;
158				if ((offset / 0x10000) != vidpage) {
159					vidpage=offset / 0x10000;
160					vga_setpage(vidpage);
161				}
162				memcpy (&backingbuf[(i + j) * 24],
163						vid.direct + off, width);
164				memcpy (vid.direct + off,
165						&pbitmap[(i >> repshift)*width], width);
166			}
167		}
168	}
169}
170
171void D_EndDirectRect (int x, int y, int width, int height)
172{
173	int i, j, k, plane, reps, repshift, offset, vidpage, off;
174
175	if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return;
176
177	if (vid.aspect > 1.5)
178	{
179		reps = 2;
180		repshift = 1;
181	} else {
182		reps = 1;
183		repshift = 0;
184	}
185
186	vidpage = 0;
187	vga_setpage(0);
188
189	if (VGA_planar)
190	{
191		for (plane=0 ; plane<4 ; plane++)
192		{
193		// select the correct plane for writing
194			outb(2, 0x3C4);
195			outb(1 << plane, 0x3C5);
196			outb(4, 0x3CE);
197			outb(plane, 0x3CF);
198
199			for (i=0 ; i<(height << repshift) ; i += reps)
200			{
201				for (k=0 ; k<reps ; k++)
202				{
203					for (j=0 ; j<(width >> 2) ; j++)
204					{
205						vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
206								backingbuf[(i + k) * 24 + (j << 2) + plane];
207					}
208				}
209			}
210		}
211	} else {
212		for (i=0 ; i<(height << repshift) ; i += reps)
213		{
214			for (j=0 ; j<reps ; j++)
215			{
216				offset = x + ((y << repshift) + i + j) * vid.rowbytes;
217				off = offset % 0x10000;
218				if ((offset / 0x10000) != vidpage) {
219					vidpage=offset / 0x10000;
220					vga_setpage(vidpage);
221				}
222				memcpy (vid.direct + off,
223						&backingbuf[(i +j)*24],
224						width);
225			}
226		}
227	}
228}
229
230/*
231=================
232VID_Gamma_f
233
234Keybinding command
235=================
236*/
237void VID_Gamma_f (void)
238{
239	float	gamma, f, inf;
240	unsigned char	palette[768];
241	int		i;
242
243	if (Cmd_Argc () == 2)
244	{
245		gamma = Q_atof (Cmd_Argv(1));
246
247		for (i=0 ; i<768 ; i++)
248		{
249			f = pow ( (host_basepal[i]+1)/256.0 , gamma );
250			inf = f*255 + 0.5;
251			if (inf < 0)
252				inf = 0;
253			if (inf > 255)
254				inf = 255;
255			palette[i] = inf;
256		}
257
258		VID_SetPalette (palette);
259
260		vid.recalc_refdef = 1;				// force a surface cache flush
261	}
262}
263
264void VID_DescribeMode_f (void)
265{
266	int modenum;
267
268	modenum = Q_atoi (Cmd_Argv(1));
269	if ((modenum >= num_modes) || (modenum < 0 ) || !modes[modenum].width)
270		Con_Printf("Invalid video mode: %d!\n",modenum);
271	Con_Printf("%d: %d x %d - ",modenum,modes[modenum].width,modes[modenum].height);
272	if (modes[modenum].bytesperpixel == 0)
273		Con_Printf("ModeX\n");
274	else
275		Con_Printf("%d bpp\n", modes[modenum].bytesperpixel<<3);
276}
277
278void VID_DescribeModes_f (void)
279{
280	int i;
281
282	for (i=0;i<num_modes;i++)
283		if (modes[i].width) {
284			Con_Printf("%d: %d x %d - ", i, modes[i].width,modes[i].height);
285			if (modes[i].bytesperpixel == 0)
286				Con_Printf("ModeX\n");
287			else
288				Con_Printf("%d bpp\n", modes[i].bytesperpixel<<3);
289		}
290}
291
292/*
293================
294VID_NumModes
295================
296*/
297int VID_NumModes ()
298{
299	int i,i1=0;
300
301	for (i=0;i<num_modes;i++)
302		i1+=(modes[i].width?1:0);
303	return (i1);
304}
305
306void VID_NumModes_f (void)
307{
308	Con_Printf("%d modes\n",VID_NumModes());
309}
310
311void VID_Debug_f (void)
312{
313	Con_Printf("mode: %d\n",current_mode);
314	Con_Printf("height x width: %d x %d\n",vid.height,vid.width);
315	Con_Printf("bpp: %d\n",modes[current_mode].bytesperpixel*8);
316	Con_Printf("vid.aspect: %f\n",vid.aspect);
317}
318
319
320
321void VID_InitModes(void)
322{
323
324	int i;
325
326// get complete information on all modes
327
328	num_modes = vga_lastmodenumber()+1;
329	modes = Z_Malloc(num_modes * sizeof(vga_modeinfo));
330	for (i=0 ; i<num_modes ; i++)
331	{
332		if (vga_hasmode(i))
333			Q_memcpy(&modes[i], vga_getmodeinfo(i), sizeof (vga_modeinfo));
334		else
335			modes[i].width = 0; // means not available
336	}
337
338// filter for modes i don't support
339
340	for (i=0 ; i<num_modes ; i++)
341	{
342		if (modes[i].bytesperpixel != 1 && modes[i].colors != 256)
343			modes[i].width = 0;
344	}
345
346}
347
348int get_mode(char *name, int width, int height, int depth)
349{
350
351	int i;
352	int ok, match;
353
354	match = (!!width) + (!!height)*2 + (!!depth)*4;
355
356	if (name)
357	{
358		i = vga_getmodenumber(name);
359		if (!modes[i].width)
360		{
361			Sys_Printf("Mode [%s] not supported\n", name);
362			i = G320x200x256;
363		}
364	}
365	else
366	{
367		for (i=0 ; i<num_modes ; i++)
368			if (modes[i].width)
369			{
370				ok = (modes[i].width == width)
371					+ (modes[i].height == height)*2
372					+ (modes[i].bytesperpixel == depth/8)*4;
373				if ((ok & match) == ok)
374					break;
375			}
376		if (i==num_modes)
377		{
378			Sys_Printf("Mode %dx%d (%d bits) not supported\n",
379				width, height, depth);
380			i = G320x200x256;
381		}
382	}
383
384	return i;
385
386}
387
388int matchmouse(int mouse, char *name)
389{
390	int i;
391	for (i=0 ; i<num_mice ; i++)
392		if (!strcmp(mice[i].name, name))
393			return i;
394	return mouse;
395}
396
397#if 0
398
399void vtswitch(int newconsole)
400{
401
402	int fd;
403	struct vt_stat x;
404
405// switch consoles and wait until reactivated
406	fd = open("/dev/console", O_RDONLY);
407	ioctl(fd, VT_GETSTATE, &x);
408	ioctl(fd, VT_ACTIVATE, newconsole);
409	ioctl(fd, VT_WAITACTIVE, x.v_active);
410	close(fd);
411
412}
413
414#endif
415
416void keyhandler(int scancode, int state)
417{
418
419	int sc;
420
421	sc = scancode & 0x7f;
422//	Con_Printf("scancode=%x (%d%s)\n", scancode, sc, scancode&0x80?"+128":"");
423	Key_Event(scantokey[sc], state == KEY_EVENTPRESS);
424
425}
426
427void VID_Shutdown(void)
428{
429
430	if (!svgalib_inited) return;
431
432//	printf("shutdown graphics called\n");
433	if (UseKeyboard)
434		keyboard_close();
435	if (UseDisplay)
436		vga_setmode(TEXT);
437//	printf("shutdown graphics finished\n");
438
439	svgalib_inited = 0;
440
441}
442
443void VID_ShiftPalette(unsigned char *p)
444{
445	VID_SetPalette(p);
446}
447
448void VID_SetPalette(byte *palette)
449{
450
451	static int tmppal[256*3];
452	int *tp;
453	int i;
454
455	if (!svgalib_inited)
456		return;
457
458	memcpy(vid_current_palette, palette, sizeof(vid_current_palette));
459
460	if (vga_getcolors() == 256)
461	{
462
463		tp = tmppal;
464		for (i=256*3 ; i ; i--)
465			*(tp++) = *(palette++) >> 2;
466
467		if (UseDisplay && vga_oktowrite())
468			vga_setpalvec(0, 256, tmppal);
469
470	}
471}
472
473int VID_SetMode (int modenum, unsigned char *palette)
474{
475	int bsize, zsize, tsize;
476
477	if ((modenum >= num_modes) || (modenum < 0) || !modes[modenum].width)
478	{
479		Cvar_SetValue ("vid_mode", (float)current_mode);
480
481		Con_Printf("No such video mode: %d\n",modenum);
482
483		return 0;
484	}
485
486	Cvar_SetValue ("vid_mode", (float)modenum);
487
488	current_mode=modenum;
489
490	vid.width = modes[current_mode].width;
491	vid.height = modes[current_mode].height;
492
493	VGA_width = modes[current_mode].width;
494	VGA_height = modes[current_mode].height;
495	VGA_planar = modes[current_mode].bytesperpixel == 0;
496	VGA_rowbytes = modes[current_mode].linewidth;
497	vid.rowbytes = modes[current_mode].linewidth;
498	if (VGA_planar) {
499		VGA_bufferrowbytes = modes[current_mode].linewidth * 4;
500		vid.rowbytes = modes[current_mode].linewidth*4;
501	}
502
503	vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
504	vid.colormap = (pixel_t *) host_colormap;
505	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
506	vid.conrowbytes = vid.rowbytes;
507	vid.conwidth = vid.width;
508	vid.conheight = vid.height;
509	vid.numpages = 1;
510
511	vid.maxwarpwidth = WARP_WIDTH;
512	vid.maxwarpheight = WARP_HEIGHT;
513
514	// alloc zbuffer and surface cache
515	if (d_pzbuffer) {
516		D_FlushCaches();
517		Hunk_FreeToHighMark (VID_highhunkmark);
518		d_pzbuffer = NULL;
519		vid_surfcache = NULL;
520	}
521
522	bsize = vid.rowbytes * vid.height;
523	tsize = D_SurfaceCacheForRes (vid.width, vid.height);
524	zsize = vid.width * vid.height * sizeof(*d_pzbuffer);
525
526	VID_highhunkmark = Hunk_HighMark ();
527
528	d_pzbuffer = Hunk_HighAllocName (bsize+tsize+zsize, "video");
529
530	vid_surfcache = ((byte *)d_pzbuffer) + zsize;
531
532	vid.conbuffer = vid.buffer = (pixel_t *)(((byte *)d_pzbuffer) + zsize + tsize);
533
534	D_InitCaches (vid_surfcache, tsize);
535
536// get goin'
537
538	vga_setmode(current_mode);
539	VID_SetPalette(palette);
540
541	VGA_pagebase = vid.direct = framebuffer_ptr = (char *) vga_getgraphmem();
542//		if (vga_setlinearaddressing()>0)
543//			framebuffer_ptr = (char *) vga_getgraphmem();
544	if (!framebuffer_ptr)
545		Sys_Error("This mode isn't hapnin'\n");
546
547	vga_setpage(0);
548
549	svgalib_inited=1;
550
551	vid.recalc_refdef = 1;				// force a surface cache flush
552
553	return 0;
554}
555
556void VID_Init(unsigned char *palette)
557{
558
559	int i;
560	int w, h, d;
561
562	S_Init(); // sound gets initialized here
563
564	if (svgalib_inited)
565		return;
566
567//	Cmd_AddCommand ("gamma", VID_Gamma_f);
568
569	if (UseDisplay)
570	{
571		vga_init();
572
573		VID_InitModes();
574
575		Cvar_RegisterVariable (&vid_mode);
576		Cvar_RegisterVariable (&vid_redrawfull);
577		Cvar_RegisterVariable (&vid_waitforrefresh);
578
579		Cmd_AddCommand("vid_nummodes", VID_NumModes_f);
580		Cmd_AddCommand("vid_describemode", VID_DescribeMode_f);
581		Cmd_AddCommand("vid_describemodes", VID_DescribeModes_f);
582		Cmd_AddCommand("vid_debug", VID_Debug_f);
583
584	// interpret command-line params
585
586		w = h = d = 0;
587		if (getenv("GSVGAMODE"))
588			current_mode = get_mode(getenv("GSVGAMODE"), w, h, d);
589		else if (COM_CheckParm("-mode"))
590			current_mode = get_mode(com_argv[COM_CheckParm("-mode")+1], w, h, d);
591		else if (COM_CheckParm("-w") || COM_CheckParm("-h")
592			|| COM_CheckParm("-d"))
593		{
594			if (COM_CheckParm("-w"))
595				w = Q_atoi(com_argv[COM_CheckParm("-w")+1]);
596			if (COM_CheckParm("-h"))
597				h = Q_atoi(com_argv[COM_CheckParm("-h")+1]);
598			if (COM_CheckParm("-d"))
599				d = Q_atoi(com_argv[COM_CheckParm("-d")+1]);
600			current_mode = get_mode(0, w, h, d);
601		}
602		else
603			current_mode = G320x200x256;
604
605	// set vid parameters
606		VID_SetMode(current_mode, palette);
607
608		VID_SetPalette(palette);
609
610		// we do want to run in the background when switched away
611		vga_runinbackground(1);
612	}
613
614	if (COM_CheckParm("-nokbd")) UseKeyboard = 0;
615
616	if (UseKeyboard)
617	{
618		for (i=0 ; i<128 ; i++)
619			scantokey[i] = ' ';
620
621		scantokey[  1] = K_ESCAPE;
622		scantokey[  2] = '1';
623		scantokey[  3] = '2';
624		scantokey[  4] = '3';
625		scantokey[  5] = '4';
626		scantokey[  6] = '5';
627		scantokey[  7] = '6';
628		scantokey[  8] = '7';
629		scantokey[  9] = '8';
630		scantokey[ 10] = '9';
631		scantokey[ 11] = '0';
632		scantokey[ 12] = '-';
633		scantokey[ 13] = '=';
634		scantokey[ 14] = K_BACKSPACE;
635		scantokey[ 15] = K_TAB;
636		scantokey[ 16] = 'q';
637		scantokey[ 17] = 'w';
638		scantokey[ 18] = 'e';
639		scantokey[ 19] = 'r';
640		scantokey[ 20] = 't';
641		scantokey[ 21] = 'y';
642		scantokey[ 22] = 'u';
643		scantokey[ 23] = 'i';
644		scantokey[ 24] = 'o';
645		scantokey[ 25] = 'p';
646		scantokey[ 26] = '[';
647		scantokey[ 27] = ']';
648		scantokey[ 28] = K_ENTER;
649		scantokey[ 29] = K_CTRL; //left
650		scantokey[ 30] = 'a';
651		scantokey[ 31] = 's';
652		scantokey[ 32] = 'd';
653		scantokey[ 33] = 'f';
654		scantokey[ 34] = 'g';
655		scantokey[ 35] = 'h';
656		scantokey[ 36] = 'j';
657		scantokey[ 37] = 'k';
658		scantokey[ 38] = 'l';
659		scantokey[ 39] = ';';
660		scantokey[ 40] = '\'';
661		scantokey[ 41] = '`';
662		scantokey[ 42] = K_SHIFT; //left
663		scantokey[ 43] = '\\';
664		scantokey[ 44] = 'z';
665		scantokey[ 45] = 'x';
666		scantokey[ 46] = 'c';
667		scantokey[ 47] = 'v';
668		scantokey[ 48] = 'b';
669		scantokey[ 49] = 'n';
670		scantokey[ 50] = 'm';
671		scantokey[ 51] = ',';
672		scantokey[ 52] = '.';
673		scantokey[ 53] = '/';
674		scantokey[ 54] = K_SHIFT; //right
675		scantokey[ 55] = '*'; //keypad
676		scantokey[ 56] = K_ALT; //left
677		scantokey[ 57] = ' ';
678		// 58 caps lock
679		scantokey[ 59] = K_F1;
680		scantokey[ 60] = K_F2;
681		scantokey[ 61] = K_F3;
682		scantokey[ 62] = K_F4;
683		scantokey[ 63] = K_F5;
684		scantokey[ 64] = K_F6;
685		scantokey[ 65] = K_F7;
686		scantokey[ 66] = K_F8;
687		scantokey[ 67] = K_F9;
688		scantokey[ 68] = K_F10;
689		// 69 numlock
690		// 70 scrollock
691		scantokey[ 71] = K_HOME;
692		scantokey[ 72] = K_UPARROW;
693		scantokey[ 73] = K_PGUP;
694		scantokey[ 74] = '-';
695		scantokey[ 75] = K_LEFTARROW;
696		scantokey[ 76] = '5';
697		scantokey[ 77] = K_RIGHTARROW;
698		scantokey[ 79] = K_END;
699		scantokey[ 78] = '+';
700		scantokey[ 80] = K_DOWNARROW;
701		scantokey[ 81] = K_PGDN;
702		scantokey[ 82] = K_INS;
703		scantokey[ 83] = K_DEL;
704		// 84 to 86 not used
705		scantokey[ 87] = K_F11;
706		scantokey[ 88] = K_F12;
707		// 89 to 95 not used
708		scantokey[ 96] = K_ENTER; //keypad enter
709		scantokey[ 97] = K_CTRL; //right
710		scantokey[ 98] = '/';
711		scantokey[ 99] = K_F12; // print screen, bind to screenshot by default
712		scantokey[100] = K_ALT; // right
713
714		scantokey[101] = K_PAUSE; // break
715		scantokey[102] = K_HOME;
716		scantokey[103] = K_UPARROW;
717		scantokey[104] = K_PGUP;
718		scantokey[105] = K_LEFTARROW;
719		scantokey[106] = K_RIGHTARROW;
720		scantokey[107] = K_END;
721		scantokey[108] = K_DOWNARROW;
722		scantokey[109] = K_PGDN;
723		scantokey[110] = K_INS;
724		scantokey[111] = K_DEL;
725
726		scantokey[119] = K_PAUSE;
727
728		if (keyboard_init())
729			Sys_Error("keyboard_init() failed");
730		keyboard_seteventhandler(keyhandler);
731	}
732
733}
734
735void VID_Update(vrect_t *rects)
736{
737	if (!svgalib_inited)
738		return;
739
740	if (!vga_oktowrite())
741		return; // can't update screen if it's not active
742
743	if (vid_waitforrefresh.value)
744		vga_waitretrace();
745
746	if (VGA_planar)
747		VGA_UpdatePlanarScreen (vid.buffer);
748
749	else if (vid_redrawfull.value) {
750		int total = vid.rowbytes * vid.height;
751		int offset;
752
753		for (offset=0;offset<total;offset+=0x10000) {
754			vga_setpage(offset/0x10000);
755			memcpy(framebuffer_ptr,
756					vid.buffer + offset,
757					((total-offset>0x10000)?0x10000:(total-offset)));
758		}
759	} else {
760		int ycount;
761		int offset;
762		int vidpage=0;
763
764		vga_setpage(0);
765
766		while (rects)
767		{
768			ycount = rects->height;
769			offset = rects->y * vid.rowbytes + rects->x;
770			while (ycount--)
771			{
772				register int i = offset % 0x10000;
773
774				if ((offset / 0x10000) != vidpage) {
775					vidpage=offset / 0x10000;
776					vga_setpage(vidpage);
777				}
778				if (rects->width + i > 0x10000) {
779					memcpy(framebuffer_ptr + i,
780							vid.buffer + offset,
781							0x10000 - i);
782					vga_setpage(++vidpage);
783					memcpy(framebuffer_ptr,
784							vid.buffer + offset + 0x10000 - i,
785							rects->width - 0x10000 + i);
786				} else
787					memcpy(framebuffer_ptr + i,
788							vid.buffer + offset,
789							rects->width);
790				offset += vid.rowbytes;
791			}
792
793			rects = rects->pnext;
794		}
795	}
796
797	if (vid_mode.value != current_mode)
798		VID_SetMode ((int)vid_mode.value, vid_current_palette);
799}
800
801static int dither;
802
803void VID_DitherOn(void)
804{
805    if (dither == 0)
806    {
807//		R_ViewChanged (&vrect, sb_lines, vid.aspect);
808        dither = 1;
809    }
810}
811
812void VID_DitherOff(void)
813{
814    if (dither)
815    {
816//		R_ViewChanged (&vrect, sb_lines, vid.aspect);
817        dither = 0;
818    }
819}
820
821void Sys_SendKeyEvents(void)
822{
823	if (!svgalib_inited)
824		return;
825
826	if (UseKeyboard)
827		while (keyboard_update());
828}
829
830void Force_CenterView_f (void)
831{
832	cl.viewangles[PITCH] = 0;
833}
834
835
836void mousehandler(int buttonstate, int dx, int dy)
837{
838	mouse_buttonstate = buttonstate;
839	mx += dx;
840	my += dy;
841}
842
843void IN_Init(void)
844{
845
846	int mtype;
847	char *mousedev;
848	int mouserate;
849
850	Cvar_RegisterVariable (&m_filter);
851
852	if (UseMouse)
853	{
854		Cvar_RegisterVariable (&mouse_button_commands[0]);
855		Cvar_RegisterVariable (&mouse_button_commands[1]);
856		Cvar_RegisterVariable (&mouse_button_commands[2]);
857		Cmd_AddCommand ("force_centerview", Force_CenterView_f);
858
859		mouse_buttons = 3;
860
861		mtype = vga_getmousetype();
862
863		mousedev = "/dev/mouse";
864		if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV");
865		if (COM_CheckParm("-mdev"))
866			mousedev = com_argv[COM_CheckParm("-mdev")+1];
867
868		mouserate = 1200;
869		if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE"));
870		if (COM_CheckParm("-mrate"))
871			mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]);
872
873//		printf("Mouse: dev=%s,type=%s,speed=%d\n",
874//			mousedev, mice[mtype].name, mouserate);
875		if (mouse_init(mousedev, mtype, mouserate))
876		{
877			Con_Printf("No mouse found\n");
878			UseMouse = 0;
879		}
880		else
881			mouse_seteventhandler(mousehandler);
882
883	}
884
885}
886
887void IN_Shutdown(void)
888{
889	if (UseMouse)
890		mouse_close();
891}
892
893/*
894===========
895IN_Commands
896===========
897*/
898void IN_Commands (void)
899{
900	if (UseMouse /*&& cls.state != ca_dedicated*/)
901	{
902		// poll mouse values
903		while (mouse_update())
904			;
905
906		// perform button actions
907		if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
908			!(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
909			Key_Event (K_MOUSE1, true);
910		else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
911			(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
912			Key_Event (K_MOUSE1, false);
913
914		if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
915			!(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
916			Key_Event (K_MOUSE2, true);
917		else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
918			(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
919			Key_Event (K_MOUSE2, false);
920
921		if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
922			!(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
923			Key_Event (K_MOUSE3, true);
924		else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
925			(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
926			Key_Event (K_MOUSE3, false);
927
928		mouse_oldbuttonstate = mouse_buttonstate;
929	}
930}
931
932/*
933===========
934IN_Move
935===========
936*/
937void IN_MouseMove (usercmd_t *cmd)
938{
939	if (!UseMouse)
940		return;
941
942	// poll mouse values
943	while (mouse_update())
944		;
945
946	if (m_filter.value)
947	{
948		mouse_x = (mx + old_mouse_x) * 0.5;
949		mouse_y = (my + old_mouse_y) * 0.5;
950	}
951	else
952	{
953		mouse_x = mx;
954		mouse_y = my;
955	}
956	old_mouse_x = mx;
957	old_mouse_y = my;
958	mx = my = 0; // clear for next update
959
960	mouse_x *= sensitivity.value;
961	mouse_y *= sensitivity.value;
962
963// add mouse X/Y movement to cmd
964	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
965		cmd->sidemove += m_side.value * mouse_x;
966	else
967		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
968
969	if (in_mlook.state & 1)
970		V_StopPitchDrift ();
971
972	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
973	{
974		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
975		if (cl.viewangles[PITCH] > 80)
976			cl.viewangles[PITCH] = 80;
977		if (cl.viewangles[PITCH] < -70)
978			cl.viewangles[PITCH] = -70;
979	}
980	else
981	{
982		if ((in_strafe.state & 1) && noclip_anglehack)
983			cmd->upmove -= m_forward.value * mouse_y;
984		else
985			cmd->forwardmove -= m_forward.value * mouse_y;
986	}
987}
988
989void IN_Move (usercmd_t *cmd)
990{
991	IN_MouseMove(cmd);
992}
993
994
995/*
996================
997VID_ModeInfo
998================
999*/
1000char *VID_ModeInfo (int modenum)
1001{
1002	static char	*badmodestr = "Bad mode number";
1003	static char modestr[40];
1004
1005	if (modenum == 0)
1006	{
1007		sprintf (modestr, "%d x %d, %d bpp",
1008				 vid.width, vid.height, modes[current_mode].bytesperpixel*8);
1009		return (modestr);
1010	}
1011	else
1012	{
1013		return (badmodestr);
1014	}
1015}
1016
1017void VID_LockBuffer (void)
1018{
1019}
1020
1021void VID_UnlockBuffer (void)
1022{
1023}
1024
1025
1026