Video Mode Change in (Windows) GLQuake

Post tutorials on how to do certain tasks within game or engine code here.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Video Mode Change in (Windows) GLQuake

Post by Baker »

Image


Downloads

1. Changed source files (5) (download)

heavy changes: gl_vidnt.c
very minor changes: host.c, menu.c, menu.h, vid.h

2. Example glquake.exe (download)

Due to the complexity of the changes in gl_vidnt.c you may be better off using a file comparison tool to assist like [free + gpl] WinMerge or another comparison tool (link) to assist adding this in to an engine rather than using the tutorial. Here are some WinMerge screenshots, but there are several file comparison tools that do a good job.

Image Image
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

Adding Video Mode Change To GLQuake

This ranks up there as one of the more complicated things to add to the GLQuake engine. As a result, not many have this but this number is now up at least 6: DarkPlaces, FTEQW, Fitzquake, ezQuake, Qrack, ProQuake 3.99 .. I'm not aware of any others but maybe some other actively developed engine has this or will have in the next version (MHQuake?).

This tutorial is going to be based mostly on the FitzQuake version of video mode [except we aren't going to allow bits-per-pixel mode switching] and partially on the Qrack version. Additionally, this is double initialization where GLQuake will start up and set the video mode possibly twice.
Bits per pixel. That requires a lot more work, maybe some time in the future I'll add that into this tutorial but the reason is that you need to clear and reload the textures ... especially the 2D graphics ... and maybe some other fun stuff.
The Basics of What Needs Done

To support video mode switching, we'll need to restructure the fun things that need done once, to be done once. We'll need to restructure things that need done every time you do a mode change for that as well.

In addition, we'll be addressing 2 issues:

1. Increasing max video modes to 600 (was 30).
2. Because it is in this file, fixing the ALT-TAB problem where with some video cards you can gradually get the screen more and more offcenter.

And ...

3. We'll need a menu to control this.
4. We'll need to alter the writing of the cvars to config.

Due to the complexity, I'll upload the changed glquake source files too.

Begin:

Let's hit the easy files first before hitting the big dawg, gl_vidnt.c

1. vid.h
Open vid.h and find "extern void (*vid_menukeyfn)(int key);" and add immediately after:

Code: Select all

#ifdef GLQUAKE
extern void (*vid_menucmdfn)(void); //johnfitz
#endif
2. menu.c
Locate this: Add the yellow and delete/cut the red text:
void (*vid_menucmdfn)(void); //johnfitz
void (*vid_menudrawfn)(void);
void (*vid_menukeyfn)(int key);
enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;
We are moving m_state to menu.h.
3. menu.h
Add this to the bottom of menu.h
enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;
4. host.c
In Host_WriteConfiguration add the yellow text:
VID_SyncCvars (); //johnfitz -- write actual current mode to config file, in case cvars were messed with

Key_WriteBindings (f);
Cvar_WriteVariables (f);

fprintf (f, "vid_restart\n");
We need to refresh the vid_width, vid_height, etc. values before writing them to the config. We are hackily adding a vid_restart command to the end of config.cfg.

A better way would be to read the vid_width and vid_height values after reading the configuration file and checking to see if they changed. Maybe.
All the easy files have been done. All that remains is gl_vidnt.c.

Which we will do next time in 18 easy steps!
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

gl_vidnt.c

5.1 Locate and make alike:
#define MAX_MODE_LIST 600
30 video modes is too few on displays that support a lot of different width x height x bpp x refresh rate hz combinations.

5.2 Locate, add the yellow for refresh rate support:
typedef struct {
modestate_t type;
int width;
int height;
int modenum;
int dib;
int fullscreen;
int bpp;
int refreshrate; //johnfitz
int halfscreen;
char modedesc[17];
} vmode_t;
5.3 Find the declaration of cvar_t vid_mode and add the yellow:

These are our supporting cvars and other variables that allow us do this and keep track of things:
qboolean gl_mtexable = false;

qboolean video_options_disabled = false;

int desktop_bpp; // query this @ startup and when entering the video menu
void VID_Menu_Init (void); //johnfitz
void VID_Menu_f (void); //johnfitz

qboolean vid_locked = false; //johnfitz
int vid_current_bpp;//R00k

void GL_SetupState (void); //johnfitz

//====================================

//johnfitz -- new cvars
cvar_t vid_fullscreen = {"vid_fullscreen", "1", true};
cvar_t vid_width = {"vid_width", "640", true};
cvar_t vid_height = {"vid_height", "480", true};

int vid_bpp;
cvar_t vid_refreshrate = {"vid_refreshrate", "60", true};
//johnfitz



cvar_t vid_mode = {"vid_mode","0", false};
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

5.4 In VID_SetWindowedMode, locate this:

Code: Select all

	if (vid.conheight > modelist[modenum].height)
		vid.conheight = modelist[modenum].height;
	if (vid.conwidth > modelist[modenum].width)
		vid.conwidth = modelist[modenum].width;
	vid.width = vid.conwidth;
	vid.height = vid.conheight;
Replace with this so the console width and height change as needed on restart in windowed mode.

Code: Select all

	//johnfitz -- stuff
	vid.width = modelist[modenum].width;
	vid.height = modelist[modenum].height;
	vid.conwidth = vid.width & 0xFFFFFFF8;
	vid.conheight = vid.conwidth * vid.height / vid.width;
	//johnfitz
5.5 VID_SetFullDIBMode, add the yellow to store refresh rate:
gdevmode.dmPelsHeight = modelist[modenum].height;
gdevmode.dmDisplayFrequency = modelist[modenum].refreshrate; //johnfitz -- refreshrate
gdevmode.dmSize = sizeof (gdevmode);
5.6 VID_SetFullDIBMode (again!), comment old old console sizing stuff with /* --- */ and add the yellow. Console sizing again:
/* if (vid.conheight > modelist[modenum].height)
vid.conheight = modelist[modenum].height;
if (vid.conwidth > modelist[modenum].width)
vid.conwidth = modelist[modenum].width; */
vid.width = modelist[modenum].width;
vid.height = modelist[modenum].height;
vid.conwidth = vid.width & 0xFFFFFFF8;
vid.conheight = vid.conwidth * vid.height / vid.width;


vid.numpages = 2;
5.7 VID_SetMode, locate and add the yellow. This restarts the mouse -- particularly important with -dinput command line parameter.
VID_SetPalette (palette);

vid.recalc_refdef = 1;

//R00k mouse died on mode change
IN_StartupMouse ();


return true;
}
5.8 Above this:

Code: Select all

/*
================
VID_UpdateWindowStatus
================
*/
Add our new supporting functions for VID_Restart, sync'ing the cvars, and our "VID_Test".

(Your VID_Test won't wait 5 seconds and revert like FitzQuake .. if you want that, borrow the changes to scr_modalmessage in FitzQuake to add a timeout option.)

Code: Select all

/*
===================
VID_Restart -- johnfitz -- change video modes on the fly
===================
*/
void VID_SyncCvars (void);
//void VID_Conwidth_Reset (void);
void VID_Restart (void)
{
	HDC			hdc;
	HGLRC		hrc;
	int			i;
	qboolean	mode_changed = false;
	vmode_t		oldmode;

	if (vid_locked)
		return;

//
// check cvars against current mode
//
	if (vid_fullscreen.value)
	{
		if (modelist[vid_default].type == MS_WINDOWED)
			mode_changed = true;
		else if (modelist[vid_default].refreshrate != (int)vid_refreshrate.value)
			mode_changed = true;
	}
	else
		if (modelist[vid_default].type != MS_WINDOWED)
			mode_changed = true;

	if (modelist[vid_default].width != (int)vid_width.value ||
		modelist[vid_default].height != (int)vid_height.value)
		mode_changed = true;

	if (mode_changed)
	{
//
// decide which mode to set
//
		oldmode = modelist[vid_default];

		if (vid_fullscreen.value)
		{
			for (i=1; i<nummodes; i++)
			{
				if (modelist[i].width == (int)vid_width.value &&
					modelist[i].height == (int)vid_height.value &&
					modelist[i].bpp == (int)vid_bpp &&
					modelist[i].refreshrate == (int)vid_refreshrate.value)
				{
					break;
				}
			}

			if (i == nummodes)
			{
				Con_Printf ("%dx%dx%d %dHz is not a valid fullscreen mode\n",
							(int)vid_width.value,
							(int)vid_height.value,
							(int)vid_bpp,
							(int)vid_refreshrate.value);
				return;
			}

			windowed = false;
			vid_default = i;
		}
		else //not fullscreen
		{
			hdc = GetDC (NULL);
			if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
			{
				Con_Printf ("Can't run windowed on non-RGB desktop\n");
				ReleaseDC (NULL, hdc);
				return;
			}
			ReleaseDC (NULL, hdc);

			if (vid_width.value < 320)
			{
				Con_Printf ("Window width can't be less than 320\n");
				return;
			}

			if (vid_height.value < 200)
			{
				Con_Printf ("Window height can't be less than 200\n");
				return;
			}

			modelist[0].width = (int)vid_width.value;
			modelist[0].height = (int)vid_height.value;
			sprintf (modelist[0].modedesc, "%dx%dx%d %dHz",
					 modelist[0].width,
					 modelist[0].height,
					 modelist[0].bpp,
					 modelist[0].refreshrate);

			windowed = true;
			vid_default = 0;
		}
//
// destroy current window
//
		hrc = wglGetCurrentContext();
		hdc = wglGetCurrentDC();
		wglMakeCurrent(NULL, NULL);

		vid_canalttab = false;

		if (hdc && dibwindow)
			ReleaseDC (dibwindow, hdc);
		if (modestate == MS_FULLDIB)
			ChangeDisplaySettings (NULL, 0);
		if (maindc && dibwindow)
			ReleaseDC (dibwindow, maindc);
		maindc = NULL;
		if (dibwindow)
			DestroyWindow (dibwindow);
//
// set new mode
//
		VID_SetMode (vid_default, host_basepal);
		maindc = GetDC(mainwindow);
		bSetupPixelFormat(maindc);

		// if bpp changes, recreate render context and reload textures
		if (modelist[vid_default].bpp != oldmode.bpp)
		{
			wglDeleteContext (hrc);
			hrc = wglCreateContext (maindc);
			if (!wglMakeCurrent (maindc, hrc))
				Sys_Error ("VID_Restart: wglMakeCurrent failed");
			
			GL_SetupState ();
		}
		else
			if (!wglMakeCurrent (maindc, hrc))
#if 1
			{
				char szBuf[80];
				LPVOID lpMsgBuf;
				DWORD dw = GetLastError();
				FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );
				sprintf(szBuf, "VID_Restart: wglMakeCurrent failed with error %d: %s", dw, lpMsgBuf);
 				Sys_Error (szBuf);
			}
#else
				Sys_Error ("VID_Restart: wglMakeCurrent failed");
#endif

		vid_canalttab = true;
	}

}

/*
================
VID_Test -- johnfitz -- like vid_restart, but asks for confirmation after switching modes
================
*/
void VID_Test (void)
{
	vmode_t oldmode;
	qboolean	mode_changed = false;

	if (vid_locked)
		return;
//
// check cvars against current mode
//
	if (vid_fullscreen.value)
	{
		if (modelist[vid_default].type == MS_WINDOWED)
			mode_changed = true;
/*		else if (modelist[vid_default].bpp != (int)vid_bpp.value)
			mode_changed = true; */
		else if (modelist[vid_default].refreshrate != (int)vid_refreshrate.value)
			mode_changed = true;
	}
	else
		if (modelist[vid_default].type != MS_WINDOWED)
			mode_changed = true;

	if (modelist[vid_default].width != (int)vid_width.value ||
		modelist[vid_default].height != (int)vid_height.value)
		mode_changed = true;

	if (!mode_changed)
		return;
//
// now try the switch
//
	oldmode = modelist[vid_default];

	VID_Restart ();

	//pop up confirmation dialoge
	if (!SCR_ModalMessage("Would you like to keep this\nvideo mode? (y/n)\n"))
	{
		//revert cvars and mode
		Cvar_Set ("vid_width", va("%i", oldmode.width));
		Cvar_Set ("vid_height", va("%i", oldmode.height));
		Cvar_Set ("vid_bpp", va("%i", oldmode.bpp));
		Cvar_Set ("vid_refreshrate", va("%i", oldmode.refreshrate));
		Cvar_Set ("vid_fullscreen", (oldmode.type == MS_WINDOWED) ? "0" : "1");
		VID_Restart ();
	}
}

/*
================
VID_Unlock -- johnfitz
================
*/
void VID_Unlock (void)
{
	vid_locked = false;

	//sync up cvars in case they were changed during the lock
	Cvar_Set ("vid_width", va("%i", modelist[vid_default].width));
	Cvar_Set ("vid_height", va("%i", modelist[vid_default].height));
	Cvar_Set ("vid_refreshrate", va("%i", modelist[vid_default].refreshrate));
	Cvar_Set ("vid_fullscreen", (windowed) ? "0" : "1");
}
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

5.9 Now we need the GL initiation split into 2 pieces, the part that needs done once vs. the setup that needs to occur duriing any video mode switch.

So the Locate GL_Init, Find this and ....

Code: Select all

/*
===============
GL_Init
===============
*/
void GL_Init (void)
{
	gl_vendor = glGetString (GL_VENDOR);
	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
	gl_renderer = glGetString (GL_RENDERER);
	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);

	gl_version = glGetString (GL_VERSION);
	Con_Printf ("GL_VERSION: %s\n", gl_version);
	gl_extensions = glGetString (GL_EXTENSIONS);
	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);

//	Con_Printf ("%s %s\n", gl_renderer, gl_version);

    if (strnicmp(gl_renderer,"PowerVR",7)==0)
         fullsbardraw = true;

    if (strnicmp(gl_renderer,"Permedia",8)==0)
         isPermedia = true;

	CheckTextureExtensions ();
	CheckMultiTextureExtensions ();

	glClearColor (1,0,0,0);
	glCullFace(GL_FRONT);
	glEnable(GL_TEXTURE_2D);

	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER, 0.666);

	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
	glShadeModel (GL_FLAT);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

//	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

#if 0
	CheckArrayExtensions ();

	glEnable (GL_VERTEX_ARRAY_EXT);
	glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
	glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
	glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
	glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
#endif
}
And replace with this:

Code: Select all

/*
===============
GL_SetupState -- johnfitz

does all the stuff from GL_Init that needs to be done every time a new GL render context is created
GL_Init will still do the stuff that only needs to be done once
===============
*/
void GL_SetupState (void) {
	glClearColor (1,0,0,0); 
	glCullFace(GL_FRONT);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER, 0.666);
	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
	glShadeModel (GL_FLAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}

/*
===============
GL_Init
===============
*/
void GL_Init (void)
{
	gl_vendor = glGetString (GL_VENDOR);
	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
	gl_renderer = glGetString (GL_RENDERER);
	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);

	gl_version = glGetString (GL_VERSION);
	Con_Printf ("GL_VERSION: %s\n", gl_version);
	gl_extensions = glGetString (GL_EXTENSIONS);
	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);

//	Con_Printf ("%s %s\n", gl_renderer, gl_version);

    if (strnicmp(gl_renderer,"PowerVR",7)==0)
         fullsbardraw = true;

    if (strnicmp(gl_renderer,"Permedia",8)==0)
         isPermedia = true;

	CheckTextureExtensions ();
	CheckMultiTextureExtensions ();


#if 0
	CheckArrayExtensions ();

	glEnable (GL_VERTEX_ARRAY_EXT);
	glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
	glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
	glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
	glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
#endif

	GL_SetupState (); //johnfitz
}
5.10 Find VID_InitDIB and add or match with the yellow:
void VID_InitDIB (HINSTANCE hInstance)
{
DEVMODE devmode; //johnfitz
WNDCLASS wc;
HDC hdc;
int i;

/* Register the frame class */
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = 0;
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = "WinQuake";

if (!RegisterClass (&wc) )
Sys_Error ("Couldn't register window class");

modelist[0].type = MS_WINDOWED;

if (COM_CheckParm("-width"))
modelist[0].width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
else
modelist[0].width = 640;

if (modelist[0].width < 320)
modelist[0].width = 320;

if (COM_CheckParm("-height"))
modelist[0].height= Q_atoi(com_argv[COM_CheckParm("-height")+1]);
else
modelist[0].height = modelist[0].width * 240/320;

if (modelist[0].height < 200) //johnfitz -- was 240
modelist[0].height = 200; //johnfitz -- was 240

//johnfitz -- get desktop bit depth
hdc = GetDC(NULL);
modelist[0].bpp = desktop_bpp = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
//johnfitz

//johnfitz -- get refreshrate
if (EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &devmode))
modelist[0].refreshrate = devmode.dmDisplayFrequency;
//johnfitz

sprintf (modelist[0].modedesc, "%dx%dx%d %dHz", //johnfitz -- added bpp, refreshrate
modelist[0].width,
modelist[0].height,
modelist[0].bpp, //johnfitz -- added bpp
modelist[0].refreshrate); //johnfitz -- added refreshrate

modelist[0].modenum = MODE_WINDOWED;
modelist[0].dib = 1;
modelist[0].fullscreen = 0;
modelist[0].halfscreen = 0;
// modelist[0].bpp = 0; // Baker says <--- no! Keep same bpp!


nummodes = 1;
}
5.11 In "VID_InitFullDIB" add or change to the yellow:

This is to support our refreshrate hz.
/*
=================
VID_InitFullDIB
=================
*/
void VID_InitFullDIB (HINSTANCE hInstance)
{
DEVMODE devmode;
int i, modenum, cmodes, originalnummodes, existingmode, numlowresmodes;
int j, bpp, done;
BOOL stat;

// enumerate >8 bpp modes
originalnummodes = nummodes;
modenum = 0;

do
{
stat = EnumDisplaySettings (NULL, modenum, &devmode);

if ((devmode.dmBitsPerPel >= 15) &&
(devmode.dmPelsWidth <= MAXWIDTH) &&
(devmode.dmPelsHeight <= MAXHEIGHT) &&
(nummodes < MAX_MODE_LIST))
{
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_DISPLAYFREQUENCY; //johnfitz -- refreshrate


if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = devmode.dmPelsWidth;
modelist[nummodes].height = devmode.dmPelsHeight;
modelist[nummodes].modenum = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = devmode.dmBitsPerPel;
modelist[nummodes].refreshrate = devmode.dmDisplayFrequency; //johnfitz -- refreshrate
sprintf (modelist[nummodes].modedesc, "%dx%dx%d %dHz", //johnfitz -- refreshrate
devmode.dmPelsWidth,
devmode.dmPelsHeight,
devmode.dmBitsPerPel,
devmode.dmDisplayFrequency); //johnfitz -- refreshrate


// if the width is more than twice the height, reduce it by half because this
// is probably a dual-screen monitor
if (!COM_CheckParm("-noadjustaspect"))
{
if (modelist[nummodes].width > (modelist[nummodes].height << 1))
{
modelist[nummodes].width >>= 1;
modelist[nummodes].halfscreen = 1;
sprintf (modelist[nummodes].modedesc, "%dx%dx%d %dHz", //johnfitz -- refreshrate
modelist[nummodes].width,
modelist[nummodes].height,
modelist[nummodes].bpp,
modelist[nummodes].refreshrate); //johnfitz -- refreshrate

}
}

for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist.width) &&
(modelist[nummodes].height == modelist.height) &&
(modelist[nummodes].bpp == modelist.bpp) &&
(modelist[nummodes].refreshrate == modelist.refreshrate)) //johnfitz -- refreshrate

{
existingmode = 1;
break;
}
}

if (!existingmode)
{
nummodes++;
}
}
}

modenum++;
} while (stat);

// see if there are any low-res modes that aren't being reported
numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
bpp = 16;
done = 0;

do
{
for (j=0 ; (j<numlowresmodes) && (nummodes < MAX_MODE_LIST) ; j++)
{
devmode.dmBitsPerPel = bpp;
devmode.dmPelsWidth = lowresmodes[j].width;
devmode.dmPelsHeight = lowresmodes[j].height;
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_DISPLAYFREQUENCY; //johnfitz -- refreshrate;


if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = devmode.dmPelsWidth;
modelist[nummodes].height = devmode.dmPelsHeight;
modelist[nummodes].modenum = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = devmode.dmBitsPerPel;
modelist[nummodes].refreshrate = devmode.dmDisplayFrequency; //johnfitz -- refreshrate
sprintf (modelist[nummodes].modedesc, "%dx%dx%d %dHz", //johnfitz -- refreshrate
devmode.dmPelsWidth,
devmode.dmPelsHeight,
devmode.dmBitsPerPel,
devmode.dmDisplayFrequency); //johnfitz -- refreshrate


for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist.width) &&
(modelist[nummodes].height == modelist.height) &&
(modelist[nummodes].bpp == modelist.bpp) &&
(modelist[nummodes].refreshrate == modelist.refreshrate)) //johnfitz -- refreshrate

{
existingmode = 1;
break;
}
}

if (!existingmode)
{
nummodes++;
}
}
}
switch (bpp)
{
case 16:
bpp = 32;
break;

case 32:
bpp = 24;
break;

case 24:
done = 1;
break;
}
} while (!done);

if (nummodes == originalnummodes)
Con_SafePrintf ("No fullscreen DIB modes found\n");
}
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

5.12 In VID_Init, add the yellow
/*
===================
VID_Init
===================
*/
void VID_Init (unsigned char *palette)
{
int i, existingmode;
int basenummodes, width, height, bpp, findbpp, done;
byte *ptmp;
char gldir[MAX_OSPATH];
HDC hdc;
DEVMODE devmode;

memset(&devmode, 0, sizeof(devmode));

Cvar_RegisterVariable (&vid_fullscreen); //johnfitz
Cvar_RegisterVariable (&vid_width); //johnfitz
Cvar_RegisterVariable (&vid_height); //johnfitz

Cvar_RegisterVariable (&vid_refreshrate); //johnfitz

Cmd_AddCommand ("vid_unlock", VID_Unlock); //johnfitz
Cmd_AddCommand ("vid_restart", VID_Restart); //johnfitz
Cmd_AddCommand ("vid_test", VID_Test); //johnfitz



Cvar_RegisterVariable (&vid_mode);
Cvar_RegisterVariable (&vid_wait);
Cvar_RegisterVariable (&vid_nopageflip);
Cvar_RegisterVariable (&_vid_wait_override);
Cvar_RegisterVariable (&_vid_default_mode);
Cvar_RegisterVariable (&_vid_default_mode_win);
Cvar_RegisterVariable (&vid_config_x);
Cvar_RegisterVariable (&vid_config_y);
Cvar_RegisterVariable (&vid_stretch_by_2);
Cvar_RegisterVariable (&_windowed_mouse);
Cvar_RegisterVariable (&gl_ztrick);

Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);

hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2));

InitCommonControls();

VID_InitDIB (global_hInstance);
basenummodes = nummodes = 1;

VID_InitFullDIB (global_hInstance);

if (COM_CheckParm("-window"))
{
hdc = GetDC (NULL);

if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
{
Sys_Error ("Can't run in non-RGB mode");
}

ReleaseDC (NULL, hdc);

windowed = true;
video_options_disabled = true;
vid_default = MODE_WINDOWED;
}
else
{
if (nummodes == 1)
Sys_Error ("No RGB fullscreen modes available");

windowed = false;

if (COM_CheckParm("-mode"))
{
vid_default = Q_atoi(com_argv[COM_CheckParm("-mode")+1]);
}
else
{
if (COM_CheckParm("-current"))
{
modelist[MODE_FULLSCREEN_DEFAULT].width =
GetSystemMetrics (SM_CXSCREEN);
modelist[MODE_FULLSCREEN_DEFAULT].height =
GetSystemMetrics (SM_CYSCREEN);
vid_default = MODE_FULLSCREEN_DEFAULT;
leavecurrentmode = 1;
}
else
{
if (COM_CheckParm("-width"))
{
width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
}
else
{
width = 640;
}

if (COM_CheckParm("-bpp"))
{
bpp = Q_atoi(com_argv[COM_CheckParm("-bpp")+1]);
findbpp = 0;
}
else
{
bpp = desktop_bpp; // Baker: match the desktop bpp if not specified, was 15
findbpp = 1;
}

if (COM_CheckParm("-height"))
height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);

// if they want to force it, add the specified mode to the list
if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST))
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = width;
modelist[nummodes].height = height;
modelist[nummodes].modenum = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = bpp;
sprintf (modelist[nummodes].modedesc, "%dx%dx%d %dHz", //johnfitz -- refreshrate
devmode.dmPelsWidth,
devmode.dmPelsHeight,
devmode.dmBitsPerPel,
devmode.dmDisplayFrequency); //johnfitz -- refreshrate


for (i=nummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist.width) &&
(modelist[nummodes].height == modelist.height) &&
(modelist[nummodes].bpp == modelist.bpp) &&
(modelist[nummodes].refreshrate == modelist.refreshrate)) //johnfitz -- refreshrate

{
existingmode = 1;
break;
}
}

if (!existingmode)
{
nummodes++;
}
}

done = 0;

do
{
if (COM_CheckParm("-height"))
{
height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);

for (i=1, vid_default=0 ; i<nummodes ; i++)
{
if ((modelist.width == width) &&
(modelist.height == height) &&
(modelist.bpp == bpp))
{
vid_default = i;
done = 1;
break;
}
}
}
else
{
for (i=1, vid_default=0 ; i<nummodes ; i++)
{
if ((modelist.width == width) && (modelist.bpp == bpp))
{
vid_default = i;
done = 1;
break;
}
}
}

if (!done)
{
if (findbpp)
{
switch (bpp)
{
case 15:
bpp = 16;
break;
case 16:
bpp = 32;
break;
case 32:
bpp = 24;
break;
case 24:
done = 1;
break;
}
}
else
{
done = 1;
}
}
} while (!done);

vid_bpp = bpp;


if (!vid_default)
{
Sys_Error ("Specified video mode not available");
}
}
}
}

vid_initialized = true;

if ((i = COM_CheckParm("-conwidth")) != 0)
vid.conwidth = Q_atoi(com_argv[i+1]);
else
vid.conwidth = 640;

vid.conwidth &= 0xfff8; // make it a multiple of eight

if (vid.conwidth < 320)
vid.conwidth = 320;

// pick a conheight that matches with correct aspect
vid.conheight = vid.conwidth*3 / 4;

if ((i = COM_CheckParm("-conheight")) != 0)
vid.conheight = Q_atoi(com_argv[i+1]);
if (vid.conheight < 200)
vid.conheight = 200;

vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));

DestroyWindow (hwnd_dialog);

Check_Gamma(palette);
VID_SetPalette (palette);

VID_SetMode (vid_default, palette);

maindc = GetDC(mainwindow);
bSetupPixelFormat(maindc);

baseRC = wglCreateContext( maindc );
if (!baseRC)
Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
if (!wglMakeCurrent( maindc, baseRC ))
Sys_Error ("wglMakeCurrent failed");

GL_Init ();

sprintf (gldir, "%s/glquake", com_gamedir);
Sys_mkdir (gldir);

vid_realmode = vid_modenum;

// Check for 3DFX Extensions and initialize them.
VID_Init8bitPalette();

vid_menucmdfn = VID_Menu_f; //johnfitz
vid_menudrawfn = VID_MenuDraw;
vid_menukeyfn = VID_MenuKey;

strcpy (badmode.modedesc, "Bad mode");
vid_canalttab = true;

if (COM_CheckParm("-fullsbar"))
fullsbardraw = true;

VID_Menu_Init(); //johnfitz

//johnfitz -- command line vid settings should override config file settings.
//so we have to lock the vid mode from now until after all config files are read.
if (COM_CheckParm("-width") || COM_CheckParm("-height") || COM_CheckParm("-bpp") || COM_CheckParm("-window"))
{
vid_locked = true;
}
//johnfitz

}
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

AND FINALLY:

5.13 Find all this code:

Code: Select all

//========================================================
// Video menu stuff
//========================================================

extern void M_Menu_Options_f (void);
extern void M_Print (int cx, int cy, char *str);
extern void M_PrintWhite (int cx, int cy, char *str);
extern void M_DrawCharacter (int cx, int line, int num);
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
extern void M_DrawPic (int x, int y, qpic_t *pic);

static int	vid_line, vid_wmodes;

typedef struct
{
	int		modenum;
	char	*desc;
	int		iscur;
} modedesc_t;

#define MAX_COLUMN_SIZE		9
#define MODE_AREA_HEIGHT	(MAX_COLUMN_SIZE + 2)
#define MAX_MODEDESCS		(MAX_COLUMN_SIZE*3)

static modedesc_t	modedescs[MAX_MODEDESCS];

/*
================
VID_MenuDraw
================
*/
void VID_MenuDraw (void)
{
	qpic_t		*p;
	char		*ptr;
	int			lnummodes, i, j, k, column, row, dup, dupmode;
	char		temp[100];
	vmode_t		*pv;

	p = Draw_CachePic ("gfx/vidmodes.lmp");
	M_DrawPic ( (320-p->width)/2, 4, p);

	vid_wmodes = 0;
	lnummodes = VID_NumModes ();
	
	for (i=1 ; (i<lnummodes) && (vid_wmodes < MAX_MODEDESCS) ; i++)
	{
		ptr = VID_GetModeDescription (i);
		pv = VID_GetModePtr (i);

		k = vid_wmodes;

		modedescs[k].modenum = i;
		modedescs[k].desc = ptr;
		modedescs[k].iscur = 0;

		if (i == vid_modenum)
			modedescs[k].iscur = 1;

		vid_wmodes++;

	}

	if (vid_wmodes > 0)
	{
		M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)");

		column = 8;
		row = 36+2*8;

		for (i=0 ; i<vid_wmodes ; i++)
		{
			if (modedescs[i].iscur)
				M_PrintWhite (column, row, modedescs[i].desc);
			else
				M_Print (column, row, modedescs[i].desc);

			column += 13*8;

			if ((i % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
			{
				column = 8;
				row += 8;
			}
		}
	}

	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*2,
			 "Video modes must be set from the");
	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
			 "command line with -width <width>");
	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4,
			 "and -bpp <bits-per-pixel>");
	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
			 "Select windowed mode with -window");
}


/*
================
VID_MenuKey
================
*/
void VID_MenuKey (int key)
{
	switch (key)
	{
	case K_ESCAPE:
		S_LocalSound ("misc/menu1.wav");
		M_Menu_Options_f ();
		break;

	default:
		break;
	}
}
And replace with our new video menu:

Code: Select all



/*
================
VID_SyncCvars -- johnfitz -- set vid cvars to match current video mode
================
*/
extern qboolean vid_consize_ignore_callback;
void VID_SyncCvars (void)
{
	Cvar_Set ("vid_width", va("%i", modelist[vid_default].width));
	Cvar_Set ("vid_height", va("%i", modelist[vid_default].height));
	Cvar_Set ("vid_refreshrate", va("%i", modelist[vid_default].refreshrate));
	Cvar_Set ("vid_fullscreen", (windowed) ? "0" : "1");
}

//==========================================================================
//
//  NEW VIDEO MENU -- johnfitz
//
//==========================================================================

extern void M_Menu_Options_f (void);
extern void M_Print (int cx, int cy, char *str);
extern void M_PrintWhite (int cx, int cy, char *str);
extern void M_DrawCharacter (int cx, int line, int num);
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
extern void M_DrawPic (int x, int y, qpic_t *pic);
extern void M_DrawCheckbox (int x, int y, int on);

extern qboolean	m_entersound;



#define VIDEO_OPTIONS_ITEMS 6
int		video_cursor_table[] = {48, 56, 64, 72, 88, 96};
int		video_options_cursor = 0;

typedef struct {int width,height;} vid_menu_mode;

//TODO: replace these fixed-length arrays with hunk_allocated buffers

vid_menu_mode vid_menu_modes[MAX_MODE_LIST];
int vid_menu_nummodes=0;

//int vid_menu_bpps[4];
//int vid_menu_numbpps=0;

int vid_menu_rates[20];
int vid_menu_numrates=0;

/*
================
VID_Menu_Init
================
*/
void VID_Menu_Init (void)
{
	int i,j,h,w;

	for (i=1;i<nummodes;i++) //start i at mode 1 because 0 is windowed mode
	{
		w = modelist[i].width;
		h = modelist[i].height;

		for (j=0;j<vid_menu_nummodes;j++)
{
			if (vid_menu_modes[j].width == w &&
				vid_menu_modes[j].height == h)
				break;
		}

		if (j==vid_menu_nummodes)
		{
			vid_menu_modes[j].width = w;
			vid_menu_modes[j].height = h;
			vid_menu_nummodes++;
		}
	}
}


/*
================
VID_Menu_RebuildRateList

regenerates rate list based on current vid_width, vid_height and vid_bpp
================
*/
void VID_Menu_RebuildRateList (void)
{
	int i,j,r;

	vid_menu_numrates=0;

	for (i=1;i<nummodes;i++) //start i at mode 1 because 0 is windowed mode
	{
		//rate list is limited to rates available with current width/height/bpp
		if (modelist[i].width != vid_width.value ||
			modelist[i].height != vid_height.value /*||
			modelist[i].bpp != vid_bpp.value*/)
			continue;

		r = modelist[i].refreshrate;

		for (j=0;j<vid_menu_numrates;j++)
		{
			if (vid_menu_rates[j] == r)
				break;
		}

		if (j==vid_menu_numrates)
		{
			vid_menu_rates[j] = r;
			vid_menu_numrates++;
		}
	}

	//if vid_refreshrate is not in the new list, change vid_refreshrate
	for (i=0;i<vid_menu_numrates;i++)
		if (vid_menu_rates[i] == (int)(vid_refreshrate.value))
			break;

	if (i==vid_menu_numrates)
		Cvar_Set ("vid_refreshrate",va("%i",vid_menu_rates[0]));
	}

/*
================
VID_Menu_ChooseNextMode

chooses next resolution in order, then updates vid_width and
vid_height cvars, then updates bpp and refreshrate lists
================
*/
void VID_Menu_ChooseNextMode (int dir)
{
	int i;

	for (i=0;i<vid_menu_nummodes;i++)
	{
		if (vid_menu_modes[i].width == vid_width.value &&
			vid_menu_modes[i].height == vid_height.value)
			break;
	}

	if (i==vid_menu_nummodes) //can't find it in list, so it must be a custom windowed res
	{
		i = 0;
	}
			else
	{
		i+=dir;
		if (i>=vid_menu_nummodes)
			i = 0;
		else if (i<0)
			i = vid_menu_nummodes-1;
	}

	Cvar_Set ("vid_width",va("%i",vid_menu_modes[i].width));
	Cvar_Set ("vid_height",va("%i",vid_menu_modes[i].height));
	VID_Menu_RebuildRateList ();
}

/*
================
VID_Menu_ChooseNextRate

chooses next refresh rate in order, then updates vid_refreshrate cvar
================
*/
void VID_Menu_ChooseNextRate (int dir)
{
	int i;

	for (i=0;i<vid_menu_numrates;i++)
	{
		if (vid_menu_rates[i] == vid_refreshrate.value)
			break;
	}

	if (i==vid_menu_numrates) //can't find it in list
	{
		i = 0;
	}
	else
	{
		i+=dir;
		if (i>=vid_menu_numrates)
			i = 0;
		else if (i<0)
			i = vid_menu_numrates-1;
}

	Cvar_Set ("vid_refreshrate",va("%i",vid_menu_rates[i]));
}

/*
================
VID_MenuKey
================
*/
void VID_MenuKey (int key)
{
	switch (key)
	{
	case K_ESCAPE:
		VID_SyncCvars (); //sync cvars before leaving menu. FIXME: there are other ways to leave menu
		S_LocalSound ("misc/menu1.wav");
		M_Menu_Options_f ();
		break;

	case K_UPARROW:
		S_LocalSound ("misc/menu1.wav");
		video_options_cursor--;
		if (video_options_cursor < 0)
			video_options_cursor = VIDEO_OPTIONS_ITEMS-1;
		break;

	case K_DOWNARROW:
		S_LocalSound ("misc/menu1.wav");
		video_options_cursor++;
		if (video_options_cursor >= VIDEO_OPTIONS_ITEMS)
			video_options_cursor = 0;
		break;

	case K_LEFTARROW:
		S_LocalSound ("misc/menu3.wav");
		switch (video_options_cursor)
		{
		case 0:
			VID_Menu_ChooseNextMode (-1);
			break;
		case 1:
			//VID_Menu_ChooseNextBpp (-1);
			break;
		case 2:
			VID_Menu_ChooseNextRate (-1);
			break;
		case 3:
			Cbuf_AddText ("toggle vid_fullscreen\n");
			break;
		case 4:
		case 5:
	default:
		break;
	}
		break;

	case K_RIGHTARROW:
		S_LocalSound ("misc/menu3.wav");
		switch (video_options_cursor)
		{
		case 0:
			VID_Menu_ChooseNextMode (1);
			break;
		case 1:
			//VID_Menu_ChooseNextBpp (1);
			break;
		case 2:
			VID_Menu_ChooseNextRate (1);
			break;
		case 3:
			if (vid_bpp == desktop_bpp)
				Cbuf_AddText ("toggle vid_fullscreen\n");
			break;
		case 4:
		case 5:
		default:
			break;
		}
		break;

	case K_ENTER:
		m_entersound = true;
		switch (video_options_cursor)
		{
		case 0:
			VID_Menu_ChooseNextMode (1);
			break;
		case 1:
			//VID_Menu_ChooseNextBpp (1);
			break;
		case 2:
			VID_Menu_ChooseNextRate (1);
			break;
		case 3:
			if (vid_bpp == desktop_bpp)
				Cbuf_AddText ("toggle vid_fullscreen\n");

			break;
		case 4:
			Cbuf_AddText ("vid_test\n");
			break;
		case 5:
			Cbuf_AddText ("vid_restart\n");
			break;
		default:
			break;
		}
		break;

	default:
		break;
	}
}

/*
================
VID_MenuDraw
================
*/
void VID_MenuDraw (void)
{
	int i = 0;
	qpic_t *p;
	char *title;

	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp"));

	//p = Draw_CachePic ("gfx/vidmodes.lmp");
	p = Draw_CachePic ("gfx/p_option.lmp");
	M_DrawPic ( (320-p->width)/2, 4, p);

	// title
	title = "Video Options";
	M_PrintWhite ((320-8*strlen(title))/2, 32, title);

	// options
	M_Print (16, video_cursor_table[i], "            Video mode");
	M_Print (216, video_cursor_table[i], va("%ix%i", (int)vid_width.value, (int)vid_height.value));
	i++;

	M_Print (16, video_cursor_table[i], "           Color depth");
	M_Print (216, video_cursor_table[i], va("%i [locked]", (int)vid_bpp));
	i++; 

	M_Print (16, video_cursor_table[i], "          Refresh rate");
	M_Print (216, video_cursor_table[i], va("%i Hz", (int)vid_refreshrate.value));
	i++;

	M_Print (16, video_cursor_table[i], "            Fullscreen");

	if (vid_bpp == desktop_bpp)
		M_DrawCheckbox (216, video_cursor_table[i], (int)vid_fullscreen.value);
	else
		M_Print (216, video_cursor_table[i], va("%s [locked]", (int)vid_fullscreen.value ? "on" : "off"));

	i++;

	M_Print (16, video_cursor_table[i], "          Test changes");
	i++;

	M_Print (16, video_cursor_table[i], "         Apply changes");

	// cursor
	M_DrawCharacter (200, video_cursor_table[video_options_cursor], 12+((int)(realtime*4)&1));

	// notes          "345678901234567890123456789012345678"
//	M_Print (16, 172, "Windowed modes always use the desk- ");
//	M_Print (16, 180, "top color depth, and can never be   ");
//	M_Print (16, 188, "larger than the desktop resolution. ");
}

/*
================
VID_Menu_f
================
*/
void VID_Menu_f (void)
{
	key_dest = key_menu;
	m_state = m_video;
	m_entersound = true;

	//set all the cvars to match the current mode when entering the menu
	VID_SyncCvars ();

	//set up bpp and rate lists based on current cvars
	VID_Menu_RebuildRateList ();
}
And we are done. Compile and run.

I guess the changes to gl_vidnt.c can be done in 13 steps, not 18.

Your new cvars are:
vid_width
vid_height
vid_fullscreen

and so forth

Your new commands are vid_restart and vid_test.

To change the video mode, go Options -> Video Mode.

To create an ALT-ENTER like alias, you could create an alias like:

alias fullscreen_toggle "toggle vid_fullscreen; vid_restart"

Except GLQuake doesn't have a toggle command, but you could borrow the toggle command from cvar.c in FitzQuake 0.80 if you wanted.

Then if you wanted ALT-ENTER support, go to keys.c and detect ENTER with a ALT state of down and have it execute "toggle vid_fullscreen; vid_restart"if you like.

Find note, you should really do this as well in gl_vidnt.c. I didn't include it in the above:
r00k wrote:In my addition to adding alt-enter,
i had to implement this bit

Code: Select all

		case WM_ACTIVATE:
			fActive = LOWORD(wParam);
			fMinimized = (BOOL) HIWORD(wParam);
			AppActivate(!(fActive == WA_INACTIVE), fMinimized);
		// fix the leftover Alt from any Alt-Tab or the like that switched us away
			Key_ClearAllStates();
			//R00k re-init the mouse after alt-tabbing please... (v1.9)
			if (!mouseactive)
			{
				IN_Shutdown ();
				IN_StartupMouse();
				IN_ActivateMouse ();
				IN_HideMouse ();
			}
			break;
Additionally in gl_vidnt.c, really you should add the Nvidia ALT-TAB fix. I forgot to include this in the above:

This keeps the window from drifting off center, a flaw in the Nvidia OpenGL drivers.
AppActivate in gl_vidnt.c wrote: if (fActive) {
if (modestate == MS_FULLDIB) {
IN_ActivateMouse ();
IN_HideMouse ();
if (vid_canalttab && vid_wassuspended) {
vid_wassuspended = false;
ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
ShowWindow(mainwindow, SW_SHOWNORMAL);

// Baker 3.80x - Fix for alt-tab bug in NVidia drivers from JoeQuake
MoveWindow (mainwindow, 0, 0, gdevmode.dmPelsWidth, gdevmode.dmPelsHeight, false);

}
} else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game) {
IN_ActivateMouse ();
IN_HideMouse ();
}
}
THE END
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

'uknown command: toggle'.

other than that, an ATI driver will 90% bug on you. Not instantly, but perhaps after a few map changes.
Run it windowed and just change the framebuffer size, and the next textures that are loaded (next map?) will be corrupted.

This is the method that carmack reported that *all* cards bugged out on in one way or another.

A more reliable way is to compleatly shut down the opengl renderer, and create a fresh new context. You'll need to load new textures, but quake doesn't really use anything that matters.
metlslime
Posts: 316
Joined: Tue Feb 05, 2008 11:03 pm

Post by metlslime »

Spike wrote:This is the method that carmack reported that *all* cards bugged out on in one way or another. A more reliable way is to compleatly shut down the opengl renderer, and create a fresh new context.
Baker, I think Spike is referring to the bug you yourself reported to me, where your (Intel?) card would report "wglMakeCurrent failed" when you tried to switch just resolution, but it worked if you also changed color depth. I sent you a patch that addressed it, but as you mentioned above, you can't really create a new context without a good way to reload textures, which isn't available in stock glquake.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

Spike wrote:'uknown command: toggle'.
Oversight. That's right, the FitzQuake fullscreen vs. windowed mode menu uses the toggle command and I didn't change it or add it in.

Must fix tutorial. Thanks for the heads up.

I tested from the console and then did a quick and dirty menu test but didn't think to try to fullscreen ON/OFF in the menu.
other than that, an ATI driver will 90% bug on you. Not instantly, but perhaps after a few map changes.
Run it windowed and just change the framebuffer size, and the next textures that are loaded (next map?) will be corrupted.

This is the method that carmack reported that *all* cards bugged out on in one way or another.

A more reliable way is to compleatly shut down the opengl renderer, and create a fresh new context. You'll need to load new textures, but quake doesn't really use anything that matters.
I don't have a machine with an ATI card to test, but I'll research the above more and see if I can do it "right" next the time I get a chance.
metlslime wrote:Baker, I think Spike is referring to the bug you yourself reported to me, where your (Intel?) card would report "wglMakeCurrent failed" when you tried to switch just resolution, but it worked if you also changed color depth. I sent you a patch that addressed it, but as you mentioned above, you can't really create a new context without a good way to reload textures, which isn't available in stock glquake.
Sometime I'll have more time to finish studying the FitzQuake texture manager and incorporate the "re-use context" patch.

I know the above isn't absolutely perfect yet (aside from the accidental incorporation of the toggle command, which I will fix).

/By the way, the machine with the "wglMakeCurrent failed" issue was a GeForce Go 6150, not an Intel.
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Post by ceriux »

hey i went to do this tutorial, but all the things you said to replace or what ever were already done when i used your download files. but the thing is, my console looks weird now...
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

ceriux wrote:hey i went to do this tutorial, but all the things you said to replace or what ever were already done when i used your download files. but the thing is, my console looks weird now...
GLQuake as it is (was) is not really a good engine to mod.

You'll have to fix 50 things before you get it to be "decent" or maybe just 10-12 if you want it to be merely "ok".

Why not use FitzQuake 0.85 as a starting point --- it already has this kind of feature too while retaining stock GLQuake compatibility from all other aspects?
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Post by ceriux »

hmm sounds like a plan. is it setup and ready to compile? (also can you provide me with a list of current features and fixes already implemented please?)
leileilol
Posts: 2783
Joined: Fri Oct 15, 2004 3:23 am

Post by leileilol »

ceriux wrote: can you provide me with a list of current features and fixes
What happened to reading the README files these days?
i should not be here
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Post by ceriux »

lol didnt know it was in there. i dont read readme's usually .

c++ express says it needs to convert fitz's source. i hit yes. nothing happens..
Post Reply