Exemple #1
0
/*
===========
IN_Init
===========
*/
void IN_Init (void)
{
	int MajorVersion = 0, MinorVersion = 0;
	qboolean DGA = false;

	Cvar_RegisterVariable (&m_filter, NULL);

	Cmd_AddCommand ("force_centerview", Force_CenterView_f);

	if (COM_CheckParm ("-nomouse"))
		mouse_available = false;
	else
		mouse_available = true;

	mouse_grab_active = false;
	dga_mouse_available = false;
	dga_mouse_active = false;

/*	if (COM_CheckParm ("-nokeyb"))
		keyboard_available = false;
	else
*/		keyboard_available = true;

	keyboard_grab_active = false;
	dga_keyboard_available = false;
	dga_keyboard_active = false;

	if (x_disp == NULL)
		Sys_Error ("IN_Init: x_disp not initialised before input...");

	DGA = XF86DGAQueryVersion(x_disp, &MajorVersion, &MinorVersion);

	if(COM_CheckParm("-nodga"))
	{
		Con_Warning ("XFree86 DGA extension disabled at command line\n");
	}
	else if (DGA) 
	{
		Con_Printf ("XFree86 DGA extension version %d.%d found\n", MajorVersion, MinorVersion);

		if (COM_CheckParm("-nodgamouse"))
			Con_Warning ("XFree86 DGA Mouse disabled at command line\n");
		else
			dga_mouse_available = true;

		if (COM_CheckParm("-nodgakeyb"))
			Con_Warning ("XFree86 DGA Keyboard disabled at command line\n");
		else
			dga_keyboard_available = true;
	}
	else
	{
		Con_Warning ("XFree86 DGA extension not supported\n");
	}

	IN_GrabMouse(); // grab mouse first!
	IN_GrabKeyboard();
}
Exemple #2
0
void IN_StartupJoystick (void)
{
	int i;
	int nummappings;
	char controllerdb[MAX_OSPATH];
	SDL_GameController *gamecontroller;
	
	if (COM_CheckParm("-nojoy"))
		return;
	
	if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1 )
	{
		Con_Warning("could not initialize SDL Game Controller\n");
		return;
	}
	
	// Load additional SDL2 controller definitions from gamecontrollerdb.txt
	q_snprintf (controllerdb, sizeof(controllerdb), "%s/gamecontrollerdb.txt", com_basedir);
	nummappings = SDL_GameControllerAddMappingsFromFile(controllerdb);
	if (nummappings > 0)
		Con_Printf("%d mappings loaded from gamecontrollerdb.txt\n", nummappings);
	
	// Also try host_parms->userdir
	if (host_parms->userdir != host_parms->basedir)
	{
		q_snprintf (controllerdb, sizeof(controllerdb), "%s/gamecontrollerdb.txt", host_parms->userdir);
		nummappings = SDL_GameControllerAddMappingsFromFile(controllerdb);
		if (nummappings > 0)
			Con_Printf("%d mappings loaded from gamecontrollerdb.txt\n", nummappings);
	}

	for (i = 0; i < SDL_NumJoysticks(); i++)
	{
		const char *joyname = SDL_JoystickNameForIndex(i);
		if ( SDL_IsGameController(i) )
		{
			const char *controllername = SDL_GameControllerNameForIndex(i);
			gamecontroller = SDL_GameControllerOpen(i);
			if (gamecontroller)
			{
				Con_Printf("detected controller: %s\n", controllername != NULL ? controllername : "NULL");
				
				joy_active_instaceid = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller));
				joy_active_controller = gamecontroller;
				break;
			}
			else
			{
				Con_Warning("failed to open controller: %s\n", controllername != NULL ? controllername : "NULL");
			}
		}
		else
		{
			Con_Warning("joystick missing controller mappings: %s\n", joyname != NULL ? joyname : "NULL" );
		}
	}
}
void Sky_LoadCloudTexture(const char *cPath)
{
	char				cFileName[PLATFORM_MAX_PATH];
	unsigned int		iWidth,iHeight;
	uint8_t				*bData;

	if(!cPath[0])
		return;

	sprintf(cFileName, "%ssky/%scloud", g_state.cTexturePath, cPath);

	bData = Image_LoadImage(cFileName,&iWidth,&iHeight);
	if(bData)
		gCloudTexture = TexMgr_LoadImage(
			cl.worldmodel,
			cFileName,
			iWidth,iHeight,
			SRC_RGBA,
			bData,
			cFileName,
			0,
			TEXPREF_ALPHA);
	else
	{
		Con_Warning("Failed to load %s!\n",cFileName);
		return;
	}
}
void Window_UpdateVideo(void)
{
	if (Video.msaa_samples != cv_video_msaasamples.iValue)
	{
		// TODO: Destroy window etc.

		Video.msaa_samples = cv_video_msaasamples.iValue;
	}

	SDL_SetWindowSize(sMainWindow, Video.iWidth, Video.iHeight);

	if (Video.vertical_sync != cv_video_verticlesync.bValue)
	{
		SDL_GL_SetSwapInterval(cv_video_verticlesync.iValue);

		Video.vertical_sync = cv_video_verticlesync.bValue;
	}

	if (Video.fullscreen != cv_video_fullscreen.bValue)
	{
		if (SDL_SetWindowFullscreen(sMainWindow, (SDL_bool)cv_video_fullscreen.bValue) == -1)
		{
			Con_Warning("Failed to set window mode!\n%s", SDL_GetError());

			// Reset the variable to the current value.
			Cvar_SetValue(cv_video_fullscreen.name, Video.fullscreen);
		}
		else
			Video.fullscreen = cv_video_fullscreen.bValue;
	}

	if (!cv_video_fullscreen.value)
		// Center the window, to ensure it's not off screen.
		SDL_SetWindowPosition(sMainWindow, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
}
Exemple #5
0
/*
===========
IN_GrabMouse
===========
*/
void IN_GrabMouse (void)
{
	if (mouse_available && !mouse_grab_active && x_win)
	{
		XWindowAttributes attribs_1;
		XSetWindowAttributes attribs_2;

		XGetWindowAttributes(x_disp, x_win, &attribs_1);
		attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK;
		XChangeWindowAttributes(x_disp, x_win, CWEventMask, &attribs_2);

		// hide cursor
		XDefineCursor(x_disp, x_win, CreateNullCursor());
		// grab pointer
		XGrabPointer(x_disp, x_win, True, 0, GrabModeAsync, GrabModeAsync, x_win, None, CurrentTime);

		if (dga_mouse_available)
		{
			if (!vidmode_fullscreen && (vid.width < 640 || vid.height < 480))
				Con_Warning ("Running low-res windowed mode, XFree86 DGA Mouse disabled\n");
			else
				IN_ActivateDGAMouse();

		}

		mouse_grab_active = true;
	}
}
void _Material_AddSkin(Material_t *mCurrentMaterial, MaterialFunctionContext_t mftContext, char *cArg)
{
	// Proceed to the next line.
	Script_GetToken(true);

	if (cToken[0] == '{')
	{
		while (true)
		{
			if (!Script_GetToken(true))
			{
				Con_Warning("End of field without closing brace! (%s) (%i)\n", mCurrentMaterial->cPath, iScriptLine);
				break;
			}

			material_currentcontext = MATERIAL_FUNCTION_SKIN;

			if (cToken[0] == '}')
			{
				mCurrentMaterial->iSkins++;
				break;
			}
			// '$' declares that the following is a function.
			else if (cToken[0] == SCRIPT_SYMBOL_FUNCTION)
				Material_CheckFunctions(mCurrentMaterial);
			// '%' declares that the following is a variable.
			else if (cToken[0] == SCRIPT_SYMBOL_VARIABLE)
			{
				/*	TODO:
				* Collect variable
				* Check it against internal solutions
				* Otherwise declare it, figure out where/how it's used
				*/
			}
			else
			{
				Con_Warning("Invalid field! (%s) (%i)\n", mCurrentMaterial->cPath, iScriptLine);
				break;
			}
		}
	}
	else
		Con_Warning("Invalid skin, no opening brace! (%s) (%i)\n", mCurrentMaterial->cPath, iScriptLine);
}
bool Material_Precache(const char *ccPath)
{
	Material_t *mNewMaterial;

	mNewMaterial = Material_Load(ccPath);
	if (!mNewMaterial)
	{
		Con_Warning("Failed to load material! (%s)\n", ccPath);
		return false;
	}

	return true;
}
sfxcache_t *S_LoadSound (sfx_t *s)
{
    char		namebuffer[512];
	wavinfo_t	info;
	int			len;
	float		stepscale;
	sfxcache_t	*sc;

	// see if still in memory
	sc = (sfxcache_t*)Cache_Check(&s->cache);
	if(sc)
		return sc;

	// load it in
	strncpy(namebuffer, g_state.cSoundPath, sizeof(namebuffer));
	strcat(namebuffer, s->name);

	uint8_t *data = (uint8_t*)COM_LoadHeapFile(namebuffer);
	if (!data)
	{
		Con_Warning("Couldn't load %s\n", namebuffer);
		return NULL;
	}

	info = GetWavinfo (s->name, data, com_filesize);

	stepscale = (float)info.rate / shm->speed;
	len = info.samples / stepscale;

	len = len * info.width * info.channels;

	sc = (sfxcache_t*)Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name);
	if (!sc)
	{
		free(data);
		return NULL;
	}

	sc->length = info.samples;
	sc->loopstart = info.loopstart;
	sc->speed = info.rate;
	sc->width = info.width;
	sc->stereo = info.channels;

	ResampleSfx (s, sc->speed, sc->width, data + info.dataofs);

	free(data);

	return sc;
}
void _Material_SetTextureEnvironmentMode(Material_t *Material, MaterialFunctionContext_t Context, char *cArg)
{
	MaterialSkin_t *sCurrentSkin;
	sCurrentSkin = Material_GetSkin(Material, Material->iSkins);
	
	int i;
	for (i = 0; i < pARRAYELEMENTS(EnvironmentModes); i++)
		if (!strncmp(EnvironmentModes[i].ccVarName, cArg, strlen(EnvironmentModes[i].ccVarName)))
		{
			sCurrentSkin->mtTexture[sCurrentSkin->uiTextures].EnvironmentMode = EnvironmentModes[i].Mode;
			return;
		}

	Con_Warning("Invalid texture environment mode! (%s) (%s)\n", cArg, Material->cName);
}
sfxcache_t *S_LoadSound (sfx_t *s)
{
    char		namebuffer[512];
	byte		*data;
	wavinfo_t	info;
	int			len;
	float		stepscale;
	sfxcache_t	*sc;
	byte		stackbuf[1*1024];		// avoid dirtying the cache heap

	// see if still in memory
	sc = (sfxcache_t*)Cache_Check(&s->cache);
	if(sc)
		return sc;

	// load it in
	Q_strcpy(namebuffer,Global.cSoundPath);
    Q_strcat(namebuffer,s->name);

	data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf));
	if (!data)
	{
		Con_Warning("Couldn't load %s\n", namebuffer);
		return NULL;
	}

	info = GetWavinfo (s->name, data, com_filesize);

	stepscale = (float)info.rate / shm->speed;
	len = info.samples / stepscale;

	len = len * info.width * info.channels;

	sc = (sfxcache_t*)Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name);
	if (!sc)
		return NULL;

	sc->length = info.samples;
	sc->loopstart = info.loopstart;
	sc->speed = info.rate;
	sc->width = info.width;
	sc->stereo = info.channels;

	ResampleSfx (s, sc->speed, sc->width, data + info.dataofs);

	return sc;
}
void R_CheckEfrags (void)
{
	efrag_t		*ef;
	int			count;

	if (cls.signon < 2)
		return; //don't spam when still parsing signon packet full of static ents

	for (count=MAX_EFRAGS, ef = cl.free_efrags; ef; count--, ef = ef->entnext)
		;

	if (count > 640 && dev_peakstats.efrags <= 640)
		Con_Warning ("%i efrags exceeds standard limit of 640.\n", count);

	dev_stats.efrags = count;
	dev_peakstats.efrags = Math_Max(count,dev_peakstats.efrags);
}
Exemple #12
0
Material_t *Material_GetByPath(const char *ccPath)
{
	int i;

	if(ccPath[0] == ' ')
	{
		Con_Warning("Attempted to find material, but recieved invalid path!\n");
		return NULL;
	}
	
	for (i = 0; i < iMaterialCount; i++)
		if (mMaterials[i].cPath[0])
			if (!strncmp(mMaterials[i].cPath, ccPath, sizeof(mMaterials[i].cPath)))
				return &mMaterials[i];

	return NULL;
}
Exemple #13
0
/*	Returns true on success.
	Unfinished
*/
Material_t *Material_GetByName(const char *ccMaterialName)
{
	int i;

	if(ccMaterialName[0] == ' ')
	{
		Con_Warning("Attempted to find material, but recieved invalid material name!\n");
		return NULL;
	}

	for (i = 0; i < iMaterialCount; i++)
		// If the material has no name, then it's not valid.
		if (mMaterials[i].cName[0])
			if (!strncmp(mMaterials[i].cName, ccMaterialName, sizeof(mMaterials[i].cName)))
				return &mMaterials[i];

	return NULL;
}
Exemple #14
0
/*
===========
IN_GrabKeyboard
===========
*/
void IN_GrabKeyboard (void)
{
	if (keyboard_available && !keyboard_grab_active && x_win)
	{
		// grab keyboard
		XGrabKeyboard(x_disp, x_win, False, GrabModeAsync, GrabModeAsync, CurrentTime);

		if (dga_keyboard_available)
		{
			if (!vidmode_fullscreen && (vid.width < 640 || vid.height < 480))
				Con_Warning ("Running low-res windowed mode, XFree86 DGA Keyboard disabled\n");
			else
				IN_ActivateDGAKeyboard();
		}

		keyboard_grab_active = true;
	}
}
void SV_CheckAllEnts (void)
{
	int			e;
	edict_t		*check;

	// See if any solid entities are inside the final position
	check = NEXT_EDICT(sv.edicts);
	for(e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT(check))
	{
		if (check->free)
			continue;
		if(	check->v.movetype == MOVETYPE_PUSH	||
			check->v.movetype == MOVETYPE_NONE	||
			check->v.movetype == MOVETYPE_NOCLIP)
			continue;

		if (SV_TestEntityPosition (check))
			Con_Warning("Entity in invalid position!\n");
	}
}
Exemple #16
0
/*	Returns a material from the given ID.
*/
Material_t *Material_Get(int iMaterialID)
{
	int i;

	// The identification would never be less than 0, and never more than our maximum.
	if (iMaterialID < 0 || iMaterialID > MATERIAL_MAX)
	{
		Con_Warning("Invalid material ID! (%i)\n",iMaterialID);
		return NULL;
	}

	for (i = 0; i < iMaterialCount; i++)
		if (mMaterials[i].iIdentification == iMaterialID)
		{
			mMaterials[i].bBind = true;

			return &mMaterials[i];
		}

	return NULL;
}
Exemple #17
0
void _Material_SetType(Material_t *mCurrentMaterial, MaterialFunctionContext_t mftContext, char *cArg)
{
	switch (mftContext)
	{
	case MATERIAL_FUNCTION_SKIN:
	{
		int	iMaterialType = Q_atoi(cArg);

		// Ensure that the given type is valid.
		if ((iMaterialType < MATERIAL_TYPE_NONE) || (iMaterialType >= MATERIAL_TYPE_MAX))
			Con_Warning("Invalid material type! (%i)\n", iMaterialType);

		mCurrentMaterial->msSkin[mCurrentMaterial->iSkins].uiType = iMaterialType;
	}
	break;
	case MATERIAL_FUNCTION_TEXTURE:
		_Material_SetTextureType(mCurrentMaterial, mftContext, cArg);
		break;
	default:
		Sys_Error("Invalid context!\n");
	}
}
void SCR_ScreenShot_f (void)
{
	uint8_t	*buffer;
	char	tganame[32], checkname[PLATFORM_MAX_PATH];
	int		i;

	if (!plCreateDirectory(va("%s/%s", com_gamedir, g_state.cScreenshotPath)))
		Sys_Error("Failed to create directory!\n%s", plGetError());

	// find a file name to save it to
	for (i = 0; i < 10000; i++)
	{
		sprintf(tganame, "%s%04i.tga", g_state.cScreenshotPath, i);
		sprintf(checkname,"%s/%s",com_gamedir,tganame);
		if(Sys_FileTime(checkname) == -1)
			break;	// file doesn't exist
	}

	if(i >= 10000)
	{
		Con_Printf ("SCR_ScreenShot_f: Couldn't find an unused filename\n");
		return;
	}

	//get data
	buffer = (uint8_t*)malloc(glwidth*glheight*3);
	glReadPixels(glx,gly,glwidth,glheight,GL_RGB,GL_UNSIGNED_BYTE,buffer);

	// now write the file
	if(Image_WriteTGA(tganame,buffer,glwidth,glheight,24,false))
		Con_Printf("Wrote %s\n",tganame);
	else
		Con_Warning("Failed to write %s\n",tganame);

	free (buffer);
}
Exemple #19
0
/*	Set flags for the material.
*/
void _Material_SetFlags(Material_t *mCurrentMaterial, MaterialFunctionContext_t mftContext, char *cArg)
{
	int	i;

	// Search through and copy each flag into the materials list of flags.
	for (i = 0; i < pARRAYELEMENTS(mfMaterialFlags); i++)
	{
		if (strstr(cArg, mfMaterialFlags[i].ccName))
		{
			if (mfMaterialFlags[i].mftContext != mftContext)
				continue;

			switch (mftContext)
			{
			case MATERIAL_FUNCTION_MATERIAL:
				if (mfMaterialFlags[i].flags == MATERIAL_FLAG_ANIMATED)
				{
					mCurrentMaterial->iAnimationFrame = 0;
					mCurrentMaterial->dAnimationTime = 0;
				}

				mCurrentMaterial->iFlags |= mfMaterialFlags[i].flags;
				break;
			case MATERIAL_FUNCTION_SKIN:
				mCurrentMaterial->msSkin[mCurrentMaterial->iSkins].uiFlags |= mfMaterialFlags[i].flags;
				break;
			case MATERIAL_FUNCTION_TEXTURE:
				mCurrentMaterial->msSkin[mCurrentMaterial->iSkins].mtTexture
					[mCurrentMaterial->msSkin[mCurrentMaterial->iSkins].uiTextures].uiFlags |= mfMaterialFlags[i].flags;
				break;
			default:
				Con_Warning("Invalid context! (%s) (%s) (%i)\n", mCurrentMaterial->cName, mfMaterialFlags[i].ccName, mftContext);
			}
		}
	}
}
Exemple #20
0
void Material_CheckFunctions(Material_t *mNewMaterial)
{
	MaterialKey_t *mKey;

	// Find the related function.
	for (mKey = MaterialFunctions; mKey->cKey; mKey++)
		// Remain case sensitive.
		if (!Q_strcasecmp(mKey->cKey, cToken + 1))
		{
			/*	todo
				account for texture slots etc
			*/
			if ((mKey->mftType != MATERIAL_FUNCTION_UNIVERSAL) && (material_currentcontext != mKey->mftType))
				Sys_Error("Attempted to call a function within the wrong context! (%s) (%s) (%i)\n", 
					cToken, mNewMaterial->cPath, iScriptLine);

			Script_GetToken(false);

			mKey->Function(mNewMaterial, material_currentcontext, cToken);
			return;
		}

	Con_Warning("Unknown function! (%s) (%s) (%i)\n", cToken, mNewMaterial->cPath, iScriptLine);
}
Exemple #21
0
static void GL_CheckExtensions (void)
{
	int swap_control;

	//
	// multitexture
	//
	if (COM_CheckParm("-nomtex"))
		Con_Warning ("Mutitexture disabled at command line\n");
	else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_multitexture"))
	{
		GL_MTexCoord2fFunc = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
		GL_SelectTextureFunc = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
		if (GL_MTexCoord2fFunc && GL_SelectTextureFunc)
		{
			Con_Printf("FOUND: ARB_multitexture\n");
			TEXTURE0 = GL_TEXTURE0_ARB;
			TEXTURE1 = GL_TEXTURE1_ARB;
			gl_mtexable = true;
		}
		else
		{
			Con_Warning ("Couldn't link to multitexture functions\n");
		}
	}
	else if (GL_ParseExtensionList(gl_extensions, "GL_SGIS_multitexture"))
	{
		GL_MTexCoord2fFunc = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMTexCoord2fSGIS");
		GL_SelectTextureFunc = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glSelectTextureSGIS");
		if (GL_MTexCoord2fFunc && GL_SelectTextureFunc)
		{
			Con_Printf("FOUND: SGIS_multitexture\n");
			TEXTURE0 = TEXTURE0_SGIS;
			TEXTURE1 = TEXTURE1_SGIS;
			gl_mtexable = true;
		}
		else
		{
			Con_Warning ("Couldn't link to multitexture functions\n");
		}
	}
	else
	{
		Con_Warning ("multitexture not supported (extension not found)\n");
	}

	//
	// texture_env_combine
	//
	if (COM_CheckParm("-nocombine"))
		Con_Warning ("texture_env_combine disabled at command line\n");
	else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_env_combine"))
	{
		Con_Printf("FOUND: ARB_texture_env_combine\n");
		gl_texture_env_combine = true;
	}
	else if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_env_combine"))
	{
		Con_Printf("FOUND: EXT_texture_env_combine\n");
		gl_texture_env_combine = true;
	}
	else
	{
		Con_Warning ("texture_env_combine not supported\n");
	}

	//
	// texture_env_add
	//
	if (COM_CheckParm("-noadd"))
		Con_Warning ("texture_env_add disabled at command line\n");
	else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_env_add"))
	{
		Con_Printf("FOUND: ARB_texture_env_add\n");
		gl_texture_env_add = true;
	}
	else if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_env_add"))
	{
		Con_Printf("FOUND: EXT_texture_env_add\n");
		gl_texture_env_add = true;
	}
	else
	{
		Con_Warning ("texture_env_add not supported\n");
	}

	//
	// swap control (the "after SDL_SetVideoMode" part)
	//
	if (!gl_swap_control)
	{
		Con_Warning ("vertical sync not supported (SDL_GL_SetAttribute failed)\n");
	}
	else if (SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &swap_control) == -1)
	{
		gl_swap_control = false;
		Con_Warning ("vertical sync not supported (SDL_GL_GetAttribute failed)\n");
	}
	else if ((vid_vsync.value && swap_control != 1) || (!vid_vsync.value && swap_control != 0))
	{
		gl_swap_control = false;
		Con_Warning ("vertical sync not supported (swap_control doesn't match vid_vsync)\n");
	}
	else
	{
		Con_Printf("FOUND: SDL_GL_SWAP_CONTROL\n");
	}

	//
	// anisotropic filtering
	//
	if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_filter_anisotropic"))
	{
		float test1,test2;
		GLuint tex;

		// test to make sure we really have control over it
		// 1.0 and 2.0 should always be legal values
		glGenTextures(1, &tex);
		glBindTexture (GL_TEXTURE_2D, tex);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
		glGetTexParameterfv (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test1);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
		glGetTexParameterfv (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test2);
		glDeleteTextures(1, &tex);

		if (test1 == 1 && test2 == 2)
		{
			Con_Printf("FOUND: EXT_texture_filter_anisotropic\n");
			gl_anisotropy_able = true;
		}
		else
		{
			Con_Warning ("anisotropic filtering locked by driver. Current driver setting is %f\n", test1);
		}

		//get max value either way, so the menu and stuff know it
		glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max_anisotropy);
		if (gl_max_anisotropy < 2)
		{
			gl_anisotropy_able = false;
			gl_max_anisotropy = 1;
			Con_Warning ("anisotropic filtering broken: disabled\n");
		}
	}
	else
	{
		gl_max_anisotropy = 1;
		Con_Warning ("texture_filter_anisotropic not supported\n");
	}
}
Exemple #22
0
/*  
==================
SV_StartSound

Each entity can have eight independant sound sources, like voice,
weapon, feet, etc.

Channel 0 is an auto-allocate channel, the others override anything
already running on that entity/channel pair.

An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off.  (max 4 attenuation)

==================
*/  
void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation)
{       
	int         sound_num;
	int			field_mask;
	int			i;
	int			ent;
	static float lastmsg = 0;

	if (volume < 0 || volume > 255)
	{
		Con_Warning ("SV_StartSound: volume = %d, max = %d\n", volume, 255);
		volume = CLAMP(0, volume, 255);
	}
	if (attenuation < 0 || attenuation > 4)
	{
		Con_Warning ("SV_StartSound: attenuation = %f, max = %d\n", attenuation, 4);
		attenuation = CLAMP(0, attenuation, 4);
	}
	if (channel < 0 || channel > 7)
	{
		Con_Warning ("SV_StartSound: channel = %i, max = %d\n", channel, 7);
		channel = CLAMP(0, channel, 7);
	}

// drop silently if there is no room
	if (sv.datagram.cursize > ((sv.protocol == PROTOCOL_NETQUAKE) ? 1024 : MAX_DATAGRAM) - 16)
		return;	

// find precache number for sound
	for (sound_num=1 ; sound_num<MAX_SOUNDS && sv.sound_precache[sound_num] ; sound_num++)
		if (!strcmp(sample, sv.sound_precache[sound_num]))
			break;

	if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
	{
		if (IsTimeout (&lastmsg, 2))
		{
			// let's not upset and annoy the user
			Con_DPrintf ("SV_StartSound: %s not precacheed\n", sample);
		}
		return;
	}

	ent = NUM_FOR_EDICT(entity);

	field_mask = 0;
	if (volume != DEFAULT_SOUND_PACKET_VOLUME)
		field_mask |= SND_VOLUME;
	if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
		field_mask |= SND_ATTENUATION;

	//johnfitz -- PROTOCOL_FITZQUAKE
	if (ent >= 8192)
	{
		if (sv.protocol == PROTOCOL_FITZQUAKE || sv.protocol == PROTOCOL_MARKV || sv.protocol == PROTOCOL_RMQ)
			field_mask |= SND_LARGEENTITY;
		else
			return; // don't send any info protocol can't support
	}
	if (sound_num >= 256 || channel >= 8)
	{
		if (sv.protocol == PROTOCOL_FITZQUAKE || sv.protocol == PROTOCOL_MARKV || sv.protocol == PROTOCOL_RMQ)
			field_mask |= SND_LARGESOUND;
		else
			return; // don't send any info protocol can't support
	}
	//johnfitz

// directed messages go only to the entity the are targeted on
	MSG_WriteByte (&sv.datagram, svc_sound);
	MSG_WriteByte (&sv.datagram, field_mask);
	if (field_mask & SND_VOLUME)
		MSG_WriteByte (&sv.datagram, volume);
	if (field_mask & SND_ATTENUATION)
		MSG_WriteByte (&sv.datagram, attenuation*64);
	
	//johnfitz -- PROTOCOL_FITZQUAKE
	if (field_mask & SND_LARGEENTITY)
	{
		MSG_WriteShort (&sv.datagram, ent);
		MSG_WriteByte (&sv.datagram, channel);
	}
	else
		MSG_WriteShort (&sv.datagram, (ent<<3) | channel);

	if (field_mask & SND_LARGESOUND)
		MSG_WriteShort (&sv.datagram, sound_num);
	else
		MSG_WriteByte (&sv.datagram, sound_num);
	//johnfitz

	for (i=0 ; i<3 ; i++)
		MSG_WriteCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]), sv.protocolflags);
}           
Exemple #23
0
int	Datagram_GetMessage (qsocket_t *sock)
{
	unsigned int	length;
	unsigned int	flags;
	int				ret = 0;
	struct qsockaddr readaddr;
	unsigned int	sequence;
	unsigned int	count;

	if (!sock->canSend)
		if ((net_time - sock->lastSendTime) > 1.0)
			ReSendMessage (sock);

	while(1)
	{	
		length = sock->landriver->Read(sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr);
/*
		// for testing packet loss effects
		if ((rand() & 255) > 220)
			continue;
*/
		if (length == 0)
			break;

		if ((int)length == -1)
		{
			Con_Printf("Read error\n");
			return -1;
		}

		// added !sock->net_wait (NAT fix)
		if (!sock->net_wait && sock->landriver->AddrCompare(&readaddr, &sock->addr) != 0)
		{
#ifdef DEBUG
			Con_DPrintf("Forged packet received\n");
			Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
			Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
#endif
			continue;
		}

		if (length < NET_HEADERSIZE)
		{
			shortPacketCount++;
			continue;
		}

		length = BigLong(packetBuffer.length);
		flags = length & (~NETFLAG_LENGTH_MASK);
		length &= NETFLAG_LENGTH_MASK;

		// ProQuake extra protection
		if (length > NET_DATAGRAMSIZE)
		{
			Con_Warning ("Datagram_GetMessage: excessive datagram length (%d, max = %d)\n", length, NET_DATAGRAMSIZE);
			return -1;
		}

		if (flags & NETFLAG_CTL)
			continue;

		sequence = BigLong(packetBuffer.sequence);
		packetsReceived++;

		// NAT fix
		if (sock->net_wait)
		{
			sock->addr = readaddr;
			strcpy(sock->address, sock->landriver->AddrToString(&readaddr));
			sock->net_wait = false;
		}

		if (flags & NETFLAG_UNRELIABLE)
		{
			if (sequence < sock->unreliableReceiveSequence)
			{
				Con_DPrintf("Got a stale datagram\n");
				ret = 0;
				break;
			}
			if (sequence != sock->unreliableReceiveSequence)
			{
				count = sequence - sock->unreliableReceiveSequence;
				droppedDatagrams += count;
				Con_DPrintf("Dropped %u datagram(s)\n", count);
			}
			sock->unreliableReceiveSequence = sequence + 1;

			length -= NET_HEADERSIZE;

			SZ_Clear (net_message->message);
			SZ_Write (net_message->message, packetBuffer.data, length);

			ret = 2;
			break;
		}

		if (flags & NETFLAG_ACK)
		{
			if (sequence != (sock->sendSequence - 1))
			{
				Con_DPrintf("Stale ACK received\n");
				continue;
			}
			if (sequence == sock->ackSequence)
			{
				sock->ackSequence++;
				if (sock->ackSequence != sock->sendSequence)
					Con_DPrintf("ack sequencing error\n");
			}
			else
			{
				Con_DPrintf("Duplicate ACK received\n");
				continue;
			}
			sock->sendMessageLength -= MAX_DATAGRAM;
			if (sock->sendMessageLength > 0)
			{
				// FIXME: was memcpy
				memmove(sock->sendMessage, sock->sendMessage + MAX_DATAGRAM, sock->sendMessageLength);
				sock->sendNext = true;
			}
			else
			{
				sock->sendMessageLength = 0;
				sock->canSend = true;
			}
			continue;
		}

		if (flags & NETFLAG_DATA)
		{
			packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK);
			packetBuffer.sequence = BigLong(sequence);
			sock->landriver->Write(sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr);

			if (sequence != sock->receiveSequence)
			{
				receivedDuplicateCount++;
				continue;
			}
			sock->receiveSequence++;

			length -= NET_HEADERSIZE;

			if (flags & NETFLAG_EOM)
			{
				SZ_Clear(net_message->message);
				SZ_Write(net_message->message, sock->receiveMessage, sock->receiveMessageLength);
				SZ_Write(net_message->message, packetBuffer.data, length);
				sock->receiveMessageLength = 0;

				ret = 1;
				break;
			}

			memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length);
			sock->receiveMessageLength += length;
			continue;
		}
	}

	if (sock->sendNext)
		SendMessageNext (sock);

	return ret;
}
void Physics_ServerFrame(void)
{
	int		i;
	edict_t	*eEntity;

	// Let the progs know that a new frame has started
	pr_global_struct.self	= EDICT_TO_PROG(sv.edicts);
	pr_global_struct.eOther	= sv.edicts;

	// TODO: should we pass the time to this? ~hogsy
	Game->Server_StartFrame();

	// Treat each object in turn
	eEntity = sv.edicts;
	for(i = 0; i < sv.num_edicts; i++,eEntity = NEXT_EDICT(eEntity))
	{
		if(eEntity->free)
			continue;

		if(pr_global_struct.force_retouch)
			SV_LinkEdict(eEntity,true);	// Force retouch even for stationary

		// [11/7/2013] Cleaned this up and gave it its own function ~hogsy
		Game->Server_EntityFrame(eEntity);

		if(i > 0 && i <= svs.maxclients)
			SV_Physics_Client(eEntity,i);
		else
		{
			switch(eEntity->v.movetype)
			{
			case MOVETYPE_NONE:
				Server_RunThink(eEntity);
				break;
			case MOVETYPE_PUSH:
				SV_Physics_Pusher(eEntity);
				break;
			case MOVETYPE_NOCLIP:
				Physics_NoClip(eEntity);
				break;
			case MOVETYPE_WALK:
			case MOVETYPE_STEP:
				Game->Physics_CheckVelocity(eEntity);
				Game->Physics_SetGravity(eEntity);

				Physics_AddFriction(eEntity,eEntity->v.velocity,eEntity->v.origin);

				SV_WalkMove(eEntity);
				SV_LinkEdict(eEntity,true);

				Server_RunThink(eEntity);
				break;
			case MOVETYPE_TOSS:
			case MOVETYPE_BOUNCE:
			case MOVETYPE_FLY:
			case MOVETYPE_FLYMISSILE:
			case MOVETYPE_FLYBOUNCE:
				Physics_Toss(eEntity);
				break;
			default:
				Con_Warning("Bad movetype set for entity! (%s)",eEntity->v.cClassname);
			}
		}
	}

	if(pr_global_struct.force_retouch)
		pr_global_struct.force_retouch--;

	sv.time += host_frametime;
}
void Sky_LoadSkyBox (char *name)
{
	int		i, mark;
	unsigned int width, height;
	char	filename[PLATFORM_MAX_PATH];
	bool	bNoneFound = true;
	uint8_t	*data;

	if(strcmp(cSkyBoxName, name) == 0)
		return; //no change

	// Purge old textures
	for(i = 0; i < 6; i++)
	{
		if(gSkyBoxTexture[i] && gSkyBoxTexture[i] != notexture)
			TexMgr_FreeTexture(gSkyBoxTexture[i]);

		gSkyBoxTexture[i] = NULL;
	}

	// Turn off skybox if sky is set to ""
	if(name[0] == 0)
	{
		cSkyBoxName[0] = 0;
		return;
	}

	// Load textures
	for (i=0; i<6; i++)
	{
		mark = Hunk_LowMark ();

		sprintf(filename, "%ssky/%s%s", g_state.cTexturePath, name, suf[i]);
		data = Image_LoadImage (filename, &width, &height);
		if (data)
		{
			gSkyBoxTexture[i] = TexMgr_LoadImage (cl.worldmodel, filename, width, height, SRC_RGBA, data, filename, 0, TEXPREF_NONE);
			bNoneFound = false;
		}
		else
		{
			Con_Warning("Couldn't load %s\n", filename);
			gSkyBoxTexture[i] = notexture;
		}

		Hunk_FreeToLowMark (mark);
	}

	if(bNoneFound) // go back to scrolling sky if skybox is totally missing
	{
		for(i = 0; i < 6; i++)
		{
			if(gSkyBoxTexture[i] && gSkyBoxTexture[i] != notexture)
				TexMgr_FreeTexture(gSkyBoxTexture[i]);

			gSkyBoxTexture[i] = NULL;
		}
		cSkyBoxName[0] = 0;
		return;
	}

	strcpy(cSkyBoxName, name);
}
/*
=====================
CL_ParseServerMessage
=====================
*/
void CL_ParseServerMessage (void)
{
	int			cmd;
	int			i;
	const char		*str; //johnfitz
	int			total, j, lastcmd; //johnfitz

//
// if recording demos, copy the message out
//
	if (cl_shownet.value == 1)
		Con_Printf ("%i ",net_message.cursize);
	else if (cl_shownet.value == 2)
		Con_Printf ("------------------\n");

	cl.onground = false;	// unless the server says otherwise
//
// parse the message
//
	MSG_BeginReading ();

	lastcmd = 0;
	while (1)
	{
		if (msg_badread)
			Host_Error ("CL_ParseServerMessage: Bad server message");

		cmd = MSG_ReadByte ();

		if (cmd == -1)
		{
			SHOWNET("END OF MESSAGE");
			return;		// end of message
		}

	// if the high bit of the command byte is set, it is a fast update
		if (cmd & U_SIGNAL) //johnfitz -- was 128, changed for clarity
		{
			SHOWNET("fast update");
			CL_ParseUpdate (cmd&127);
			continue;
		}

		SHOWNET(svc_strings[cmd]);

	// other commands
		switch (cmd)
		{
		default:
			Host_Error ("Illegible server message, previous was %s\n", svc_strings[lastcmd]); //johnfitz -- added svc_strings[lastcmd]
			break;

		case svc_nop:
		//	Con_Printf ("svc_nop\n");
			break;

		case svc_time:
			cl.mtime[1] = cl.mtime[0];
			cl.mtime[0] = MSG_ReadFloat ();
			break;

		case svc_clientdata:
			CL_ParseClientdata (); //johnfitz -- removed bits parameter, we will read this inside CL_ParseClientdata()
			break;

		case svc_version:
			i = MSG_ReadLong ();
			//johnfitz -- support multiple protocols
			if (i != PROTOCOL_NETQUAKE && i != PROTOCOL_FITZQUAKE)
				Host_Error ("Server returned version %i, not %i or %i\n", i, PROTOCOL_NETQUAKE, PROTOCOL_FITZQUAKE);
			cl.protocol = i;
			//johnfitz
			break;

		case svc_disconnect:
			Host_EndGame ("Server disconnected\n");

		case svc_print:
			Con_Printf ("%s", MSG_ReadString ());
			break;

		case svc_centerprint:
			//johnfitz -- log centerprints to console
			str = MSG_ReadString ();
			SCR_CenterPrint (str);
			Con_LogCenterPrint (str);
			//johnfitz
			break;

		case svc_stufftext:
			cls.stufftext_frame = host_framecount;	// allow full frame update
								// in demo playback -- Pa3PyX
			Cbuf_AddText (MSG_ReadString ());
			break;

		case svc_damage:
			V_ParseDamage ();
			break;

		case svc_serverinfo:
			CL_ParseServerInfo ();
			vid.recalc_refdef = true;	// leave intermission full screen
			break;

		case svc_setangle:
			for (i=0 ; i<3 ; i++)
				cl.viewangles[i] = MSG_ReadAngle ();
			break;

		case svc_setview:
			cl.viewentity = MSG_ReadShort ();
			break;

		case svc_lightstyle:
			i = MSG_ReadByte ();
			if (i >= MAX_LIGHTSTYLES)
				Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
			q_strlcpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING);
			cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map);
			//johnfitz -- save extra info
			if (cl_lightstyle[i].length)
			{
				total = 0;
				cl_lightstyle[i].peak = 'a';
				for (j=0; j<cl_lightstyle[i].length; j++)
				{
					total += cl_lightstyle[i].map[j] - 'a';
					cl_lightstyle[i].peak = q_max(cl_lightstyle[i].peak, cl_lightstyle[i].map[j]);
				}
				cl_lightstyle[i].average = total / cl_lightstyle[i].length + 'a';
			}
			else
				cl_lightstyle[i].average = cl_lightstyle[i].peak = 'm';
			//johnfitz
			break;

		case svc_sound:
			CL_ParseStartSoundPacket();
			break;

		case svc_stopsound:
			i = MSG_ReadShort();
			S_StopSound(i>>3, i&7);
			break;

		case svc_updatename:
			Sbar_Changed ();
			i = MSG_ReadByte ();
			if (i >= cl.maxclients)
				Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD");
			q_strlcpy (cl.scores[i].name, MSG_ReadString(), MAX_SCOREBOARDNAME);
			break;

		case svc_updatefrags:
			Sbar_Changed ();
			i = MSG_ReadByte ();
			if (i >= cl.maxclients)
				Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD");
			cl.scores[i].frags = MSG_ReadShort ();
			break;

		case svc_updatecolors:
			Sbar_Changed ();
			i = MSG_ReadByte ();
			if (i >= cl.maxclients)
				Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
			cl.scores[i].colors = MSG_ReadByte ();
			CL_NewTranslation (i);
			break;

		case svc_particle:
			R_ParseParticleEffect ();
			break;

		case svc_spawnbaseline:
			i = MSG_ReadShort ();
			// must use CL_EntityNum() to force cl.num_entities up
			CL_ParseBaseline (CL_EntityNum(i), 1); // johnfitz -- added second parameter
			break;

		case svc_spawnstatic:
			CL_ParseStatic (1); //johnfitz -- added parameter
			break;

		case svc_temp_entity:
			CL_ParseTEnt ();
			break;

		case svc_setpause:
			cl.paused = MSG_ReadByte ();
			if (cl.paused)
			{
				CDAudio_Pause ();
				BGM_Pause ();
			}
			else
			{
				CDAudio_Resume ();
				BGM_Resume ();
			}
			break;

		case svc_signonnum:
			i = MSG_ReadByte ();
			if (i <= cls.signon)
				Host_Error ("Received signon %i when at %i", i, cls.signon);
			cls.signon = i;
			//johnfitz -- if signonnum==2, signon packet has been fully parsed, so check for excessive static ents and efrags
			if (i == 2)
			{
				if (cl.num_statics > 128)
					Con_Warning ("%i static entities exceeds standard limit of 128.\n", cl.num_statics);
				R_CheckEfrags ();
			}
			//johnfitz
			CL_SignonReply ();
			break;

		case svc_killedmonster:
			cl.stats[STAT_MONSTERS]++;
			break;

		case svc_foundsecret:
			cl.stats[STAT_SECRETS]++;
			break;

		case svc_updatestat:
			i = MSG_ReadByte ();
			if (i < 0 || i >= MAX_CL_STATS)
				Sys_Error ("svc_updatestat: %i is invalid", i);
			cl.stats[i] = MSG_ReadLong ();;
			break;

		case svc_spawnstaticsound:
			CL_ParseStaticSound (1); //johnfitz -- added parameter
			break;

		case svc_cdtrack:
			cl.cdtrack = MSG_ReadByte ();
			cl.looptrack = MSG_ReadByte ();
			if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
				BGM_PlayCDtrack ((byte)cls.forcetrack, true);
			else
				BGM_PlayCDtrack ((byte)cl.cdtrack, true);
			break;

		case svc_intermission:
			cl.intermission = 1;
			cl.completed_time = cl.time;
			vid.recalc_refdef = true;	// go to full screen
			break;

		case svc_finale:
			cl.intermission = 2;
			cl.completed_time = cl.time;
			vid.recalc_refdef = true;	// go to full screen
			//johnfitz -- log centerprints to console
			str = MSG_ReadString ();
			SCR_CenterPrint (str);
			Con_LogCenterPrint (str);
			//johnfitz
			break;

		case svc_cutscene:
			cl.intermission = 3;
			cl.completed_time = cl.time;
			vid.recalc_refdef = true;	// go to full screen
			//johnfitz -- log centerprints to console
			str = MSG_ReadString ();
			SCR_CenterPrint (str);
			Con_LogCenterPrint (str);
			//johnfitz
			break;

		case svc_sellscreen:
			Cmd_ExecuteString ("help", src_command);
			break;

		//johnfitz -- new svc types
		case svc_skybox:
			Sky_LoadSkyBox (MSG_ReadString());
			break;

		case svc_bf:
			Cmd_ExecuteString ("bf", src_command);
			break;

		case svc_fog:
			Fog_ParseServerMessage ();
			break;

		case svc_spawnbaseline2: //PROTOCOL_FITZQUAKE
			i = MSG_ReadShort ();
			// must use CL_EntityNum() to force cl.num_entities up
			CL_ParseBaseline (CL_EntityNum(i), 2);
			break;

		case svc_spawnstatic2: //PROTOCOL_FITZQUAKE
			CL_ParseStatic (2);
			break;

		case svc_spawnstaticsound2: //PROTOCOL_FITZQUAKE
			CL_ParseStaticSound (2);
			break;
		//johnfitz
		}

		lastcmd = cmd; //johnfitz
	}
}
/*	Get gamma level.
	Based on the Darkplaces implementation.
*/
void Window_GetGamma(unsigned short *usRamp, int iRampSize)
{
	if (!SDL_GetWindowGammaRamp(sMainWindow, usRamp, usRamp + iRampSize, usRamp + iRampSize * 2))
		Con_Warning("Failed to get gamma level!\n%s", SDL_GetError());
}
void Window_InitializeVideo(void)
{
	int	iFlags =
		SDL_WINDOW_SHOWN |
		SDL_WINDOW_OPENGL |
		SDL_WINDOW_FULLSCREEN;
	SDL_Surface	*sIcon;

	// [28/7/2013] Moved check here and corrected, seems more secure ~hogsy
	if (SDL_VideoInit(NULL) < 0)
		Sys_Error("Failed to initialize video!\n%s\n", SDL_GetError());

	SDL_DisableScreenSaver();

	// Get display information.
	if (SDL_GetCurrentDisplayMode(0, &sDisplayMode) != 0)
		Sys_Error("Failed to get current display information!\n%s\n", SDL_GetError());

	if (!Video.fullscreen)
		iFlags &= ~SDL_WINDOW_FULLSCREEN;

#if 0
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#endif
	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 8);
#if 0
	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
#endif
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	sMainWindow = SDL_CreateWindow(
		Game->Name,				// [9/7/2013] Window name is based on the name given by Game ~hogsy
		SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED,
		Video.iWidth,
		Video.iHeight,
		iFlags);
	if (!sMainWindow)
		Sys_Error("Failed to create window!\n%s\n", SDL_GetError());

	// Attempt to grab the window icon from the game directory.
	sIcon = SDL_LoadBMP(va("%s/icon.bmp", com_gamedir));
	if (sIcon)
	{
		// [25/3/2014] Set the transparency key... ~hogsy
		SDL_SetColorKey(sIcon, true, SDL_MapRGB(sIcon->format, 0, 0, 0));
		SDL_SetWindowIcon(sMainWindow, sIcon);
		SDL_FreeSurface(sIcon);
	}
	else
		// Give us a warning, but continue.
		Con_Warning("Failed to load window icon! (%s)\n", SDL_GetError());

	sMainContext = SDL_GL_CreateContext(sMainWindow);
	if (!sMainContext)
		Sys_Error("Failed to create context!\n%s\n", SDL_GetError());

	SDL_GL_SetSwapInterval(0);

#ifdef _WIN32
	if (SDL_GetWindowWMInfo(sMainWindow, &sSystemInfo))
		g_mainwindow.instance = sSystemInfo.info.win.window;
	else
		Con_Warning("Failed to get WM information! (%s)\n", SDL_GetError());
#endif
}
/*
==================
CL_ParseServerInfo
==================
*/
void CL_ParseServerInfo (void)
{
	const char	*str;
	int		i;
	int		nummodels, numsounds;
	char	model_precache[MAX_MODELS][MAX_QPATH];
	char	sound_precache[MAX_SOUNDS][MAX_QPATH];

	Con_DPrintf ("Serverinfo packet received.\n");
//
// wipe the client_state_t struct
//
	CL_ClearState ();

// parse protocol version number
	i = MSG_ReadLong ();
	//johnfitz -- support multiple protocols
	if (i != PROTOCOL_NETQUAKE && i != PROTOCOL_FITZQUAKE) {
		Con_Printf ("\n"); //becuase there's no newline after serverinfo print
		Host_Error ("Server returned version %i, not %i or %i\n", i, PROTOCOL_NETQUAKE, PROTOCOL_FITZQUAKE);
	}
	cl.protocol = i;
	//johnfitz

// parse maxclients
	cl.maxclients = MSG_ReadByte ();
	if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
	{
		Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
		return;
	}
	cl.scores = (scoreboard_t *) Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");

// parse gametype
	cl.gametype = MSG_ReadByte ();

// parse signon message
	str = MSG_ReadString ();
	q_strlcpy (cl.levelname, str, sizeof(cl.levelname));

// seperate the printfs so the server message can have a color
	Con_Printf ("\n%s\n", Con_Quakebar(40)); //johnfitz
	Con_Printf ("%c%s\n", 2, str);

//johnfitz -- tell user which protocol this is
	Con_Printf ("Using protocol %i\n", i);

// first we go through and touch all of the precache data that still
// happens to be in the cache, so precaching something else doesn't
// needlessly purge it

// precache models
	memset (cl.model_precache, 0, sizeof(cl.model_precache));
	for (nummodels = 1 ; ; nummodels++)
	{
		str = MSG_ReadString ();
		if (!str[0])
			break;
		if (nummodels==MAX_MODELS)
		{
			Con_Printf ("Server sent too many model precaches\n");
			return;
		}
		q_strlcpy (model_precache[nummodels], str, MAX_QPATH);
		Mod_TouchModel (str);
	}

	//johnfitz -- check for excessive models
	if (nummodels >= 256)
		Con_Warning ("%i models exceeds standard limit of 256.\n", nummodels);
	//johnfitz

// precache sounds
	memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
	for (numsounds = 1 ; ; numsounds++)
	{
		str = MSG_ReadString ();
		if (!str[0])
			break;
		if (numsounds==MAX_SOUNDS)
		{
			Con_Printf ("Server sent too many sound precaches\n");
			return;
		}
		q_strlcpy (sound_precache[numsounds], str, MAX_QPATH);
		S_TouchSound (str);
	}

	//johnfitz -- check for excessive sounds
	if (numsounds >= 256)
		Con_Warning ("%i sounds exceeds standard limit of 256.\n", numsounds);
	//johnfitz

//
// now we try to load everything else until a cache allocation fails
//

	// copy the naked name of the map file to the cl structure -- O.S
	COM_StripExtension (COM_SkipPath(model_precache[1]), cl.mapname, sizeof(cl.mapname));

	for (i = 1; i < nummodels; i++)
	{
		cl.model_precache[i] = Mod_ForName (model_precache[i], false);
		if (cl.model_precache[i] == NULL)
		{
			Con_Printf("Model %s not found\n", model_precache[i]);
			return;
		}
		CL_KeepaliveMessage ();
	}

	S_BeginPrecaching ();
	for (i = 1; i < numsounds; i++)
	{
		cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
		CL_KeepaliveMessage ();
	}
	S_EndPrecaching ();

// local state
	cl_entities[0].model = cl.worldmodel = cl.model_precache[1];

	R_NewMap ();

	//johnfitz -- clear out string; we don't consider identical
	//messages to be duplicates if the map has changed in between
	con_lastcenterstring[0] = 0;
	//johnfitz

	Hunk_Check ();		// make sure nothing is hurt

	noclip_anglehack = false;		// noclip is turned off at start

	warn_about_nehahra_protocol = true; //johnfitz -- warn about nehahra protocol hack once per server connection

//johnfitz -- reset developer stats
	memset(&dev_stats, 0, sizeof(dev_stats));
	memset(&dev_peakstats, 0, sizeof(dev_peakstats));
	memset(&dev_overflows, 0, sizeof(dev_overflows));
}
/*
==================
CL_ParseUpdate

Parse an entity update message from the server
If an entities model or origin changes from frame to frame, it must be
relinked.  Other attributes can change without relinking.
==================
*/
void CL_ParseUpdate (int bits)
{
	int		i;
	qmodel_t	*model;
	int		modnum;
	qboolean	forcelink;
	entity_t	*ent;
	int		num;
	int		skin;

	if (cls.signon == SIGNONS - 1)
	{	// first update is the final signon stage
		cls.signon = SIGNONS;
		CL_SignonReply ();
	}

	if (bits & U_MOREBITS)
	{
		i = MSG_ReadByte ();
		bits |= (i<<8);
	}

	//johnfitz -- PROTOCOL_FITZQUAKE
	if (cl.protocol == PROTOCOL_FITZQUAKE)
	{
		if (bits & U_EXTEND1)
			bits |= MSG_ReadByte() << 16;
		if (bits & U_EXTEND2)
			bits |= MSG_ReadByte() << 24;
	}
	//johnfitz

	if (bits & U_LONGENTITY)
		num = MSG_ReadShort ();
	else
		num = MSG_ReadByte ();

	ent = CL_EntityNum (num);

	if (ent->msgtime != cl.mtime[1])
		forcelink = true;	// no previous frame to lerp from
	else
		forcelink = false;

	//johnfitz -- lerping
	if (ent->msgtime + 0.2 < cl.mtime[0]) //more than 0.2 seconds since the last message (most entities think every 0.1 sec)
		ent->lerpflags |= LERP_RESETANIM; //if we missed a think, we'd be lerping from the wrong frame
	//johnfitz

	ent->msgtime = cl.mtime[0];

	if (bits & U_MODEL)
	{
		modnum = MSG_ReadByte ();
		if (modnum >= MAX_MODELS)
			Host_Error ("CL_ParseModel: bad modnum");
	}
	else
		modnum = ent->baseline.modelindex;

	if (bits & U_FRAME)
		ent->frame = MSG_ReadByte ();
	else
		ent->frame = ent->baseline.frame;

	if (bits & U_COLORMAP)
		i = MSG_ReadByte();
	else
		i = ent->baseline.colormap;
	if (!i)
		ent->colormap = vid.colormap;
	else
	{
		if (i > cl.maxclients)
			Sys_Error ("i >= cl.maxclients");
		ent->colormap = cl.scores[i-1].translations;
	}
	if (bits & U_SKIN)
		skin = MSG_ReadByte();
	else
		skin = ent->baseline.skin;
	if (skin != ent->skinnum)
	{
		ent->skinnum = skin;
		if (num > 0 && num <= cl.maxclients)
			R_TranslateNewPlayerSkin (num - 1); //johnfitz -- was R_TranslatePlayerSkin
	}
	if (bits & U_EFFECTS)
		ent->effects = MSG_ReadByte();
	else
		ent->effects = ent->baseline.effects;

// shift the known values for interpolation
	VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
	VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);

	if (bits & U_ORIGIN1)
		ent->msg_origins[0][0] = MSG_ReadCoord ();
	else
		ent->msg_origins[0][0] = ent->baseline.origin[0];
	if (bits & U_ANGLE1)
		ent->msg_angles[0][0] = MSG_ReadAngle();
	else
		ent->msg_angles[0][0] = ent->baseline.angles[0];

	if (bits & U_ORIGIN2)
		ent->msg_origins[0][1] = MSG_ReadCoord ();
	else
		ent->msg_origins[0][1] = ent->baseline.origin[1];
	if (bits & U_ANGLE2)
		ent->msg_angles[0][1] = MSG_ReadAngle();
	else
		ent->msg_angles[0][1] = ent->baseline.angles[1];

	if (bits & U_ORIGIN3)
		ent->msg_origins[0][2] = MSG_ReadCoord ();
	else
		ent->msg_origins[0][2] = ent->baseline.origin[2];
	if (bits & U_ANGLE3)
		ent->msg_angles[0][2] = MSG_ReadAngle();
	else
		ent->msg_angles[0][2] = ent->baseline.angles[2];

	//johnfitz -- lerping for movetype_step entities
	if (bits & U_STEP)
	{
		ent->lerpflags |= LERP_MOVESTEP;
		ent->forcelink = true;
	}
	else
		ent->lerpflags &= ~LERP_MOVESTEP;
	//johnfitz

	//johnfitz -- PROTOCOL_FITZQUAKE and PROTOCOL_NEHAHRA
	if (cl.protocol == PROTOCOL_FITZQUAKE)
	{
		if (bits & U_ALPHA)
			ent->alpha = MSG_ReadByte();
		else
			ent->alpha = ent->baseline.alpha;
		if (bits & U_FRAME2)
			ent->frame = (ent->frame & 0x00FF) | (MSG_ReadByte() << 8);
		if (bits & U_MODEL2)
			modnum = (modnum & 0x00FF) | (MSG_ReadByte() << 8);
		if (bits & U_LERPFINISH)
		{
			ent->lerpfinish = ent->msgtime + ((float)(MSG_ReadByte()) / 255);
			ent->lerpflags |= LERP_FINISH;
		}
		else
			ent->lerpflags &= ~LERP_FINISH;
	}
	else if (cl.protocol == PROTOCOL_NETQUAKE)
	{
		//HACK: if this bit is set, assume this is PROTOCOL_NEHAHRA
		if (bits & U_TRANS)
		{
			float a, b;

			if (warn_about_nehahra_protocol)
			{
				Con_Warning ("nonstandard update bit, assuming Nehahra protocol\n");
				warn_about_nehahra_protocol = false;
			}

			a = MSG_ReadFloat();
			b = MSG_ReadFloat(); //alpha
			if (a == 2)
				MSG_ReadFloat(); //fullbright (not using this yet)
			ent->alpha = ENTALPHA_ENCODE(b);
		}
		else
			ent->alpha = ent->baseline.alpha;
	}
	//johnfitz

	//johnfitz -- moved here from above
	model = cl.model_precache[modnum];
	if (model != ent->model)
	{
		ent->model = model;
	// automatic animation (torches, etc) can be either all together
	// or randomized
		if (model)
		{
			if (model->synctype == ST_RAND)
				ent->syncbase = (float)(rand()&0x7fff) / 0x7fff;
			else
				ent->syncbase = 0.0;
		}
		else
			forcelink = true;	// hack to make null model players work
		if (num > 0 && num <= cl.maxclients)
			R_TranslateNewPlayerSkin (num - 1); //johnfitz -- was R_TranslatePlayerSkin

		ent->lerpflags |= LERP_RESETANIM; //johnfitz -- don't lerp animation across model changes
	}
	//johnfitz

	if ( forcelink )
	{	// didn't have an update last message
		VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
		VectorCopy (ent->msg_origins[0], ent->origin);
		VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
		VectorCopy (ent->msg_angles[0], ent->angles);
		ent->forcelink = true;
	}
}