Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

vid_dll.c (16730B)


      1 /*
      2 Copyright (C) 1997-2001 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 // Main windowed and fullscreen graphics interface module. This module
     21 // is used for both the software and OpenGL rendering versions of the
     22 // Quake refresh engine.
     23 #include <assert.h>
     24 #include <float.h>
     25 
     26 #include "..\client\client.h"
     27 #include "winquake.h"
     28 //#include "zmouse.h"
     29 
     30 // Structure containing functions exported from refresh DLL
     31 refexport_t	re;
     32 
     33 cvar_t *win_noalttab;
     34 
     35 #ifndef WM_MOUSEWHEEL
     36 #define WM_MOUSEWHEEL (WM_MOUSELAST+1)  // message that will be supported by the OS 
     37 #endif
     38 
     39 static UINT MSH_MOUSEWHEEL;
     40 
     41 // Console variables that we need to access from this module
     42 cvar_t		*vid_gamma;
     43 cvar_t		*vid_ref;			// Name of Refresh DLL loaded
     44 cvar_t		*vid_xpos;			// X coordinate of window position
     45 cvar_t		*vid_ypos;			// Y coordinate of window position
     46 cvar_t		*vid_fullscreen;
     47 
     48 // Global variables used internally by this module
     49 viddef_t	viddef;				// global video state; used by other modules
     50 HINSTANCE	reflib_library;		// Handle to refresh DLL 
     51 qboolean	reflib_active = 0;
     52 
     53 HWND        cl_hwnd;            // Main window handle for life of program
     54 
     55 #define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
     56 
     57 LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
     58 
     59 static qboolean s_alttab_disabled;
     60 
     61 extern	unsigned	sys_msg_time;
     62 
     63 /*
     64 ** WIN32 helper functions
     65 */
     66 extern qboolean s_win95;
     67 
     68 static void WIN_DisableAltTab( void )
     69 {
     70 	if ( s_alttab_disabled )
     71 		return;
     72 
     73 	if ( s_win95 )
     74 	{
     75 		BOOL old;
     76 
     77 		SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
     78 	}
     79 	else
     80 	{
     81 		RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
     82 		RegisterHotKey( 0, 1, MOD_ALT, VK_RETURN );
     83 	}
     84 	s_alttab_disabled = true;
     85 }
     86 
     87 static void WIN_EnableAltTab( void )
     88 {
     89 	if ( s_alttab_disabled )
     90 	{
     91 		if ( s_win95 )
     92 		{
     93 			BOOL old;
     94 
     95 			SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
     96 		}
     97 		else
     98 		{
     99 			UnregisterHotKey( 0, 0 );
    100 			UnregisterHotKey( 0, 1 );
    101 		}
    102 
    103 		s_alttab_disabled = false;
    104 	}
    105 }
    106 
    107 /*
    108 ==========================================================================
    109 
    110 DLL GLUE
    111 
    112 ==========================================================================
    113 */
    114 
    115 #define	MAXPRINTMSG	4096
    116 void VID_Printf (int print_level, char *fmt, ...)
    117 {
    118 	va_list		argptr;
    119 	char		msg[MAXPRINTMSG];
    120 	static qboolean	inupdate;
    121 	
    122 	va_start (argptr,fmt);
    123 	vsprintf (msg,fmt,argptr);
    124 	va_end (argptr);
    125 
    126 	if (print_level == PRINT_ALL)
    127 	{
    128 		Com_Printf ("%s", msg);
    129 	}
    130 	else if ( print_level == PRINT_DEVELOPER )
    131 	{
    132 		Com_DPrintf ("%s", msg);
    133 	}
    134 	else if ( print_level == PRINT_ALERT )
    135 	{
    136 		MessageBox( 0, msg, "PRINT_ALERT", MB_ICONWARNING );
    137 		OutputDebugString( msg );
    138 	}
    139 }
    140 
    141 void VID_Error (int err_level, char *fmt, ...)
    142 {
    143 	va_list		argptr;
    144 	char		msg[MAXPRINTMSG];
    145 	static qboolean	inupdate;
    146 	
    147 	va_start (argptr,fmt);
    148 	vsprintf (msg,fmt,argptr);
    149 	va_end (argptr);
    150 
    151 	Com_Error (err_level,"%s", msg);
    152 }
    153 
    154 //==========================================================================
    155 
    156 byte        scantokey[128] = 
    157 					{ 
    158 //  0           1       2       3       4       5       6       7 
    159 //  8           9       A       B       C       D       E       F 
    160 	0  ,    27,     '1',    '2',    '3',    '4',    '5',    '6', 
    161 	'7',    '8',    '9',    '0',    '-',    '=',    K_BACKSPACE, 9, // 0 
    162 	'q',    'w',    'e',    'r',    't',    'y',    'u',    'i', 
    163 	'o',    'p',    '[',    ']',    13 ,    K_CTRL,'a',  's',      // 1 
    164 	'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';', 
    165 	'\'' ,    '`',    K_SHIFT,'\\',  'z',    'x',    'c',    'v',      // 2 
    166 	'b',    'n',    'm',    ',',    '.',    '/',    K_SHIFT,'*', 
    167 	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3 
    168 	K_F6, K_F7, K_F8, K_F9, K_F10,  K_PAUSE,    0  , K_HOME, 
    169 	K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW, K_KP_PLUS,K_END, //4 
    170 	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11, 
    171 	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5
    172 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
    173 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6 
    174 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
    175 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7 
    176 }; 
    177 
    178 /*
    179 =======
    180 MapKey
    181 
    182 Map from windows to quake keynums
    183 =======
    184 */
    185 int MapKey (int key)
    186 {
    187 	int result;
    188 	int modified = ( key >> 16 ) & 255;
    189 	qboolean is_extended = false;
    190 
    191 	if ( modified > 127)
    192 		return 0;
    193 
    194 	if ( key & ( 1 << 24 ) )
    195 		is_extended = true;
    196 
    197 	result = scantokey[modified];
    198 
    199 	if ( !is_extended )
    200 	{
    201 		switch ( result )
    202 		{
    203 		case K_HOME:
    204 			return K_KP_HOME;
    205 		case K_UPARROW:
    206 			return K_KP_UPARROW;
    207 		case K_PGUP:
    208 			return K_KP_PGUP;
    209 		case K_LEFTARROW:
    210 			return K_KP_LEFTARROW;
    211 		case K_RIGHTARROW:
    212 			return K_KP_RIGHTARROW;
    213 		case K_END:
    214 			return K_KP_END;
    215 		case K_DOWNARROW:
    216 			return K_KP_DOWNARROW;
    217 		case K_PGDN:
    218 			return K_KP_PGDN;
    219 		case K_INS:
    220 			return K_KP_INS;
    221 		case K_DEL:
    222 			return K_KP_DEL;
    223 		default:
    224 			return result;
    225 		}
    226 	}
    227 	else
    228 	{
    229 		switch ( result )
    230 		{
    231 		case 0x0D:
    232 			return K_KP_ENTER;
    233 		case 0x2F:
    234 			return K_KP_SLASH;
    235 		case 0xAF:
    236 			return K_KP_PLUS;
    237 		}
    238 		return result;
    239 	}
    240 }
    241 
    242 void AppActivate(BOOL fActive, BOOL minimize)
    243 {
    244 	Minimized = minimize;
    245 
    246 	Key_ClearStates();
    247 
    248 	// we don't want to act like we're active if we're minimized
    249 	if (fActive && !Minimized)
    250 		ActiveApp = true;
    251 	else
    252 		ActiveApp = false;
    253 
    254 	// minimize/restore mouse-capture on demand
    255 	if (!ActiveApp)
    256 	{
    257 		IN_Activate (false);
    258 		CDAudio_Activate (false);
    259 		S_Activate (false);
    260 
    261 		if ( win_noalttab->value )
    262 		{
    263 			WIN_EnableAltTab();
    264 		}
    265 	}
    266 	else
    267 	{
    268 		IN_Activate (true);
    269 		CDAudio_Activate (true);
    270 		S_Activate (true);
    271 		if ( win_noalttab->value )
    272 		{
    273 			WIN_DisableAltTab();
    274 		}
    275 	}
    276 }
    277 
    278 /*
    279 ====================
    280 MainWndProc
    281 
    282 main window procedure
    283 ====================
    284 */
    285 LONG WINAPI MainWndProc (
    286     HWND    hWnd,
    287     UINT    uMsg,
    288     WPARAM  wParam,
    289     LPARAM  lParam)
    290 {
    291 	LONG			lRet = 0;
    292 
    293 	if ( uMsg == MSH_MOUSEWHEEL )
    294 	{
    295 		if ( ( ( int ) wParam ) > 0 )
    296 		{
    297 			Key_Event( K_MWHEELUP, true, sys_msg_time );
    298 			Key_Event( K_MWHEELUP, false, sys_msg_time );
    299 		}
    300 		else
    301 		{
    302 			Key_Event( K_MWHEELDOWN, true, sys_msg_time );
    303 			Key_Event( K_MWHEELDOWN, false, sys_msg_time );
    304 		}
    305         return DefWindowProc (hWnd, uMsg, wParam, lParam);
    306 	}
    307 
    308 	switch (uMsg)
    309 	{
    310 	case WM_MOUSEWHEEL:
    311 		/*
    312 		** this chunk of code theoretically only works under NT4 and Win98
    313 		** since this message doesn't exist under Win95
    314 		*/
    315 		if ( ( short ) HIWORD( wParam ) > 0 )
    316 		{
    317 			Key_Event( K_MWHEELUP, true, sys_msg_time );
    318 			Key_Event( K_MWHEELUP, false, sys_msg_time );
    319 		}
    320 		else
    321 		{
    322 			Key_Event( K_MWHEELDOWN, true, sys_msg_time );
    323 			Key_Event( K_MWHEELDOWN, false, sys_msg_time );
    324 		}
    325 		break;
    326 
    327 	case WM_HOTKEY:
    328 		return 0;
    329 
    330 	case WM_CREATE:
    331 		cl_hwnd = hWnd;
    332 
    333 		MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG"); 
    334         return DefWindowProc (hWnd, uMsg, wParam, lParam);
    335 
    336 	case WM_PAINT:
    337 		SCR_DirtyScreen ();	// force entire screen to update next frame
    338         return DefWindowProc (hWnd, uMsg, wParam, lParam);
    339 
    340 	case WM_DESTROY:
    341 		// let sound and input know about this?
    342 		cl_hwnd = NULL;
    343         return DefWindowProc (hWnd, uMsg, wParam, lParam);
    344 
    345 	case WM_ACTIVATE:
    346 		{
    347 			int	fActive, fMinimized;
    348 
    349 			// KJB: Watch this for problems in fullscreen modes with Alt-tabbing.
    350 			fActive = LOWORD(wParam);
    351 			fMinimized = (BOOL) HIWORD(wParam);
    352 
    353 			AppActivate( fActive != WA_INACTIVE, fMinimized);
    354 
    355 			if ( reflib_active )
    356 				re.AppActivate( !( fActive == WA_INACTIVE ) );
    357 		}
    358         return DefWindowProc (hWnd, uMsg, wParam, lParam);
    359 
    360 	case WM_MOVE:
    361 		{
    362 			int		xPos, yPos;
    363 			RECT r;
    364 			int		style;
    365 
    366 			if (!vid_fullscreen->value)
    367 			{
    368 				xPos = (short) LOWORD(lParam);    // horizontal position 
    369 				yPos = (short) HIWORD(lParam);    // vertical position 
    370 
    371 				r.left   = 0;
    372 				r.top    = 0;
    373 				r.right  = 1;
    374 				r.bottom = 1;
    375 
    376 				style = GetWindowLong( hWnd, GWL_STYLE );
    377 				AdjustWindowRect( &r, style, FALSE );
    378 
    379 				Cvar_SetValue( "vid_xpos", xPos + r.left);
    380 				Cvar_SetValue( "vid_ypos", yPos + r.top);
    381 				vid_xpos->modified = false;
    382 				vid_ypos->modified = false;
    383 				if (ActiveApp)
    384 					IN_Activate (true);
    385 			}
    386 		}
    387         return DefWindowProc (hWnd, uMsg, wParam, lParam);
    388 
    389 // this is complicated because Win32 seems to pack multiple mouse events into
    390 // one update sometimes, so we always check all states and look for events
    391 	case WM_LBUTTONDOWN:
    392 	case WM_LBUTTONUP:
    393 	case WM_RBUTTONDOWN:
    394 	case WM_RBUTTONUP:
    395 	case WM_MBUTTONDOWN:
    396 	case WM_MBUTTONUP:
    397 	case WM_MOUSEMOVE:
    398 		{
    399 			int	temp;
    400 
    401 			temp = 0;
    402 
    403 			if (wParam & MK_LBUTTON)
    404 				temp |= 1;
    405 
    406 			if (wParam & MK_RBUTTON)
    407 				temp |= 2;
    408 
    409 			if (wParam & MK_MBUTTON)
    410 				temp |= 4;
    411 
    412 			IN_MouseEvent (temp);
    413 		}
    414 		break;
    415 
    416 	case WM_SYSCOMMAND:
    417 		if ( wParam == SC_SCREENSAVE )
    418 			return 0;
    419         return DefWindowProc (hWnd, uMsg, wParam, lParam);
    420 	case WM_SYSKEYDOWN:
    421 		if ( wParam == 13 )
    422 		{
    423 			if ( vid_fullscreen )
    424 			{
    425 				Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->value );
    426 			}
    427 			return 0;
    428 		}
    429 		// fall through
    430 	case WM_KEYDOWN:
    431 		Key_Event( MapKey( lParam ), true, sys_msg_time);
    432 		break;
    433 
    434 	case WM_SYSKEYUP:
    435 	case WM_KEYUP:
    436 		Key_Event( MapKey( lParam ), false, sys_msg_time);
    437 		break;
    438 
    439 	case MM_MCINOTIFY:
    440 		{
    441 			LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    442 			lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
    443 		}
    444 		break;
    445 
    446 	default:	// pass all unhandled messages to DefWindowProc
    447         return DefWindowProc (hWnd, uMsg, wParam, lParam);
    448     }
    449 
    450     /* return 0 if handled message, 1 if not */
    451     return DefWindowProc( hWnd, uMsg, wParam, lParam );
    452 }
    453 
    454 /*
    455 ============
    456 VID_Restart_f
    457 
    458 Console command to re-start the video mode and refresh DLL. We do this
    459 simply by setting the modified flag for the vid_ref variable, which will
    460 cause the entire video mode and refresh DLL to be reset on the next frame.
    461 ============
    462 */
    463 void VID_Restart_f (void)
    464 {
    465 	vid_ref->modified = true;
    466 }
    467 
    468 void VID_Front_f( void )
    469 {
    470 	SetWindowLong( cl_hwnd, GWL_EXSTYLE, WS_EX_TOPMOST );
    471 	SetForegroundWindow( cl_hwnd );
    472 }
    473 
    474 /*
    475 ** VID_GetModeInfo
    476 */
    477 typedef struct vidmode_s
    478 {
    479 	const char *description;
    480 	int         width, height;
    481 	int         mode;
    482 } vidmode_t;
    483 
    484 vidmode_t vid_modes[] =
    485 {
    486 	{ "Mode 0: 320x240",   320, 240,   0 },
    487 	{ "Mode 1: 400x300",   400, 300,   1 },
    488 	{ "Mode 2: 512x384",   512, 384,   2 },
    489 	{ "Mode 3: 640x480",   640, 480,   3 },
    490 	{ "Mode 4: 800x600",   800, 600,   4 },
    491 	{ "Mode 5: 960x720",   960, 720,   5 },
    492 	{ "Mode 6: 1024x768",  1024, 768,  6 },
    493 	{ "Mode 7: 1152x864",  1152, 864,  7 },
    494 	{ "Mode 8: 1280x960",  1280, 960, 8 },
    495 	{ "Mode 9: 1600x1200", 1600, 1200, 9 }
    496 };
    497 
    498 qboolean VID_GetModeInfo( int *width, int *height, int mode )
    499 {
    500 	if ( mode < 0 || mode >= VID_NUM_MODES )
    501 		return false;
    502 
    503 	*width  = vid_modes[mode].width;
    504 	*height = vid_modes[mode].height;
    505 
    506 	return true;
    507 }
    508 
    509 /*
    510 ** VID_UpdateWindowPosAndSize
    511 */
    512 void VID_UpdateWindowPosAndSize( int x, int y )
    513 {
    514 	RECT r;
    515 	int		style;
    516 	int		w, h;
    517 
    518 	r.left   = 0;
    519 	r.top    = 0;
    520 	r.right  = viddef.width;
    521 	r.bottom = viddef.height;
    522 
    523 	style = GetWindowLong( cl_hwnd, GWL_STYLE );
    524 	AdjustWindowRect( &r, style, FALSE );
    525 
    526 	w = r.right - r.left;
    527 	h = r.bottom - r.top;
    528 
    529 	MoveWindow( cl_hwnd, vid_xpos->value, vid_ypos->value, w, h, TRUE );
    530 }
    531 
    532 /*
    533 ** VID_NewWindow
    534 */
    535 void VID_NewWindow ( int width, int height)
    536 {
    537 	viddef.width  = width;
    538 	viddef.height = height;
    539 
    540 	cl.force_refdef = true;		// can't use a paused refdef
    541 }
    542 
    543 void VID_FreeReflib (void)
    544 {
    545 	if ( !FreeLibrary( reflib_library ) )
    546 		Com_Error( ERR_FATAL, "Reflib FreeLibrary failed" );
    547 	memset (&re, 0, sizeof(re));
    548 	reflib_library = NULL;
    549 	reflib_active  = false;
    550 }
    551 
    552 /*
    553 ==============
    554 VID_LoadRefresh
    555 ==============
    556 */
    557 qboolean VID_LoadRefresh( char *name )
    558 {
    559 	refimport_t	ri;
    560 	GetRefAPI_t	GetRefAPI;
    561 	
    562 	if ( reflib_active )
    563 	{
    564 		re.Shutdown();
    565 		VID_FreeReflib ();
    566 	}
    567 
    568 	Com_Printf( "------- Loading %s -------\n", name );
    569 
    570 	if ( ( reflib_library = LoadLibrary( name ) ) == 0 )
    571 	{
    572 		Com_Printf( "LoadLibrary(\"%s\") failed\n", name );
    573 
    574 		return false;
    575 	}
    576 
    577 	ri.Cmd_AddCommand = Cmd_AddCommand;
    578 	ri.Cmd_RemoveCommand = Cmd_RemoveCommand;
    579 	ri.Cmd_Argc = Cmd_Argc;
    580 	ri.Cmd_Argv = Cmd_Argv;
    581 	ri.Cmd_ExecuteText = Cbuf_ExecuteText;
    582 	ri.Con_Printf = VID_Printf;
    583 	ri.Sys_Error = VID_Error;
    584 	ri.FS_LoadFile = FS_LoadFile;
    585 	ri.FS_FreeFile = FS_FreeFile;
    586 	ri.FS_Gamedir = FS_Gamedir;
    587 	ri.Cvar_Get = Cvar_Get;
    588 	ri.Cvar_Set = Cvar_Set;
    589 	ri.Cvar_SetValue = Cvar_SetValue;
    590 	ri.Vid_GetModeInfo = VID_GetModeInfo;
    591 	ri.Vid_MenuInit = VID_MenuInit;
    592 	ri.Vid_NewWindow = VID_NewWindow;
    593 
    594 	if ( ( GetRefAPI = (void *) GetProcAddress( reflib_library, "GetRefAPI" ) ) == 0 )
    595 		Com_Error( ERR_FATAL, "GetProcAddress failed on %s", name );
    596 
    597 	re = GetRefAPI( ri );
    598 
    599 	if (re.api_version != API_VERSION)
    600 	{
    601 		VID_FreeReflib ();
    602 		Com_Error (ERR_FATAL, "%s has incompatible api_version", name);
    603 	}
    604 
    605 	if ( re.Init( global_hInstance, MainWndProc ) == -1 )
    606 	{
    607 		re.Shutdown();
    608 		VID_FreeReflib ();
    609 		return false;
    610 	}
    611 
    612 	Com_Printf( "------------------------------------\n");
    613 	reflib_active = true;
    614 
    615 //======
    616 //PGM
    617 	vidref_val = VIDREF_OTHER;
    618 	if(vid_ref)
    619 	{
    620 		if(!strcmp (vid_ref->string, "gl"))
    621 			vidref_val = VIDREF_GL;
    622 		else if(!strcmp(vid_ref->string, "soft"))
    623 			vidref_val = VIDREF_SOFT;
    624 	}
    625 //PGM
    626 //======
    627 
    628 	return true;
    629 }
    630 
    631 /*
    632 ============
    633 VID_CheckChanges
    634 
    635 This function gets called once just before drawing each frame, and it's sole purpose in life
    636 is to check to see if any of the video mode parameters have changed, and if they have to 
    637 update the rendering DLL and/or video mode to match.
    638 ============
    639 */
    640 void VID_CheckChanges (void)
    641 {
    642 	char name[100];
    643 
    644 	if ( win_noalttab->modified )
    645 	{
    646 		if ( win_noalttab->value )
    647 		{
    648 			WIN_DisableAltTab();
    649 		}
    650 		else
    651 		{
    652 			WIN_EnableAltTab();
    653 		}
    654 		win_noalttab->modified = false;
    655 	}
    656 
    657 	if ( vid_ref->modified )
    658 	{
    659 		cl.force_refdef = true;		// can't use a paused refdef
    660 		S_StopAllSounds();
    661 	}
    662 	while (vid_ref->modified)
    663 	{
    664 		/*
    665 		** refresh has changed
    666 		*/
    667 		vid_ref->modified = false;
    668 		vid_fullscreen->modified = true;
    669 		cl.refresh_prepped = false;
    670 		cls.disable_screen = true;
    671 
    672 		Com_sprintf( name, sizeof(name), "ref_%s.dll", vid_ref->string );
    673 		if ( !VID_LoadRefresh( name ) )
    674 		{
    675 			if ( strcmp (vid_ref->string, "soft") == 0 )
    676 				Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!");
    677 			Cvar_Set( "vid_ref", "soft" );
    678 
    679 			/*
    680 			** drop the console if we fail to load a refresh
    681 			*/
    682 			if ( cls.key_dest != key_console )
    683 			{
    684 				Con_ToggleConsole_f();
    685 			}
    686 		}
    687 		cls.disable_screen = false;
    688 	}
    689 
    690 	/*
    691 	** update our window position
    692 	*/
    693 	if ( vid_xpos->modified || vid_ypos->modified )
    694 	{
    695 		if (!vid_fullscreen->value)
    696 			VID_UpdateWindowPosAndSize( vid_xpos->value, vid_ypos->value );
    697 
    698 		vid_xpos->modified = false;
    699 		vid_ypos->modified = false;
    700 	}
    701 }
    702 
    703 /*
    704 ============
    705 VID_Init
    706 ============
    707 */
    708 void VID_Init (void)
    709 {
    710 	/* Create the video variables so we know how to start the graphics drivers */
    711 	vid_ref = Cvar_Get ("vid_ref", "soft", CVAR_ARCHIVE);
    712 	vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
    713 	vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
    714 	vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE);
    715 	vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE );
    716 	win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE );
    717 
    718 	/* Add some console commands that we want to handle */
    719 	Cmd_AddCommand ("vid_restart", VID_Restart_f);
    720 	Cmd_AddCommand ("vid_front", VID_Front_f);
    721 
    722 	/*
    723 	** this is a gross hack but necessary to clamp the mode for 3Dfx
    724 	*/
    725 #if 0
    726 	{
    727 		cvar_t *gl_driver = Cvar_Get( "gl_driver", "opengl32", 0 );
    728 		cvar_t *gl_mode = Cvar_Get( "gl_mode", "3", 0 );
    729 
    730 		if ( stricmp( gl_driver->string, "3dfxgl" ) == 0 )
    731 		{
    732 			Cvar_SetValue( "gl_mode", 3 );
    733 			viddef.width  = 640;
    734 			viddef.height = 480;
    735 		}
    736 	}
    737 #endif
    738 
    739 	/* Disable the 3Dfx splash screen */
    740 	putenv("FX_GLIDE_NO_SPLASH=0");
    741 		
    742 	/* Start the graphics mode and load refresh DLL */
    743 	VID_CheckChanges();
    744 }
    745 
    746 /*
    747 ============
    748 VID_Shutdown
    749 ============
    750 */
    751 void VID_Shutdown (void)
    752 {
    753 	if ( reflib_active )
    754 	{
    755 		re.Shutdown ();
    756 		VID_FreeReflib ();
    757 	}
    758 }
    759 
    760