1 /*
2  * vid_dos.c -- DOS-specific video routines.
3  * from quake1 source with minor adaptations for uhexen2.
4  * $Id: vid_dos.c 5676 2016-07-20 12:56:03Z sezero $
5  *
6  * Copyright (C) 1996-1997  Id Software, Inc.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <dos.h>
29 #include <dpmi.h>
30 #include <go32.h>
31 
32 #include "quakedef.h"
33 #include "d_local.h"
34 #include "dosisms.h"
35 #include "vid_dos.h"
36 #include "cfgfile.h"
37 
38 modestate_t	modestate = MS_UNINIT;
39 static int	vid_modenum;
40 static vmode_t	*pcurrentmode = NULL;
41 static int	vid_testingmode, vid_realmode;
42 static double	vid_testendtime;
43 
44 static cvar_t	vid_mode = {"vid_mode", "0", CVAR_NONE};
45 cvar_t		vid_wait = {"vid_wait", "0", CVAR_NONE};
46 cvar_t		vid_nopageflip = {"vid_nopageflip", "0", CVAR_ARCHIVE};
47 cvar_t		_vid_wait_override = {"_vid_wait_override", "0", CVAR_ARCHIVE};
48 static cvar_t	_vid_default_mode = {"_vid_default_mode", "0", CVAR_ARCHIVE};
49 // compatibility with windows version:
50 static cvar_t	_vid_default_mode_win = {"_vid_default_mode_win", "1", CVAR_ARCHIVE};
51 static cvar_t	vid_config_x = {"vid_config_x", "800", CVAR_ARCHIVE};
52 static cvar_t	vid_config_y = {"vid_config_y", "600", CVAR_ARCHIVE};
53 static cvar_t	vid_stretch_by_2 = {"vid_stretch_by_2", "1", CVAR_ARCHIVE};
54 cvar_t		_enable_mouse = {"_enable_mouse", "0", CVAR_ARCHIVE};
55 static cvar_t	vid_fullscreen_mode = {"vid_fullscreen_mode", "3", CVAR_ARCHIVE};
56 static cvar_t	vid_windowed_mode = {"vid_windowed_mode", "0", CVAR_ARCHIVE};
57 
58 viddef_t	vid;		/* global video state	*/
59 int		numvidmodes;
60 vmode_t		*pvidmodes;
61 
62 static int	firstupdate = 1;
63 
64 static void VID_TestMode_f (void);
65 static void VID_NumModes_f (void);
66 static void VID_DescribeCurrentMode_f (void);
67 static void VID_DescribeMode_f (void);
68 static void VID_DescribeModes_f (void);
69 
70 static qboolean VID_SetMode (int modenum, const unsigned char *palette);
71 
72 static byte	vid_current_palette[768];	/* save for mode changes */
73 
74 static qboolean	nomodecheck = false;
75 
76 unsigned short	d_8to16table[256];	/* not used in 8 bpp mode */
77 unsigned int	d_8to24table[256];	/* not used in 8 bpp mode */
78 
79 byte		globalcolormap[VID_GRADES*256], lastglobalcolor = 0;
80 byte		*lastsourcecolormap = NULL;
81 
82 static void VID_MenuDraw (void);
83 static void VID_MenuKey (int key);
84 
85 
86 /*
87 ================
88 VID_Init
89 ================
90 */
VID_Init(const unsigned char * palette)91 void    VID_Init (const unsigned char *palette)
92 {
93 	const char	*read_vars[] = {
94 				"_vid_default_mode" };
95 #define num_readvars	( sizeof(read_vars)/sizeof(read_vars[0]) )
96 
97 	Cvar_RegisterVariable (&vid_mode);
98 	Cvar_RegisterVariable (&vid_wait);
99 	Cvar_RegisterVariable (&vid_nopageflip);
100 	Cvar_RegisterVariable (&_vid_wait_override);
101 	Cvar_RegisterVariable (&_vid_default_mode);
102 	Cvar_RegisterVariable (&_vid_default_mode_win);
103 	Cvar_RegisterVariable (&vid_config_x);
104 	Cvar_RegisterVariable (&vid_config_y);
105 	Cvar_RegisterVariable (&vid_stretch_by_2);
106 	Cvar_RegisterVariable (&_enable_mouse);
107 	Cvar_RegisterVariable (&vid_fullscreen_mode);
108 	Cvar_RegisterVariable (&vid_windowed_mode);
109 
110 	Cmd_AddCommand ("vid_testmode", VID_TestMode_f);
111 	Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
112 	Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
113 	Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
114 	Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
115 
116 // perform an early read of config.cfg
117 	CFG_ReadCvars (read_vars, num_readvars);
118 
119 // set up the mode list; note that later inits link in their modes ahead of
120 // earlier ones, so the standard VGA modes are always first in the list. This
121 // is important because mode 0 must always be VGA mode 0x13
122 	if (!safemode && !COM_CheckParm("-stdvid"))
123 		VID_InitExtra ();
124 	VGA_Init ();
125 
126 	vid_testingmode = 0;
127 	vid_modenum = vid_mode.integer;
128 
129 	if (_vid_default_mode.integer < 0 || _vid_default_mode.integer >= numvidmodes)
130 		Cvar_SetQuick (&_vid_default_mode, "0");
131 	Cvar_LockVar ("_vid_default_mode");
132 
133 	Cvar_SetROM ("sys_nostdout", "1");	// disable printing to terminal
134 	VID_SetMode (vid_modenum, palette);
135 
136 	vid_realmode = vid_modenum;
137 
138 	vid_menudrawfn = VID_MenuDraw;
139 	vid_menukeyfn = VID_MenuKey;
140 }
141 
142 
143 /*
144 =================
145 VID_GetModePtr
146 =================
147 */
VID_GetModePtr(int modenum)148 static vmode_t *VID_GetModePtr (int modenum)
149 {
150 	vmode_t	*pv;
151 
152 	pv = pvidmodes;
153 	if (!pv)
154 		Sys_Error ("VID_GetModePtr: empty vid mode list");
155 
156 	while (modenum--)
157 	{
158 		pv = pv->pnext;
159 		if (!pv)
160 			Sys_Error ("VID_GetModePtr: corrupt vid mode list");
161 	}
162 
163 	return pv;
164 }
165 
166 /*
167 ================
168 VID_NumModes
169 ================
170 */
VID_NumModes(void)171 static int VID_NumModes (void)
172 {
173 	return (numvidmodes);
174 }
175 
176 
177 /*
178 ================
179 VID_ModeInfo
180 ================
181 */
VID_ModeInfo(int modenum,const char ** ppheader)182 static const char *VID_ModeInfo (int modenum, const char **ppheader)
183 {
184 	static const char	badmodestr[] = "Bad mode number";
185 	vmode_t		*pv;
186 
187 	pv = VID_GetModePtr (modenum);
188 
189 	if (!pv)
190 	{
191 		if (ppheader)
192 			*ppheader = NULL;
193 		return badmodestr;
194 	}
195 	else
196 	{
197 		if (ppheader)
198 			*ppheader = pv->header;
199 		return pv->name;
200 	}
201 }
202 
203 
204 /*
205 ================
206 VID_SetMode
207 ================
208 */
VID_SetMode(int modenum,const unsigned char * palette)209 static qboolean VID_SetMode (int modenum, const unsigned char *palette)
210 {
211 	int		status;
212 	vmode_t	*pnewmode, *poldmode;
213 
214 	if ((modenum >= numvidmodes) || (modenum < 0))
215 	{
216 		Cvar_SetValueQuick (&vid_mode, (float)vid_modenum);
217 
218 		nomodecheck = true;
219 		Con_Printf ("No such video mode: %d\n", modenum);
220 		nomodecheck = false;
221 
222 		if (pcurrentmode == NULL)
223 		{
224 			modenum = 0;	// mode hasn't been set yet, so initialize to base
225 					//  mode since they gave us an invalid initial mode
226 		}
227 		else
228 		{
229 			return false;
230 		}
231 	}
232 
233 	pnewmode = VID_GetModePtr (modenum);
234 
235 	if (pnewmode == pcurrentmode)
236 		return true;	// already in the desired mode
237 
238 // initialize the new mode
239 	poldmode = pcurrentmode;
240 	pcurrentmode = pnewmode;
241 
242 	vid.width = pcurrentmode->width;
243 	vid.height = pcurrentmode->height;
244 	vid.aspect = pcurrentmode->aspect;
245 	vid.rowbytes = pcurrentmode->rowbytes;
246 
247 	status = (*pcurrentmode->setmode) (&vid, pcurrentmode);
248 
249 	if (status < 1)
250 	{
251 		if (status == 0)
252 		{
253 		// real, hard failure that requires resetting the mode
254 			if (!VID_SetMode (vid_modenum, palette))	// restore prior mode
255 				Sys_Error ("VID_SetMode: Unable to set any mode, probably "
256 						   "because there's not enough memory available");
257 			Con_Printf ("Failed to set mode %d\n", modenum);
258 			return false;
259 		}
260 		else if (status == -1)
261 		{
262 		// not enough memory; just put things back the way they were
263 			pcurrentmode = poldmode;
264 			vid.width = pcurrentmode->width;
265 			vid.height = pcurrentmode->height;
266 			vid.aspect = pcurrentmode->aspect;
267 			vid.rowbytes = pcurrentmode->rowbytes;
268 			return false;
269 		}
270 		else
271 		{
272 			Sys_Error ("VID_SetMode: invalid setmode return code %d", status);
273 		}
274 	}
275 
276 	(*pcurrentmode->setpalette) (&vid, pcurrentmode, palette);
277 
278 	vid_modenum = modenum;
279 	Cvar_SetValueQuick (&vid_mode, (float)vid_modenum);
280 
281 	nomodecheck = true;
282 	Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL));
283 	nomodecheck = false;
284 
285 	vid.recalc_refdef = 1;
286 
287 	return true;
288 }
289 
290 
291 /*
292 ================
293 VID_SetPalette
294 ================
295 */
VID_SetPalette(const unsigned char * palette)296 void VID_SetPalette (const unsigned char *palette)
297 {
298 	if (palette != vid_current_palette)
299 		memcpy(vid_current_palette, palette, 768);
300 	(*pcurrentmode->setpalette)(&vid, pcurrentmode, vid_current_palette);
301 }
302 
303 
304 /*
305 ================
306 VID_ShiftPalette
307 ================
308 */
VID_ShiftPalette(const unsigned char * palette)309 void VID_ShiftPalette (const unsigned char *palette)
310 {
311 	VID_SetPalette (palette);
312 }
313 
314 
315 /*
316 ================
317 VID_Shutdown
318 ================
319 */
VID_Shutdown(void)320 void VID_Shutdown (void)
321 {
322 	regs.h.ah = 0;
323 	regs.h.al = 0x3;
324 	dos_int86(0x10);
325 
326 	vid_testingmode = 0;
327 }
328 
329 
330 /*
331 ================
332 VID_Update
333 ================
334 */
VID_Update(vrect_t * rects)335 void VID_Update (vrect_t *rects)
336 {
337 	if (firstupdate && host_initialized)
338 	{
339 		firstupdate = 0;
340 		Cvar_SetValueQuick (&vid_mode, _vid_default_mode.integer);
341 	}
342 
343 	(*pcurrentmode->swapbuffers)(&vid, pcurrentmode, rects);
344 
345 	if (nomodecheck)
346 		return;
347 
348 	if (vid_testingmode)
349 	{
350 		if (realtime >= vid_testendtime)
351 		{
352 			VID_SetMode (vid_realmode, vid_current_palette);
353 			vid_testingmode = 0;
354 		}
355 	}
356 	else
357 	{
358 		if (vid_mode.integer != vid_realmode)
359 		{
360 			VID_SetMode (vid_mode.integer, vid_current_palette);
361 			Cvar_SetValueQuick (&vid_mode, (float)vid_modenum);
362 							// so if mode set fails, we don't keep on
363 							//  trying to set it
364 			vid_realmode = vid_modenum;
365 		}
366 	}
367 }
368 
369 
370 /*
371 =================
372 VID_NumModes_f
373 =================
374 */
VID_NumModes_f(void)375 static void VID_NumModes_f (void)
376 {
377 	int		nummodes;
378 
379 	nummodes = VID_NumModes ();
380 	if (nummodes == 1)
381 		Con_Printf ("%d video mode is available\n", VID_NumModes ());
382 	else
383 		Con_Printf ("%d video modes are available\n", VID_NumModes ());
384 }
385 
386 
387 /*
388 =================
389 VID_DescribeCurrentMode_f
390 =================
391 */
VID_DescribeCurrentMode_f(void)392 static void VID_DescribeCurrentMode_f (void)
393 {
394 	Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL));
395 }
396 
397 
398 /*
399 =================
400 VID_DescribeMode_f
401 =================
402 */
VID_DescribeMode_f(void)403 void VID_DescribeMode_f (void)
404 {
405 	int		modenum;
406 
407 	modenum = atoi (Cmd_Argv(1));
408 
409 	Con_Printf ("%s\n", VID_ModeInfo (modenum, NULL));
410 }
411 
412 
413 /*
414 =================
415 VID_DescribeModes_f
416 =================
417 */
VID_DescribeModes_f(void)418 void VID_DescribeModes_f (void)
419 {
420 	int		i, nummodes;
421 	const char	*pinfo;
422 	const char	*pheader;
423 	vmode_t		*pv;
424 	qboolean	na;
425 
426 	na = false;
427 
428 	nummodes = VID_NumModes ();
429 	for (i = 0; i < nummodes; i++)
430 	{
431 		pv = VID_GetModePtr (i);
432 		pinfo = VID_ModeInfo (i, &pheader);
433 		if (pheader)
434 			Con_Printf ("\n%s\n", pheader);
435 
436 		if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes,
437 				(pv->numpages == 1) || vid_nopageflip.integer))
438 		{
439 			Con_Printf ("%2d: %s\n", i, pinfo);
440 		}
441 		else
442 		{
443 			Con_Printf ("**: %s\n", pinfo);
444 			na = true;
445 		}
446 	}
447 
448 	if (na)
449 	{
450 		Con_Printf ("\n[**: not enough system RAM for mode]\n");
451 	}
452 }
453 
454 
455 /*
456 =================
457 VID_GetModeDescription
458 =================
459 */
VID_GetModeDescription(int modenum)460 static const char *VID_GetModeDescription (int modenum)
461 {
462 	const char	*pinfo;
463 	const char	*pheader;
464 	vmode_t		*pv;
465 
466 	pv = VID_GetModePtr (modenum);
467 	pinfo = VID_ModeInfo (modenum, &pheader);
468 
469 	if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes,
470 			(pv->numpages == 1) || vid_nopageflip.integer))
471 	{
472 		return pinfo;
473 	}
474 	else
475 	{
476 		return NULL;
477 	}
478 }
479 
480 
481 /*
482 =================
483 VID_TestMode_f
484 =================
485 */
VID_TestMode_f(void)486 static void VID_TestMode_f (void)
487 {
488 	int		modenum;
489 	double	testduration;
490 
491 	if (!vid_testingmode)
492 	{
493 		modenum = atoi (Cmd_Argv(1));
494 
495 		if (VID_SetMode (modenum, vid_current_palette))
496 		{
497 			vid_testingmode = 1;
498 			testduration = atof (Cmd_Argv(2));
499 			if (testduration == 0)
500 				testduration = 5.0;
501 			vid_testendtime = realtime + testduration;
502 		}
503 	}
504 }
505 
506 
507 /*
508 ================
509 D_BeginDirectRect
510 ================
511 */
D_BeginDirectRect(int x,int y,byte * pbitmap,int width,int height)512 void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
513 {
514 
515 	if (!vid.direct || !pcurrentmode)
516 		return;
517 
518 	if ((width > 24) || (height > 24) || (width < 1) || (height < 1))
519 		return;
520 
521 	if (width & 0x03)
522 		return;
523 
524 	(*pcurrentmode->begindirectrect) (&vid, pcurrentmode, x, y, pbitmap, width, height);
525 }
526 
527 /*
528 ================
529 D_EndDirectRect
530 ================
531 */
D_EndDirectRect(int x,int y,int width,int height)532 void D_EndDirectRect (int x, int y, int width, int height)
533 {
534 
535 	if (!vid.direct || !pcurrentmode)
536 		return;
537 
538 	if ((width > 24) || (height > 24) || (width < 1) || (height < 1))
539 		return;
540 
541 	if ((width & 0x03) || (height & 0x03))
542 		return;
543 
544 	(*pcurrentmode->enddirectrect) (&vid, pcurrentmode, x, y, width, height);
545 }
546 
D_ShowLoadingSize(void)547 void D_ShowLoadingSize (void)
548 {
549 #if defined(DRAW_PROGRESSBARS)
550 /* to be implemented. */
551 #endif	/* !DRAW_PROGRESSBARS */
552 }
553 
VID_LockBuffer(void)554 void VID_LockBuffer (void)
555 {
556 /* nothing to do */
557 }
558 
VID_UnlockBuffer(void)559 void VID_UnlockBuffer (void)
560 {
561 /* nothing to do */
562 }
563 
564 
VID_HandlePause(qboolean paused)565 void VID_HandlePause (qboolean paused)
566 {
567 	if (paused)	IN_DeactivateMouse ();
568 	else		IN_ActivateMouse ();
569 }
570 
571 
572 //===========================================================================
573 
574 static int	vid_line, vid_wmodes, vid_column_size;
575 
576 typedef struct
577 {
578 	int		modenum;
579 	const char	*desc;
580 	int		iscur;
581 } modedesc_t;
582 
583 #define	MAX_COLUMN_SIZE	11
584 #define MAX_MODEDESCS	(MAX_COLUMN_SIZE * 3)
585 
586 static modedesc_t	modedescs[MAX_MODEDESCS];
587 
588 /*
589 ================
590 VID_MenuDraw
591 ================
592 */
VID_MenuDraw(void)593 static void VID_MenuDraw (void)
594 {
595 	const char	*ptr;
596 	int		nummodes, i, j, column, row, dup;
597 	char		temp[100];
598 
599 	vid_wmodes = 0;
600 	nummodes = VID_NumModes ();
601 
602 	ScrollTitle("gfx/menu/title7.lmp");
603 
604 	for (i = 0; i < nummodes; i++)
605 	{
606 		if (vid_wmodes < MAX_MODEDESCS)
607 		{
608 			if (i != 1)
609 			{
610 				ptr = VID_GetModeDescription (i);
611 
612 				if (ptr)
613 				{
614 					dup = 0;
615 
616 					for (j = 0; j < vid_wmodes; j++)
617 					{
618 						if (!strcmp (modedescs[j].desc, ptr))
619 						{
620 							if (modedescs[j].modenum != 0)
621 							{
622 								modedescs[j].modenum = i;
623 								dup = 1;
624 
625 								if (i == vid_modenum)
626 									modedescs[j].iscur = 1;
627 							}
628 							else
629 							{
630 								dup = 1;
631 							}
632 
633 							break;
634 						}
635 					}
636 
637 					if (!dup)
638 					{
639 						modedescs[vid_wmodes].modenum = i;
640 						modedescs[vid_wmodes].desc = ptr;
641 						modedescs[vid_wmodes].iscur = 0;
642 
643 						if (i == vid_modenum)
644 							modedescs[vid_wmodes].iscur = 1;
645 
646 						vid_wmodes++;
647 					}
648 				}
649 			}
650 		}
651 	}
652 
653 	vid_column_size = (vid_wmodes + 2) / 3;
654 
655 	column = 16;
656 	row = 36;
657 
658 	for (i = 0; i < vid_wmodes; i++)
659 	{
660 		if (modedescs[i].iscur)
661 			M_PrintWhite (column, row, modedescs[i].desc);
662 		else
663 			M_Print (column, row, modedescs[i].desc);
664 
665 		row += 8;
666 
667 		if ((i % vid_column_size) == (vid_column_size - 1))
668 		{
669 			column += 13*8;
670 			row = 36;
671 		}
672 	}
673 
674 // line cursor
675 	if (vid_testingmode)
676 	{
677 		q_snprintf (temp, sizeof(temp), "TESTING %s",
678 				modedescs[vid_line].desc);
679 		M_Print (13*8, 36 + MAX_COLUMN_SIZE * 8 + 8*4, temp);
680 		M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6,
681 				"Please wait 5 seconds...");
682 	}
683 	else
684 	{
685 		M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8,
686 				"Press Enter to set mode");
687 		M_Print (6*8, 36 + MAX_COLUMN_SIZE * 8 + 8*3,
688 				"T to test mode for 5 seconds");
689 		ptr = VID_GetModeDescription (vid_modenum);
690 		q_snprintf (temp, sizeof(temp), "D to make %s the default", ptr);
691 		M_Print (6*8, 36 + MAX_COLUMN_SIZE * 8 + 8*5, temp);
692 		ptr = VID_GetModeDescription (_vid_default_mode.integer);
693 
694 		if (ptr)
695 		{
696 			q_snprintf (temp, sizeof(temp), "Current default is %s", ptr);
697 			M_Print (7*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6, temp);
698 		}
699 
700 		M_Print (15*8, 36 + MAX_COLUMN_SIZE * 8 + 8*8,
701 				"Esc to exit");
702 
703 		row = 36 + (vid_line % vid_column_size) * 8;
704 		column = 8 + (vid_line / vid_column_size) * 13*8;
705 
706 		M_DrawCharacter (column, row, 12+((int)(realtime*4)&1));
707 	}
708 }
709 
710 
711 /*
712 ================
713 VID_MenuKey
714 ================
715 */
VID_MenuKey(int key)716 static void VID_MenuKey (int key)
717 {
718 	if (vid_testingmode)
719 		return;
720 
721 	switch (key)
722 	{
723 	case K_ESCAPE:
724 		S_LocalSound ("raven/menu1.wav");
725 		M_Menu_Options_f ();
726 		break;
727 
728 	case K_UPARROW:
729 		S_LocalSound ("raven/menu1.wav");
730 		vid_line--;
731 
732 		if (vid_line < 0)
733 			vid_line = vid_wmodes - 1;
734 		break;
735 
736 	case K_DOWNARROW:
737 		S_LocalSound ("raven/menu1.wav");
738 		vid_line++;
739 
740 		if (vid_line >= vid_wmodes)
741 			vid_line = 0;
742 		break;
743 
744 	case K_LEFTARROW:
745 		S_LocalSound ("raven/menu1.wav");
746 		vid_line -= vid_column_size;
747 
748 		if (vid_line < 0)
749 		{
750 			vid_line += ((vid_wmodes + (vid_column_size - 1)) / vid_column_size) * vid_column_size;
751 			while (vid_line >= vid_wmodes)
752 				vid_line -= vid_column_size;
753 		}
754 		break;
755 
756 	case K_RIGHTARROW:
757 		S_LocalSound ("raven/menu1.wav");
758 		vid_line += vid_column_size;
759 
760 		if (vid_line >= vid_wmodes)
761 		{
762 			vid_line -= ((vid_wmodes + (vid_column_size - 1)) / vid_column_size) * vid_column_size;
763 			while (vid_line < 0)
764 				vid_line += vid_column_size;
765 		}
766 		break;
767 
768 	case K_ENTER:
769 		S_LocalSound ("raven/menu1.wav");
770 		VID_SetMode (modedescs[vid_line].modenum, vid_current_palette);
771 		break;
772 
773 	case 'T':
774 	case 't':
775 		S_LocalSound ("raven/menu1.wav");
776 		if (VID_SetMode (modedescs[vid_line].modenum, vid_current_palette))
777 		{
778 			vid_testingmode = 1;
779 			vid_testendtime = realtime + 5.0;
780 		}
781 		break;
782 
783 	case 'D':
784 	case 'd':
785 		S_LocalSound ("raven/menu1.wav");
786 		firstupdate = 0;
787 		Cvar_SetValueQuick (&_vid_default_mode, vid_modenum);
788 		break;
789 
790 	default:
791 		break;
792 	}
793 }
794 
795