[quakespasm] 01/06: Imported Upstream version 0.91.0+dfsg

Stephen Kitt skitt at moszumanska.debian.org
Wed Jan 20 12:59:16 UTC 2016


This is an automated email from the git hooks/post-receive script.

skitt pushed a commit to branch master
in repository quakespasm.

commit ad3a795980ce73c09ad37ae829ae597b91a51c5c
Author: Stephen Kitt <steve at sk2.org>
Date:   Wed Jan 20 11:29:30 2016 +0100

    Imported Upstream version 0.91.0+dfsg
---
 Linux/sgml/Quakespasm.sgml           |  52 +++++++-
 Misc/fs_search_order.patch           |  14 +--
 Misc/quake_retexturing_project.patch |  29 ++---
 Quake/cmd.c                          |  13 +-
 Quake/common.c                       |   2 +-
 Quake/console.c                      |   2 +-
 Quake/gl_fog.c                       |  12 ++
 Quake/gl_mesh.c                      | 227 ++++++++++++++++++++---------------
 Quake/gl_model.c                     |  13 ++
 Quake/gl_model.h                     |   6 +
 Quake/gl_rmain.c                     |  55 ++++++---
 Quake/gl_rmisc.c                     | 128 +++++++++++++++++++-
 Quake/gl_screen.c                    |   3 +-
 Quake/gl_sky.c                       |  28 ++++-
 Quake/gl_texmgr.c                    |  47 ++++++--
 Quake/gl_texmgr.h                    |   1 +
 Quake/gl_vidsdl.c                    |  36 ++++--
 Quake/glquake.h                      |  13 +-
 Quake/host.c                         |   2 +-
 Quake/main_sdl.c                     |   8 +-
 Quake/menu.c                         |   2 +-
 Quake/pr_cmds.c                      |  11 +-
 Quake/quakedef.h                     |   4 +-
 Quake/r_alias.c                      |  14 +--
 Quake/r_brush.c                      |  17 ++-
 Quake/r_sprite.c                     |   2 +-
 Quake/r_world.c                      |  34 ++++--
 Quake/sbar.c                         |   2 +-
 Quake/snd_dma.c                      |   2 +-
 Quake/snd_mp3.c                      |  49 +++++---
 Quake/sys_sdl_win.c                  |   4 +-
 Quake/zone.c                         |   9 +-
 Quakespasm.html                      | 116 +++++++++++++-----
 Quakespasm.txt                       | 146 ++++++++++++++++------
 34 files changed, 803 insertions(+), 300 deletions(-)

diff --git a/Linux/sgml/Quakespasm.sgml b/Linux/sgml/Quakespasm.sgml
index 51bec77..9572fca 100644
--- a/Linux/sgml/Quakespasm.sgml
+++ b/Linux/sgml/Quakespasm.sgml
@@ -4,7 +4,7 @@
 <toc>
 <verb></verb>
 
-<em>Page last edited June 4, 2015</em>
+<em>Page last edited: December 2015</em>
 
 <sect> About <p>
 
@@ -19,7 +19,7 @@ sound driver, some graphical niceities, and numerous bug-fixes and other improve
 
 <itemize>
 <item><url url="http://quakespasm.sourceforge.net/download.htm" name="Project Downloads">
-<item><url url="http://quakespasm.ericwa.com/job/quakespasm/" name="Automatic Builds">
+<item><url url="http://quakespasm.ericwa.com/job/quakespasm-sdl2/" name="Automatic Builds">
 </itemize>
 
 
@@ -108,12 +108,56 @@ The "game" command doesn't execute quake.rc in the new game directory being swit
 </p>
 <sect> Changes<p>
 
+<sect1> Changes in 0.91.1<p>
+<sect2> Bugfixes
+<itemize>
+<item> Fix unwanted fog mode change upon video restart.
+<item> Work around Intel 855 bug in status bar drawing with "r_oldwater 0" and "scr_sbaralpha 0".
+<item> Fix an obscure GLSL bug where changing gamma would result in the screen turning to noise.
+<item> Fix GLSL gamma causing the tiled screen border to turn white when "sizedown" is used.
+<item> Fix an alias model VBO renderer bug where a model not precached during map start wouldn't be drawn.
+<item> Fix the order of OpenGL context creation and window creation in SDL2 video.
+<item> Fix a calling convention issue in windows DPI awareness function pointers.
+<item> Fix a random texture recoloring after video mode change.
+<item> Fix a liquid turning to garbage after several video mode changes and "r_oldwater 0".
+<item> Fix a wrong alpha-sorting bug introduced in 0.90.1.
+<item> Fix "flush" command not reloading mdl's from disk (bug introduced in 0.90.1).
+<item> Prevent a possible buffer overflow in Cbuf_Execute (old Q1/Q2 bug).
+<item> Prevent a possible vulnerability in MSG_ReadString (old Q1/Q2 bug).
+</itemize>
+
+<sect2> Visual improvements
+<itemize>
+<item> New cvars r_lavaalpha, r_slimealpha, r_telealpha for fine-tuning specific liquid opacities (from DirectQ/RMQEngine, non-archived, default to 0), and new worldspawn keys _wateralpha, _lavaalpha, _slimealpha, _telealpha, _skyfog (unique to Quakespasm, similar to the behaviour of the "fog" worldspawn key).
+<item> GLSL gamma is now supported on older hardware without NPOT extension.
+</itemize>
+
+<sect2> Interface improvements
+<itemize>
+<item> New r_pos command to show player position.
+<item> NaN detection in traceline with "developer 1" set now warns instead of errors.
+</itemize>
+
+<sect2> Code cleanup / Other
+<itemize>
+<item> Update third-party libraries.
+</itemize>
+
+<sect2> Raised limits
+<itemize>
+<item> Default max_edicts 8192 (was 2048) and no longer saved to config.cfg.
+<item> Default heapsize 256 MB (was 64 MB).
+<item> Default zone 4 MB (was 384 KB).
+<item> Raised MAX_SFX to 1024 (was 512).
+</itemize>
+</p>
+
 <sect1> Changes in 0.90.1<p>
 <sect2> Bugfixes
 <itemize>
 <item> Fix dynamic light artifact where changing lightmap are rendered one frame late (bug introduced in 0.90.0).
 <item> Fix texture memory leak when changing video modes with SDL2.
-<item> Fix rare incorrect mdl lighting on 64-bit builds. <url url="http://forums.inside3d.com/viewtopic.php?f=3&t=5620" name="(details here.)">
+<item> Fix rare incorrect mdl lighting on 64-bit builds. <url url="http://forums.insideqc.com/viewtopic.php?f=3&t=5620" name="(details here.)">
 <item> Fix fullbrights turning black after "kill" command (bug introduced in 0.90.0).
 <item> Clear all fog values on map change to prevent colored fog carrying over to jam3_tronyn.bsp.
 <item> Allow loading saves with } character in quoted strings, fixes issue with retrojam1_skacky.bsp.
@@ -382,7 +426,7 @@ The "game" command doesn't execute quake.rc in the new game directory being swit
 <item><url url="http://quakespasm.sourceforge.net/download.htm" name="Downloads">
 <item><url url="http://www.celephais.net/fitzquake" name="FitzQuake Homepage">
 <item><url url="http://www.celephais.net/board/view_thread.php?id=60452" name="Func Quakespasm forum">
-<item><url url="http://forums.inside3d.com/viewforum.php?f=14" name="Inside 3D forums">
+<item><url url="http://forums.insideqc.com" name="Inside3D forums">
 </itemize>
 
 </article>
diff --git a/Misc/fs_search_order.patch b/Misc/fs_search_order.patch
index 8190142..1e03d18 100644
--- a/Misc/fs_search_order.patch
+++ b/Misc/fs_search_order.patch
@@ -1,14 +1,12 @@
-allow plain files to override files inside a PAK file -- Sander van Dijk
+allow plain files to override files inside a PAK file -- Sander van Dijk.
 
 Index: Quake/common.c
 ===================================================================
---- Quake/common.c	(revision 1060)
+--- Quake/common.c	(revision 1280)
 +++ Quake/common.c	(working copy)
-@@ -1900,15 +1900,7 @@ static void COM_AddGameDirectory (const 
- 	if (com_searchpaths)
- 		path_id = com_searchpaths->path_id << 1;
+@@ -1911,13 +1911,6 @@ static void COM_AddGameDirectory (const 
  	else	path_id = 1U;
--
+ 
  _add_path:
 -	// add the directory to the search path
 -	search = (searchpath_t *) Z_Malloc(sizeof(searchpath_t));
@@ -20,11 +18,11 @@ Index: Quake/common.c
  	// add any pak files in the format pak0.pak pak1.pak, ...
  	for (i = 0; ; i++)
  	{
-@@ -1940,6 +1932,13 @@ _add_path:
+@@ -1949,6 +1942,13 @@ _add_path:
  		if (!pak) break;
  	}
  
-+	// add the directory to the search path -- moved here from before the pakX.pak loop -- svdijk
++	// add the directory to the search path -- moved here from before the pakX.pak loop -- svdijk.
 +	search = (searchpath_t *) Z_Malloc(sizeof(searchpath_t));
 +	search->path_id = path_id;
 +	q_strlcpy (search->filename, com_gamedir, sizeof(search->filename));
diff --git a/Misc/quake_retexturing_project.patch b/Misc/quake_retexturing_project.patch
index afef9b3..c48cdf4 100644
--- a/Misc/quake_retexturing_project.patch
+++ b/Misc/quake_retexturing_project.patch
@@ -1,9 +1,9 @@
 
 Index: Quake/gl_model.c
 ===================================================================
---- Quake/gl_model.c	(revision 1060)
+--- Quake/gl_model.c	(revision 1280)
 +++ Quake/gl_model.c	(working copy)
-@@ -401,6 +401,8 @@ void Mod_LoadTextures (lump_t *l)
+@@ -404,6 +404,8 @@ void Mod_LoadTextures (lump_t *l)
  	extern byte *hunk_base;
  //johnfitz
  
@@ -12,7 +12,7 @@ Index: Quake/gl_model.c
  	//johnfitz -- don't return early if no textures; still need to create dummy texture
  	if (!l->filelen)
  	{
-@@ -452,7 +454,17 @@ void Mod_LoadTextures (lump_t *l)
+@@ -465,7 +467,17 @@ void Mod_LoadTextures (lump_t *l)
  		if (!isDedicated) //no texture uploading for dedicated server
  		{
  			if (!q_strncasecmp(tx->name,"sky",3)) //sky texture //also note -- was Q_strncmp, changed to match qbsp
@@ -30,7 +30,7 @@ Index: Quake/gl_model.c
  			else if (tx->name[0] == '*') //warping texture
  			{
  				//external textures -- first look in "textures/mapname/" then look in "textures/"
-@@ -502,6 +514,52 @@ void Mod_LoadTextures (lump_t *l)
+@@ -515,6 +527,52 @@ void Mod_LoadTextures (lump_t *l)
  				//external textures -- first look in "textures/mapname/" then look in "textures/"
  				mark = Hunk_LowMark ();
  				COM_StripExtension (loadmodel->name + 5, mapname, sizeof(mapname));
@@ -85,34 +85,35 @@ Index: Quake/gl_model.c
  				if (!data)
 Index: Quake/gl_rmain.c
 ===================================================================
---- Quake/gl_rmain.c	(revision 1060)
+--- Quake/gl_rmain.c	(revision 1280)
 +++ Quake/gl_rmain.c	(working copy)
-@@ -101,6 +101,7 @@
- cvar_t	r_nolerp_list = {"r_nolerp_list", "progs/flame.mdl,progs/flame2.mdl,progs/braztall.mdl,progs/brazshrt.mdl,progs/longtrch.mdl,progs/flame_pyre.mdl,progs/v_saw.mdl,progs/v_xfist.mdl,progs/h2stuff/newfire.mdl", CVAR_NONE};
+@@ -101,6 +101,8 @@
+ 
  extern cvar_t	r_vfog;
  //johnfitz
++
 +cvar_t	r_externaltexture_fix = {"r_externaltexture_fix","0", CVAR_ARCHIVE}; //mk
  
  cvar_t	gl_zfix = {"gl_zfix", "0", CVAR_NONE}; // QuakeSpasm z-fighting fix
  
 Index: Quake/gl_rmisc.c
 ===================================================================
---- Quake/gl_rmisc.c	(revision 1060)
+--- Quake/gl_rmisc.c	(revision 1280)
 +++ Quake/gl_rmisc.c	(working copy)
-@@ -46,6 +46,7 @@
- extern cvar_t r_nolerp_list;
+@@ -47,6 +47,7 @@
+ extern cvar_t r_noshadow_list;
  //johnfitz
  extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix
 +extern cvar_t r_externaltexture_fix; //mk
  
  extern gltexture_t *playertextures[MAX_SCOREBOARD]; //johnfitz
  
-@@ -168,6 +169,7 @@ void R_Init (void)
- 	Cvar_RegisterVariable (&r_nolerp_list);
- 	Cvar_SetCallback (&r_nolerp_list, R_NoLerpList_f);
+@@ -231,6 +232,7 @@ void R_Init (void)
+ 	Cvar_RegisterVariable (&r_noshadow_list);
+ 	Cvar_SetCallback (&r_noshadow_list, R_Model_ExtraFlags_List_f);
  	//johnfitz
 +	Cvar_RegisterVariable (&r_externaltexture_fix); //mk
  
  	Cvar_RegisterVariable (&gl_zfix); // QuakeSpasm z-fighting fix
- 
+ 	Cvar_RegisterVariable (&r_lavaalpha);
 
diff --git a/Quake/cmd.c b/Quake/cmd.c
index 4d41a59..b14143a 100644
--- a/Quake/cmd.c
+++ b/Quake/cmd.c
@@ -165,9 +165,16 @@ void Cbuf_Execute (void)
 				break;
 		}
 
-
-		memcpy (line, text, i);
-		line[i] = 0;
+		if (i > (int)sizeof(line) - 1)
+		{
+			memcpy (line, text, sizeof(line) - 1);
+			line[sizeof(line) - 1] = 0;
+		}
+		else
+		{
+			memcpy (line, text, i);
+			line[i] = 0;
+		}
 
 // delete the text from the command buffer and move remaining commands down
 // this is necessary because commands (exec, alias) can insert data at the
diff --git a/Quake/common.c b/Quake/common.c
index 9897870..baaaac1 100644
--- a/Quake/common.c
+++ b/Quake/common.c
@@ -812,7 +812,7 @@ const char *MSG_ReadString (void)
 	l = 0;
 	do
 	{
-		c = MSG_ReadChar ();
+		c = MSG_ReadByte ();
 		if (c == -1 || c == 0)
 			break;
 		string[l] = c;
diff --git a/Quake/console.c b/Quake/console.c
index 7428d65..e17927a 100644
--- a/Quake/console.c
+++ b/Quake/console.c
@@ -819,7 +819,7 @@ extern filelist_item_t	*demolist;
 
 typedef struct arg_completion_type_s
 {
-	char		*command;
+	const char		*command;
 	filelist_item_t	**filelist;
 } arg_completion_type_t;
 
diff --git a/Quake/gl_fog.c b/Quake/gl_fog.c
index a120aee..e0e3996 100644
--- a/Quake/gl_fog.c
+++ b/Quake/gl_fog.c
@@ -394,5 +394,17 @@ void Fog_Init (void)
 	fog_green = DEFAULT_GRAY;
 	fog_blue = DEFAULT_GRAY;
 
+	Fog_SetupState ();
+}
+
+/*
+=============
+Fog_SetupState
+ 
+ericw -- moved from Fog_Init, state that needs to be setup when a new context is created
+=============
+*/
+void Fog_SetupState (void)
+{
 	glFogi(GL_FOG_MODE, GL_EXP2);
 }
diff --git a/Quake/gl_mesh.c b/Quake/gl_mesh.c
index d0a314b..c362fce 100644
--- a/Quake/gl_mesh.c
+++ b/Quake/gl_mesh.c
@@ -287,7 +287,8 @@ void BuildTris (void)
 	alltris += pheader->numtris;
 }
 
-void GL_MakeAliasModelDisplayLists_VBO (void);
+static void GL_MakeAliasModelDisplayLists_VBO (void);
+static void GLMesh_LoadVertexBuffer (qmodel_t *m, const aliashdr_t *hdr);
 
 /*
 ================
@@ -436,144 +437,178 @@ void GL_MakeAliasModelDisplayLists_VBO (void)
 			}
 		}
 	}
+	
+	// upload immediately
+	GLMesh_LoadVertexBuffer (aliasmodel, pheader);
 }
 
 #define NUMVERTEXNORMALS	 162
 extern	float	r_avertexnormals[NUMVERTEXNORMALS][3];
 
-GLuint r_meshvbo = 0;
-GLuint r_meshindexesvbo = 0;
-
 /*
 ================
-GLMesh_LoadVertexBuffers
+GLMesh_LoadVertexBuffer
 
-Loop over all precached alias models, and upload them into one big VBO plus
-an GL_ELEMENT_ARRAY_BUFFER for the vertex indices.
+Upload the given alias model's mesh to a VBO
 
 Original code by MH from RMQEngine
 ================
 */
-void GLMesh_LoadVertexBuffers (void)
+static void GLMesh_LoadVertexBuffer (qmodel_t *m, const aliashdr_t *hdr)
 {
-	int j;
-	qmodel_t *m;
-	int totalindexes = 0;
 	int totalvbosize = 0;
+	const aliasmesh_t *desc;
+	const short *indexes;
+	const trivertx_t *trivertexes;
+	byte *vbodata;
+	int f;
 
 	if (!gl_glsl_alias_able)
 		return;
+	
+// count the sizes we need
+	
+	// ericw -- RMQEngine stored these vbo*ofs values in aliashdr_t, but we must not
+	// mutate Mod_Extradata since it might be reloaded from disk, so I moved them to qmodel_t
+	// (test case: roman1.bsp from arwop, 64mb heap)
+	m->vboindexofs = 0;
+	
+	m->vboxyzofs = 0;
+	totalvbosize += (hdr->numposes * hdr->numverts_vbo * sizeof (meshxyz_t)); // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
+	
+	m->vbostofs = totalvbosize;
+	totalvbosize += (hdr->numverts_vbo * sizeof (meshst_t));
+	
+	if (!hdr->numindexes) return;
+	if (!totalvbosize) return;
+	
+// grab the pointers to data in the extradata
 
-	// pass 1 - count the sizes we need
-	for (j = 1; j < MAX_MODELS; j++)
-	{
-		aliashdr_t *hdr;
-
-		if (!(m = cl.model_precache[j])) break;
-		if (m->type != mod_alias) continue;
-
-		hdr = Mod_Extradata (m);
+	desc = (aliasmesh_t *) ((byte *) hdr + hdr->meshdesc);
+	indexes = (short *) ((byte *) hdr + hdr->indexes);
+	trivertexes = (trivertx_t *) ((byte *)hdr + hdr->vertexes);
 
-		// ericw -- RMQEngine stored these vbo*ofs values in aliashdr_t, but we must not
-		// mutate Mod_Extradata since it might be reloaded from disk, so I moved them to qmodel_t
-		// (test case: roman1.bsp from arwop, 64mb heap)
-		m->vboindexofs = (totalindexes * sizeof (unsigned short));
-		totalindexes += hdr->numindexes;
+// upload indices buffer
 
-		m->vboxyzofs = totalvbosize;
-		totalvbosize += (hdr->numposes * hdr->numverts_vbo * sizeof (meshxyz_t)); // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
+	GL_DeleteBuffersFunc (1, &m->meshindexesvbo);
+	GL_GenBuffersFunc (1, &m->meshindexesvbo);
+	GL_BindBufferFunc (GL_ELEMENT_ARRAY_BUFFER, m->meshindexesvbo);
+	GL_BufferDataFunc (GL_ELEMENT_ARRAY_BUFFER, hdr->numindexes * sizeof (unsigned short), indexes, GL_STATIC_DRAW);
 
-		m->vbostofs = totalvbosize;
-		totalvbosize += (hdr->numverts_vbo * sizeof (meshst_t));
-	}
+// create the vertex buffer (empty)
 
-	if (!totalindexes) return;
-	if (!totalvbosize) return;
+	vbodata = (byte *) malloc(totalvbosize);
+	memset(vbodata, 0, totalvbosize);
 
-	// pass 2 - create the buffers
-	GL_DeleteBuffersFunc (1, &r_meshindexesvbo);
-	GL_GenBuffersFunc (1, &r_meshindexesvbo);
-	GL_BindBufferFunc (GL_ELEMENT_ARRAY_BUFFER, r_meshindexesvbo);
-	GL_BufferDataFunc (GL_ELEMENT_ARRAY_BUFFER, totalindexes * sizeof (unsigned short), NULL, GL_STATIC_DRAW);
+// fill in the vertices at the start of the buffer
+	for (f = 0; f < hdr->numposes; f++) // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
+	{
+		int v;
+		meshxyz_t *xyz = (meshxyz_t *) (vbodata + (f * hdr->numverts_vbo * sizeof (meshxyz_t)));
+		const trivertx_t *tv = trivertexes + (hdr->numverts * f);
 
-	GL_DeleteBuffersFunc (1, &r_meshvbo);
-	GL_GenBuffersFunc (1, &r_meshvbo);
-	GL_BindBufferFunc (GL_ARRAY_BUFFER, r_meshvbo);
-	GL_BufferDataFunc (GL_ARRAY_BUFFER, totalvbosize, NULL, GL_STATIC_DRAW);
+		for (v = 0; v < hdr->numverts_vbo; v++)
+		{
+			trivertx_t trivert = tv[desc[v].vertindex];
+
+			xyz[v].xyz[0] = trivert.v[0];
+			xyz[v].xyz[1] = trivert.v[1];
+			xyz[v].xyz[2] = trivert.v[2];
+			xyz[v].xyz[3] = 1;	// need w 1 for 4 byte vertex compression
+
+			// map the normal coordinates in [-1..1] to [-127..127] and store in an unsigned char.
+			// this introduces some error (less than 0.004), but the normals were very coarse
+			// to begin with
+			xyz[v].normal[0] = 127 * r_avertexnormals[trivert.lightnormalindex][0];
+			xyz[v].normal[1] = 127 * r_avertexnormals[trivert.lightnormalindex][1];
+			xyz[v].normal[2] = 127 * r_avertexnormals[trivert.lightnormalindex][2];
+			xyz[v].normal[3] = 0;	// unused; for 4-byte alignment
+		}
+	}
 
-	// pass 3 - fill in the buffers
-	for (j = 1; j < MAX_MODELS; j++)
+// fill in the ST coords at the end of the buffer
 	{
-		int f;
-		aliashdr_t *hdr;
-		aliasmesh_t *desc;
 		meshst_t *st;
 		float hscale, vscale;
 
-		if (!(m = cl.model_precache[j])) break;
-		if (m->type != mod_alias) continue;
-
-		hdr = Mod_Extradata (m);
-		desc = (aliasmesh_t *) ((byte *) hdr + hdr->meshdesc);
-
 		//johnfitz -- padded skins
 		hscale = (float)hdr->skinwidth/(float)TexMgr_PadConditional(hdr->skinwidth);
 		vscale = (float)hdr->skinheight/(float)TexMgr_PadConditional(hdr->skinheight);
 		//johnfitz
 
-		GL_BufferSubDataFunc (GL_ELEMENT_ARRAY_BUFFER,
-			m->vboindexofs,
-			hdr->numindexes * sizeof (unsigned short),
-			((byte *) hdr + hdr->indexes));
-
-		for (f = 0; f < hdr->numposes; f++) // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
+		st = (meshst_t *) (vbodata + m->vbostofs);
+		for (f = 0; f < hdr->numverts_vbo; f++)
 		{
-			int v;
-			meshxyz_t *xyz = (meshxyz_t *) malloc (hdr->numverts_vbo * sizeof (meshxyz_t));
-			trivertx_t *tv = (trivertx_t *) ((byte *) hdr + hdr->vertexes + (hdr->numverts * sizeof(trivertx_t) * f));
+			st[f].st[0] = hscale * ((float) desc[f].st[0] + 0.5f) / (float) hdr->skinwidth;
+			st[f].st[1] = vscale * ((float) desc[f].st[1] + 0.5f) / (float) hdr->skinheight;
+		}
+	}
 
-			for (v = 0; v < hdr->numverts_vbo; v++)
-			{
-				trivertx_t trivert = tv[desc[v].vertindex];
-
-				xyz[v].xyz[0] = trivert.v[0];
-				xyz[v].xyz[1] = trivert.v[1];
-				xyz[v].xyz[2] = trivert.v[2];
-				xyz[v].xyz[3] = 1;	// need w 1 for 4 byte vertex compression
-
-				// map the normal coordinates in [-1..1] to [-127..127] and store in an unsigned char.
-				// this introduces some error (less than 0.004), but the normals were very coarse
-				// to begin with
-				xyz[v].normal[0] = 127 * r_avertexnormals[trivert.lightnormalindex][0];
-				xyz[v].normal[1] = 127 * r_avertexnormals[trivert.lightnormalindex][1];
-				xyz[v].normal[2] = 127 * r_avertexnormals[trivert.lightnormalindex][2];
-				xyz[v].normal[3] = 0;	// unused; for 4-byte alignment
-			}
+// upload vertexes buffer
+	GL_DeleteBuffersFunc (1, &m->meshvbo);
+	GL_GenBuffersFunc (1, &m->meshvbo);
+	GL_BindBufferFunc (GL_ARRAY_BUFFER, m->meshvbo);
+	GL_BufferDataFunc (GL_ARRAY_BUFFER, totalvbosize, vbodata, GL_STATIC_DRAW);
 
-			GL_BufferSubDataFunc (GL_ARRAY_BUFFER,
-				m->vboxyzofs + (f * hdr->numverts_vbo * sizeof (meshxyz_t)),
-				hdr->numverts_vbo * sizeof (meshxyz_t),
-				xyz);
+	free (vbodata);
 
-			free (xyz);
-		}
+// invalidate the cached bindings
+	GL_ClearBufferBindings ();
+}
 
-		st = (meshst_t *) malloc (hdr->numverts_vbo * sizeof (meshst_t));
+/*
+================
+GLMesh_LoadVertexBuffers
 
-		for (f = 0; f < hdr->numverts_vbo; f++)
-		{
-			st[f].st[0] = hscale * ((float) desc[f].st[0] + 0.5f) / (float) hdr->skinwidth;
-			st[f].st[1] = vscale * ((float) desc[f].st[1] + 0.5f) / (float) hdr->skinheight;
-		}
+Loop over all precached alias models, and upload each one to a VBO.
+================
+*/
+void GLMesh_LoadVertexBuffers (void)
+{
+	int j;
+	qmodel_t *m;
+	const aliashdr_t *hdr;
 
-		GL_BufferSubDataFunc (GL_ARRAY_BUFFER,
-			m->vbostofs,
-			hdr->numverts_vbo * sizeof (meshst_t),
-			st);
+	if (!gl_glsl_alias_able)
+		return;
+	
+	for (j = 1; j < MAX_MODELS; j++)
+	{
+		if (!(m = cl.model_precache[j])) break;
+		if (m->type != mod_alias) continue;
 
-		free (st);
+		hdr = (const aliashdr_t *) Mod_Extradata (m);
+		
+		GLMesh_LoadVertexBuffer (m, hdr);
 	}
+}
 
-// invalidate the cached bindings
+/*
+================
+GLMesh_DeleteVertexBuffers
+
+Delete VBOs for all loaded alias models
+================
+*/
+void GLMesh_DeleteVertexBuffers (void)
+{
+	int j;
+	qmodel_t *m;
+	
+	if (!gl_glsl_alias_able)
+		return;
+	
+	for (j = 1; j < MAX_MODELS; j++)
+	{
+		if (!(m = cl.model_precache[j])) break;
+		if (m->type != mod_alias) continue;
+		
+		GL_DeleteBuffersFunc (1, &m->meshvbo);
+		m->meshvbo = 0;
+
+		GL_DeleteBuffersFunc (1, &m->meshindexesvbo);
+		m->meshindexesvbo = 0;
+	}
+	
 	GL_ClearBufferBindings ();
 }
diff --git a/Quake/gl_model.c b/Quake/gl_model.c
index dedeaef..a231b15 100644
--- a/Quake/gl_model.c
+++ b/Quake/gl_model.c
@@ -200,6 +200,9 @@ void Mod_ResetAll (void)
 	int		i;
 	qmodel_t	*mod;
 
+	//ericw -- free alias model VBOs
+	GLMesh_DeleteVertexBuffers ();
+	
 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
 	{
 		if (!mod->needload) //otherwise Mod_ClearAll() did it already
@@ -1193,6 +1196,16 @@ void Mod_LoadFaces (lump_t *l, qboolean bsp2)
 		else if (out->texinfo->texture->name[0] == '*') // warp surface
 		{
 			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
+
+		// detect special liquid types
+			if (!strncmp (out->texinfo->texture->name, "*lava", 5))
+				out->flags |= SURF_DRAWLAVA;
+			else if (!strncmp (out->texinfo->texture->name, "*slime", 6))
+				out->flags |= SURF_DRAWSLIME;
+			else if (!strncmp (out->texinfo->texture->name, "*tele", 5))
+				out->flags |= SURF_DRAWTELE;
+			else out->flags |= SURF_DRAWWATER;
+
 			Mod_PolyForUnlitSurface (out);
 			GL_SubdivideSurface (out);
 		}
diff --git a/Quake/gl_model.h b/Quake/gl_model.h
index 023e484..4b1acc5 100644
--- a/Quake/gl_model.h
+++ b/Quake/gl_model.h
@@ -108,6 +108,10 @@ typedef struct texture_s
 #define SURF_UNDERWATER		0x80
 #define SURF_NOTEXTURE		0x100 //johnfitz
 #define SURF_DRAWFENCE		0x200
+#define SURF_DRAWLAVA		0x400
+#define SURF_DRAWSLIME		0x800
+#define SURF_DRAWTELE		0x1000
+#define SURF_DRAWWATER		0x2000
 
 // !!! if this is changed, it must be changed in asm_draw.h too !!!
 typedef struct
@@ -481,6 +485,8 @@ typedef struct qmodel_s
 // alias model
 //
 
+	GLuint		meshvbo;
+	GLuint		meshindexesvbo;
 	int			vboindexofs;    // offset in vbo of the hdr->numindexes unsigned shorts
 	int			vboxyzofs;      // offset in vbo of hdr->numposes*hdr->numverts_vbo meshxyz_t
 	int			vbostofs;       // offset in vbo of hdr->numverts_vbo meshst_t
diff --git a/Quake/gl_rmain.c b/Quake/gl_rmain.c
index 38541ea..908425a 100644
--- a/Quake/gl_rmain.c
+++ b/Quake/gl_rmain.c
@@ -62,6 +62,7 @@ cvar_t	r_norefresh = {"r_norefresh","0",CVAR_NONE};
 cvar_t	r_drawentities = {"r_drawentities","1",CVAR_NONE};
 cvar_t	r_drawviewmodel = {"r_drawviewmodel","1",CVAR_NONE};
 cvar_t	r_speeds = {"r_speeds","0",CVAR_NONE};
+cvar_t	r_pos = {"r_pos","0",CVAR_NONE};
 cvar_t	r_fullbright = {"r_fullbright","0",CVAR_NONE};
 cvar_t	r_lightmap = {"r_lightmap","0",CVAR_NONE};
 cvar_t	r_shadows = {"r_shadows","0",CVAR_ARCHIVE};
@@ -103,6 +104,12 @@ extern cvar_t	r_vfog;
 
 cvar_t	gl_zfix = {"gl_zfix", "0", CVAR_NONE}; // QuakeSpasm z-fighting fix
 
+cvar_t	r_lavaalpha = {"r_lavaalpha","0",CVAR_NONE};
+cvar_t	r_telealpha = {"r_telealpha","0",CVAR_NONE};
+cvar_t	r_slimealpha = {"r_slimealpha","0",CVAR_NONE};
+
+float	map_wateralpha, map_lavaalpha, map_telealpha, map_slimealpha;
+
 qboolean r_drawflat_cheatsafe, r_fullbright_cheatsafe, r_lightmap_cheatsafe, r_drawworld_cheatsafe; //johnfitz
 
 //==============================================================================
@@ -113,6 +120,7 @@ qboolean r_drawflat_cheatsafe, r_fullbright_cheatsafe, r_lightmap_cheatsafe, r_d
 
 static GLuint r_gamma_texture;
 static GLuint r_gamma_program;
+static int r_gamma_texture_width, r_gamma_texture_height;
 
 // uniforms used in gamma shader
 static GLuint gammaLoc;
@@ -173,6 +181,8 @@ GLSLGamma_GammaCorrect
 */
 void GLSLGamma_GammaCorrect (void)
 {
+	float smax, tmax;
+
 	if (!gl_glsl_gamma_able)
 		return;
 
@@ -184,8 +194,17 @@ void GLSLGamma_GammaCorrect (void)
 	{
 		glGenTextures (1, &r_gamma_texture);
 		glBindTexture (GL_TEXTURE_2D, r_gamma_texture);
+
+		r_gamma_texture_width = glwidth;
+		r_gamma_texture_height = glheight;
+
+		if (!gl_texture_NPOT)
+		{
+			r_gamma_texture_width = TexMgr_Pad(r_gamma_texture_width);
+			r_gamma_texture_height = TexMgr_Pad(r_gamma_texture_height);
+		}
 	
-		glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, glwidth, glheight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+		glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, r_gamma_texture_width, r_gamma_texture_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
 		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 	}
@@ -215,21 +234,24 @@ void GLSLGamma_GammaCorrect (void)
 
 	glViewport (glx, gly, glwidth, glheight);
 
+	smax = glwidth/(float)r_gamma_texture_width;
+	tmax = glheight/(float)r_gamma_texture_height;
+
 	glBegin (GL_QUADS);
 	glTexCoord2f (0, 0);
 	glVertex2f (-1, -1);
-	glTexCoord2f (1, 0);
+	glTexCoord2f (smax, 0);
 	glVertex2f (1, -1);
-	glTexCoord2f (1, 1);
+	glTexCoord2f (smax, tmax);
 	glVertex2f (1, 1);
-	glTexCoord2f (0, 1);
+	glTexCoord2f (0, tmax);
 	glVertex2f (-1, 1);
 	glEnd ();
 	
 	GL_UseProgramFunc (0);
 	
 // clear cached binding
-	GL_Bind (notexture);
+	GL_ClearBindings ();
 }
 
 /*
@@ -579,11 +601,6 @@ void R_SetupView (void)
 //
 //==============================================================================
 
-static int R_EntitySortFunc(const void *a, const void *b)
-{
-	return (*(entity_t **)a)->model - (*(entity_t **)b)->model;
-}
-
 /*
 =============
 R_DrawEntitiesOnList
@@ -591,21 +608,15 @@ R_DrawEntitiesOnList
 */
 void R_DrawEntitiesOnList (qboolean alphapass) //johnfitz -- added parameter
 {
-	entity_t	*entities_sorted[MAX_VISEDICTS];
 	int		i;
 
 	if (!r_drawentities.value)
 		return;
 
-	//ericw -- draw the entities sorted by model, to eliminate redundant texture binding
-	memcpy (entities_sorted, cl_visedicts, cl_numvisedicts * sizeof(entity_t *));
-	qsort (entities_sorted, cl_numvisedicts, sizeof(entity_t *), R_EntitySortFunc);
-	//ericw --
-
 	//johnfitz -- sprites are not a special case
 	for (i=0 ; i<cl_numvisedicts ; i++)
 	{
-		currententity = entities_sorted[i];
+		currententity = cl_visedicts[i];
 
 		//johnfitz -- if alphapass is true, draw only alpha entites this time
 		//if alphapass is false, draw only nonalpha entities this time
@@ -988,7 +999,15 @@ void R_RenderView (void)
 
 	//johnfitz -- modified r_speeds output
 	time2 = Sys_DoubleTime ();
-	if (r_speeds.value == 2)
+	if (r_pos.value)
+		Con_Printf ("x %i y %i z %i (pitch %i yaw %i roll %i)\n",
+			(int)cl_entities[cl.viewentity].origin[0],
+			(int)cl_entities[cl.viewentity].origin[1],
+			(int)cl_entities[cl.viewentity].origin[2],
+			(int)cl.viewangles[PITCH],
+			(int)cl.viewangles[YAW],
+			(int)cl.viewangles[ROLL]);
+	else if (r_speeds.value == 2)
 		Con_Printf ("%3i ms  %4i/%4i wpoly %4i/%4i epoly %3i lmap %4i/%4i sky %1.1f mtex\n",
 					(int)((time2-time1)*1000),
 					rs_brushpolys,
diff --git a/Quake/gl_rmisc.c b/Quake/gl_rmisc.c
index cc78233..df1853b 100644
--- a/Quake/gl_rmisc.c
+++ b/Quake/gl_rmisc.c
@@ -110,6 +110,64 @@ static void R_Model_ExtraFlags_List_f (cvar_t *var)
 }
 
 /*
+====================
+R_SetWateralpha_f -- ericw
+====================
+*/
+static void R_SetWateralpha_f (cvar_t *var)
+{
+	map_wateralpha = var->value;
+}
+
+/*
+====================
+R_SetLavaalpha_f -- ericw
+====================
+*/
+static void R_SetLavaalpha_f (cvar_t *var)
+{
+	map_lavaalpha = var->value;
+}
+
+/*
+====================
+R_SetTelealpha_f -- ericw
+====================
+*/
+static void R_SetTelealpha_f (cvar_t *var)
+{
+	map_telealpha = var->value;
+}
+
+/*
+====================
+R_SetSlimealpha_f -- ericw
+====================
+*/
+static void R_SetSlimealpha_f (cvar_t *var)
+{
+	map_slimealpha = var->value;
+}
+
+/*
+====================
+GL_WaterAlphaForSurfface -- ericw
+====================
+*/
+float GL_WaterAlphaForSurface (msurface_t *fa)
+{
+	if (fa->flags & SURF_DRAWLAVA)
+		return map_lavaalpha > 0 ? map_lavaalpha : map_wateralpha;
+	else if (fa->flags & SURF_DRAWTELE)
+		return map_telealpha > 0 ? map_telealpha : map_wateralpha;
+	else if (fa->flags & SURF_DRAWSLIME)
+		return map_slimealpha > 0 ? map_slimealpha : map_wateralpha;
+	else
+		return map_wateralpha;
+}
+
+
+/*
 ===============
 R_Init
 ===============
@@ -128,10 +186,12 @@ void R_Init (void)
 	Cvar_RegisterVariable (&r_drawviewmodel);
 	Cvar_RegisterVariable (&r_shadows);
 	Cvar_RegisterVariable (&r_wateralpha);
+	Cvar_SetCallback (&r_wateralpha, R_SetWateralpha_f);
 	Cvar_RegisterVariable (&r_dynamic);
 	Cvar_RegisterVariable (&r_novis);
 	Cvar_SetCallback (&r_novis, R_VisChanged);
 	Cvar_RegisterVariable (&r_speeds);
+	Cvar_RegisterVariable (&r_pos);
 
 	Cvar_RegisterVariable (&gl_finish);
 	Cvar_RegisterVariable (&gl_clear);
@@ -173,6 +233,12 @@ void R_Init (void)
 	//johnfitz
 
 	Cvar_RegisterVariable (&gl_zfix); // QuakeSpasm z-fighting fix
+	Cvar_RegisterVariable (&r_lavaalpha);
+	Cvar_RegisterVariable (&r_telealpha);
+	Cvar_RegisterVariable (&r_slimealpha);
+	Cvar_SetCallback (&r_lavaalpha, R_SetLavaalpha_f);
+	Cvar_SetCallback (&r_telealpha, R_SetTelealpha_f);
+	Cvar_SetCallback (&r_slimealpha, R_SetSlimealpha_f);
 
 	R_InitParticles ();
 	R_SetClearColor_f (&r_clearcolor); //johnfitz
@@ -256,6 +322,61 @@ void R_NewGame (void)
 }
 
 /*
+=============
+R_ParseWorldspawn
+
+called at map load
+=============
+*/
+static void R_ParseWorldspawn (void)
+{
+	char key[128], value[4096];
+	const char *data;
+
+	map_wateralpha = r_wateralpha.value;
+	map_lavaalpha = r_lavaalpha.value;
+	map_telealpha = r_telealpha.value;
+	map_slimealpha = r_slimealpha.value;
+
+	data = COM_Parse(cl.worldmodel->entities);
+	if (!data)
+		return; // error
+	if (com_token[0] != '{')
+		return; // error
+	while (1)
+	{
+		data = COM_Parse(data);
+		if (!data)
+			return; // error
+		if (com_token[0] == '}')
+			break; // end of worldspawn
+		if (com_token[0] == '_')
+			strcpy(key, com_token + 1);
+		else
+			strcpy(key, com_token);
+		while (key[strlen(key)-1] == ' ') // remove trailing spaces
+			key[strlen(key)-1] = 0;
+		data = COM_Parse(data);
+		if (!data)
+			return; // error
+		strcpy(value, com_token);
+
+		if (!strcmp("wateralpha", key))
+			map_wateralpha = atof(value);
+
+		if (!strcmp("lavaalpha", key))
+			map_lavaalpha = atof(value);
+
+		if (!strcmp("telealpha", key))
+			map_telealpha = atof(value);
+
+		if (!strcmp("slimealpha", key))
+			map_slimealpha = atof(value);
+	}
+}
+
+
+/*
 ===============
 R_NewMap
 ===============
@@ -276,14 +397,15 @@ void R_NewMap (void)
 	R_ClearParticles ();
 
 	GL_BuildLightmaps ();
-	GL_BuildVBOs ();
-	GLMesh_LoadVertexBuffers ();
-	
+	GL_BuildBModelVertexBuffer ();
+	//ericw -- no longer load alias models into a VBO here, it's done in Mod_LoadAliasModel
+
 	r_framecount = 0; //johnfitz -- paranoid?
 	r_visframecount = 0; //johnfitz -- paranoid?
 
 	Sky_NewMap (); //johnfitz -- skybox in worldspawn
 	Fog_NewMap (); //johnfitz -- global fog in worldspawn
+	R_ParseWorldspawn (); //ericw -- wateralpha, lavaalpha, telealpha, slimealpha in worldspawn
 
 	load_subdivide_size = gl_subdivide_size.value; //johnfitz -- is this the right place to set this?
 }
diff --git a/Quake/gl_screen.c b/Quake/gl_screen.c
index 631c914..1c3c806 100644
--- a/Quake/gl_screen.c
+++ b/Quake/gl_screen.c
@@ -953,7 +953,8 @@ johnfitz -- modified to use glwidth/glheight instead of vid.width/vid.height
 */
 void SCR_TileClear (void)
 {
-	if (scr_tileclear_updates >= vid.numpages && !gl_clear.value)
+	//ericw -- added check for glsl gamma. TODO: remove this ugly optimization?
+	if (scr_tileclear_updates >= vid.numpages && !gl_clear.value && !(gl_glsl_gamma_able && vid_gamma.value != 1))
 		return;
 	scr_tileclear_updates++;
 
diff --git a/Quake/gl_sky.c b/Quake/gl_sky.c
index a97748e..7c9cf63 100644
--- a/Quake/gl_sky.c
+++ b/Quake/gl_sky.c
@@ -77,6 +77,8 @@ int	vec_to_st[6][3] =
 	{-2,1,-3}
 };
 
+float	skyfog; // ericw
+
 //==============================================================================
 //
 //  INIT
@@ -223,6 +225,7 @@ void Sky_NewMap (void)
 	skybox_name[0] = 0;
 	for (i=0; i<6; i++)
 		skybox_textures[i] = NULL;
+	skyfog = r_skyfog.value;
 
 	//
 	// read worldspawn (this is so ugly, and shouldn't it be done on the server?)
@@ -258,6 +261,9 @@ void Sky_NewMap (void)
 		if (!strcmp("sky", key))
 			Sky_LoadSkyBox(value);
 
+		if (!strcmp("skyfog", key))
+			skyfog = atof(value);
+
 #if 1 //also accept non-standard keys
 		else if (!strcmp("skyname", key)) //half-life
 			Sky_LoadSkyBox(value);
@@ -288,6 +294,17 @@ void Sky_SkyCommand_f (void)
 }
 
 /*
+====================
+R_SetSkyfog_f -- ericw
+====================
+*/
+static void R_SetSkyfog_f (cvar_t *var)
+{
+// clear any skyfog setting from worldspawn
+	skyfog = var->value;
+}
+
+/*
 =============
 Sky_Init
 =============
@@ -300,6 +317,7 @@ void Sky_Init (void)
 	Cvar_RegisterVariable (&r_sky_quality);
 	Cvar_RegisterVariable (&r_skyalpha);
 	Cvar_RegisterVariable (&r_skyfog);
+	Cvar_SetCallback (&r_skyfog, R_SetSkyfog_f);
 
 	Cmd_AddCommand ("sky",Sky_SkyCommand_f);
 
@@ -699,14 +717,14 @@ void Sky_DrawSkyBox (void)
 		rs_skypolys++;
 		rs_skypasses++;
 
-		if (Fog_GetDensity() > 0 && r_skyfog.value > 0)
+		if (Fog_GetDensity() > 0 && skyfog > 0)
 		{
 			float *c;
 
 			c = Fog_GetColor();
 			glEnable (GL_BLEND);
 			glDisable (GL_TEXTURE_2D);
-			glColor4f (c[0],c[1],c[2], CLAMP(0.0,r_skyfog.value,1.0));
+			glColor4f (c[0],c[1],c[2], CLAMP(0.0,skyfog,1.0));
 
 			glBegin (GL_QUADS);
 			Sky_EmitSkyBoxVertex (skymins[0][i], skymins[1][i], i);
@@ -850,14 +868,14 @@ void Sky_DrawFaceQuad (glpoly_t *p)
 		rs_skypasses += 2;
 	}
 
-	if (Fog_GetDensity() > 0 && r_skyfog.value > 0)
+	if (Fog_GetDensity() > 0 && skyfog > 0)
 	{
 		float *c;
 
 		c = Fog_GetColor();
 		glEnable (GL_BLEND);
 		glDisable (GL_TEXTURE_2D);
-		glColor4f (c[0],c[1],c[2], CLAMP(0.0,r_skyfog.value,1.0));
+		glColor4f (c[0],c[1],c[2], CLAMP(0.0,skyfog,1.0));
 
 		glBegin (GL_QUADS);
 		for (i=0, v=p->verts[0] ; i<4 ; i++, v+=VERTEXSIZE)
@@ -993,7 +1011,7 @@ void Sky_DrawSky (void)
 	//
 	// render slow sky: cloud layers or skybox
 	//
-	if (!r_fastsky.value && !(Fog_GetDensity() > 0 && r_skyfog.value >= 1))
+	if (!r_fastsky.value && !(Fog_GetDensity() > 0 && skyfog >= 1))
 	{
 		glDepthFunc(GL_GEQUAL);
 		glDepthMask(0);
diff --git a/Quake/gl_texmgr.c b/Quake/gl_texmgr.c
index f9c2bf9..4637406 100644
--- a/Quake/gl_texmgr.c
+++ b/Quake/gl_texmgr.c
@@ -343,6 +343,9 @@ gltexture_t *TexMgr_NewTexture (void)
 
 static void GL_DeleteTexture (gltexture_t *texture);
 
+//ericw -- workaround for preventing TexMgr_FreeTexture during TexMgr_ReloadImages
+static qboolean in_reload_images;
+
 /*
 ================
 TexMgr_FreeTexture
@@ -352,6 +355,9 @@ void TexMgr_FreeTexture (gltexture_t *kill)
 {
 	gltexture_t *glt;
 
+	if (in_reload_images)
+		return;
+	
 	if (kill == NULL)
 	{
 		Con_Printf ("TexMgr_FreeTexture: NULL texture\n");
@@ -562,9 +568,11 @@ void TexMgr_RecalcWarpImageSize (void)
 	while (gl_warpimagesize > vid.height)
 		gl_warpimagesize >>= 1;
 
-	if (gl_warpimagesize == oldsize)
-		return;
-
+	// ericw -- removed early exit if (gl_warpimagesize == oldsize).
+	// after vid_restart TexMgr_ReloadImage reloads textures
+	// to tx->source_width/source_height, which might not match oldsize.
+	// fixes: https://sourceforge.net/p/quakespasm/bugs/13/
+	
 	//
 	// resize the textures in opengl
 	//
@@ -1390,18 +1398,23 @@ void TexMgr_ReloadImages (void)
 {
 	gltexture_t *glt;
 
-// ericw -- flush the cache before reloading textures. This avoids an obscure
-// bug where, if the hunk is almost full, an allocation in TexMgr_ReloadImage
+// ericw -- tricky bug: if the hunk is almost full, an allocation in TexMgr_ReloadImage
 // triggers cache items to be freed, which calls back into TexMgr to free the
-// texture. Calling TexMgr_FreeTexture within the loop below causes things to
-// go haywire. A test case is jam3_tronyn.bsp with -heapsize 65536
-    Cache_Flush();
+// texture. If this frees 'glt' in the loop below, the active_gltextures
+// list gets corrupted.
+// A test case is jam3_tronyn.bsp with -heapsize 65536, and do several mode
+// switches/fullscreen toggles
+// 2015-09-04 -- Cache_Flush workaround was causing issues (http://sourceforge.net/p/quakespasm/bugs/10/)
+// switching to a boolean flag.
+	in_reload_images = true;
 
 	for (glt = active_gltextures; glt; glt = glt->next)
 	{
 		glGenTextures(1, &glt->texnum);
 		TexMgr_ReloadImage (glt, -1, -1);
 	}
+	
+	in_reload_images = false;
 }
 
 /*
@@ -1510,3 +1523,21 @@ static void GL_DeleteTexture (gltexture_t *texture)
 
 	texture->texnum = 0;
 }
+
+/*
+================
+GL_ClearBindings -- ericw
+ 
+Invalidates cached bindings, so the next GL_Bind calls for each TMU will
+make real glBindTexture calls.
+Call this after changing the binding outside of GL_Bind.
+================
+*/
+void GL_ClearBindings(void)
+{
+	int i;
+	for (i = 0; i < 3; i++)
+	{
+		currenttexture[i] = -1;
+	}
+}
diff --git a/Quake/gl_texmgr.h b/Quake/gl_texmgr.h
index f772df3..6597b0c 100644
--- a/Quake/gl_texmgr.h
+++ b/Quake/gl_texmgr.h
@@ -104,6 +104,7 @@ void GL_SelectTexture (GLenum target);
 void GL_DisableMultitexture (void); //selects texture unit 0
 void GL_EnableMultitexture (void); //selects texture unit 1
 void GL_Bind (gltexture_t *texture);
+void GL_ClearBindings (void);
 
 #endif	/* _GL_TEXMAN_H */
 
diff --git a/Quake/gl_vidsdl.c b/Quake/gl_vidsdl.c
index 32f5a21..169eba7 100644
--- a/Quake/gl_vidsdl.c
+++ b/Quake/gl_vidsdl.c
@@ -588,10 +588,6 @@ static qboolean VID_SetMode (int width, int height, int bpp, qboolean fullscreen
 		}
 		if (!draw_context)
 			Sys_Error ("Couldn't create window");
-
-		gl_context = SDL_GL_CreateContext (draw_context);
-		if (!gl_context)
-			Sys_Error ("Couldn't create GL context");
 	}
 
 	/* Ensure the window is not fullscreen */
@@ -618,6 +614,13 @@ static qboolean VID_SetMode (int width, int height, int bpp, qboolean fullscreen
 
 	SDL_ShowWindow (draw_context);
 
+	/* Create GL context if needed */
+	if (!gl_context) {
+		gl_context = SDL_GL_CreateContext(draw_context);
+		if (!gl_context)
+			Sys_Error("Couldn't create GL context");
+	}
+
 	gl_swap_control = true;
 	if (SDL_GL_SetSwapInterval ((vid_vsync.value) ? 1 : 0) == -1)
 		gl_swap_control = false;
@@ -734,14 +737,18 @@ static void VID_Restart (void)
 		return;
 	}
 	
-// ericw -- depending on platform / SDL version, after a video mode change we
-// can have a new context (all textures are already freed) or the same context
-// as before, in which case we need to delete the old textures to avoid a
-// memory leak.
+// ericw -- OS X, SDL1: textures, VBO's invalid after mode change
+//          OS X, SDL2: still valid after mode change
+// To handle both cases, delete all GL objects (textures, VBO, GLSL) now.
+// We must not interleave deleting the old objects with creating new ones, because
+// one of the new objects could be given the same ID as an invalid handle
+// which is later deleted.
 
 	TexMgr_DeleteTextureObjects ();
 	GLSLGamma_DeleteTexture ();
 	R_DeleteShaders ();
+	GL_DeleteBModelVertexBuffer ();
+	GLMesh_DeleteVertexBuffers ();
 
 //
 // set new mode
@@ -750,9 +757,10 @@ static void VID_Restart (void)
 
 	GL_Init ();
 	TexMgr_ReloadImages ();
-	GL_BuildVBOs ();
+	GL_BuildBModelVertexBuffer ();
 	GLMesh_LoadVertexBuffers ();
 	GL_SetupState ();
+	Fog_SetupState ();
 
 	//warpimages needs to be recalculated
 	TexMgr_RecalcWarpImageSize ();
@@ -1160,7 +1168,7 @@ static void GL_CheckExtensions (void)
 	//
 	if (COM_CheckParm("-noglslgamma"))
 		Con_Warning ("GLSL gamma disabled at command line\n");
-	else if (gl_glsl_able && gl_texture_NPOT)
+	else if (gl_glsl_able)
 	{
 		gl_glsl_gamma_able = true;
 	}
@@ -1641,7 +1649,13 @@ void	VID_Init (void)
 // new proc by S.A., called by alt-return key binding.
 void	VID_Toggle (void)
 {
-	static qboolean vid_toggle_works = true;
+	// disabling the fast path completely because SDL_SetWindowFullscreen was changing
+	// the window size on SDL2/WinXP and we weren't set up to handle it. --ericw
+	//
+	// TODO: Clear out the dead code, reinstate the fast path using SDL_SetWindowFullscreen
+	// inside VID_SetMode, check window size to fix WinXP issue. This will
+	// keep all the mode changing code in one place.
+	static qboolean vid_toggle_works = false;
 	qboolean toggleWorked;
 	Uint32 flags = 0;
 
diff --git a/Quake/glquake.h b/Quake/glquake.h
index 3715eb2..a9df1e4 100644
--- a/Quake/glquake.h
+++ b/Quake/glquake.h
@@ -127,11 +127,15 @@ extern	cvar_t	r_drawentities;
 extern	cvar_t	r_drawworld;
 extern	cvar_t	r_drawviewmodel;
 extern	cvar_t	r_speeds;
+extern	cvar_t	r_pos;
 extern	cvar_t	r_waterwarp;
 extern	cvar_t	r_fullbright;
 extern	cvar_t	r_lightmap;
 extern	cvar_t	r_shadows;
 extern	cvar_t	r_wateralpha;
+extern	cvar_t	r_lavaalpha;
+extern	cvar_t	r_telealpha;
+extern	cvar_t	r_slimealpha;
 extern	cvar_t	r_dynamic;
 extern	cvar_t	r_novis;
 
@@ -296,6 +300,8 @@ typedef struct glsl_attrib_binding_s {
 	GLuint attrib;
 } glsl_attrib_binding_t;
 
+extern float	map_wateralpha, map_lavaalpha, map_telealpha, map_slimealpha; //ericw
+
 //johnfitz -- fog functions called from outside gl_fog.c
 void Fog_ParseServerMessage (void);
 float *Fog_GetColor (void);
@@ -307,6 +313,7 @@ void Fog_StopAdditive (void);
 void Fog_SetupFrame (void);
 void Fog_NewMap (void);
 void Fog_Init (void);
+void Fog_SetupState (void);
 
 void R_NewGame (void);
 
@@ -337,8 +344,10 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
 
 void R_RenderDlights (void);
 void GL_BuildLightmaps (void);
-void GL_BuildVBOs (void);
+void GL_DeleteBModelVertexBuffer (void);
+void GL_BuildBModelVertexBuffer (void);
 void GLMesh_LoadVertexBuffers (void);
+void GLMesh_DeleteVertexBuffers (void);
 void R_RebuildAllLightmaps (void);
 
 int R_LightPoint (vec3_t p);
@@ -383,5 +392,7 @@ void GL_ClearBufferBindings ();
 void GLSLGamma_DeleteTexture (void);
 void GLSLGamma_GammaCorrect (void);
 
+float GL_WaterAlphaForSurface (msurface_t *fa);
+
 #endif	/* __GLQUAKE_H */
 
diff --git a/Quake/host.c b/Quake/host.c
index f7714b3..a39df6b 100644
--- a/Quake/host.c
+++ b/Quake/host.c
@@ -61,7 +61,7 @@ cvar_t	host_framerate = {"host_framerate","0",CVAR_NONE};	// set for slow motion
 cvar_t	host_speeds = {"host_speeds","0",CVAR_NONE};			// set for running times
 cvar_t	host_maxfps = {"host_maxfps", "72", CVAR_ARCHIVE}; //johnfitz
 cvar_t	host_timescale = {"host_timescale", "0", CVAR_NONE}; //johnfitz
-cvar_t	max_edicts = {"max_edicts", "2048", CVAR_ARCHIVE}; //johnfitz
+cvar_t	max_edicts = {"max_edicts", "8192", CVAR_NONE}; //johnfitz //ericw -- changed from 2048 to 8192, removed CVAR_ARCHIVE
 
 cvar_t	sys_ticrate = {"sys_ticrate","0.05",CVAR_NONE}; // dedicated server
 cvar_t	serverprofile = {"serverprofile","0",CVAR_NONE};
diff --git a/Quake/main_sdl.c b/Quake/main_sdl.c
index 208e469..1aefdc5 100644
--- a/Quake/main_sdl.c
+++ b/Quake/main_sdl.c
@@ -87,11 +87,7 @@ static void Sys_InitSDL (void)
 	atexit(Sys_AtExit);
 }
 
-#if defined(_LP64) || defined(__LP64__) || defined(_WIN64)
-#define DEFAULT_MEMORY 0x4800000
-#else
-#define DEFAULT_MEMORY 0x4000000
-#endif
+#define DEFAULT_MEMORY (256 * 1024 * 1024) // ericw -- was 72MB (64-bit) / 64MB (32-bit)
 
 static quakeparms_t	parms;
 
@@ -137,7 +133,7 @@ int main(int argc, char *argv[])
 	Sys_Printf("GLQuake %1.2f (c) id Software\n", GLQUAKE_VERSION);
 	Sys_Printf("FitzQuake %1.2f (c) John Fitzgibbons\n", FITZQUAKE_VERSION);
 	Sys_Printf("FitzQuake SDL port (c) SleepwalkR, Baker\n");
-	Sys_Printf("QuakeSpasm %1.2f.%d (c) Ozkan Sezer, Stevenaaus\n",
+	Sys_Printf("QuakeSpasm %1.2f.%d (c) Ozkan Sezer, Eric Wasylishen & others\n",
 					QUAKESPASM_VERSION, QUAKESPASM_VER_PATCH);
 
 	Sys_Printf("Host_Init\n");
diff --git a/Quake/menu.c b/Quake/menu.c
index adebe1c..c9fd724 100644
--- a/Quake/menu.c
+++ b/Quake/menu.c
@@ -1617,7 +1617,7 @@ qboolean M_Quit_TextEntry (void)
 void M_Quit_Draw (void) //johnfitz -- modified for new quit message
 {
 	char	msg1[40];
-	char	msg2[] = "by Ozkan Sezer & Stevenaaus"; /* msg2/msg3 are mostly [40] */
+	char	msg2[] = "by Ozkan, Ericw & Stevenaaus"; /* msg2/msg3 are mostly [40] */
 	char	msg3[] = "Press y to quit";
 	int		boxlen;
 
diff --git a/Quake/pr_cmds.c b/Quake/pr_cmds.c
index 910c940..bf1c4ee 100644
--- a/Quake/pr_cmds.c
+++ b/Quake/pr_cmds.c
@@ -685,15 +685,16 @@ static void PF_traceline (void)
 	if (developer.value) {
 	  if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) ||
 	      IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2])) {
-	   Host_Error("NAN in traceline:\nv1(%f %f %f) v2(%f %f %f)\nentity %d",
+	    Con_Warning ("NAN in traceline:\nv1(%f %f %f) v2(%f %f %f)\nentity %d\n",
 		      v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], NUM_FOR_EDICT(ent));
 	  }
-	} else {
-	  if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]))
+	}
+
+	if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]))
 		v1[0] = v1[1] = v1[2] = 0;
-	  if (IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
+	if (IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
 		v2[0] = v2[1] = v2[2] = 0;
-	}
+
 	trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
 
 	pr_global_struct->trace_allsolid = trace.allsolid;
diff --git a/Quake/quakedef.h b/Quake/quakedef.h
index 47f546a..f9ae266 100644
--- a/Quake/quakedef.h
+++ b/Quake/quakedef.h
@@ -36,8 +36,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define	X11_VERSION		1.10
 
 #define	FITZQUAKE_VERSION	0.85	//johnfitz
-#define	QUAKESPASM_VERSION	0.90
-#define	QUAKESPASM_VER_PATCH	1	// helper to print a string like 0.90.0
+#define	QUAKESPASM_VERSION	0.91
+#define	QUAKESPASM_VER_PATCH	0	// helper to print a string like 0.91.0
 
 //define	PARANOID			// speed sapping error checking
 
diff --git a/Quake/r_alias.c b/Quake/r_alias.c
index f573c47..4de9c39 100644
--- a/Quake/r_alias.c
+++ b/Quake/r_alias.c
@@ -36,8 +36,6 @@ float	r_avertexnormals[NUMVERTEXNORMALS][3] =
 #include "anorms.h"
 };
 
-vec3_t	shadevector;
-
 extern vec3_t	lightcolor; //johnfitz -- replaces "float shadelight" for lit support
 
 // precalculated dot products for quantized angles
@@ -51,6 +49,7 @@ extern	vec3_t			lightspot;
 
 float	*shadedots = r_avertexnormal_dots[0];
 vec3_t	shadevector;
+
 float	entalpha; //johnfitz
 
 qboolean	overbright; //johnfitz
@@ -86,9 +85,6 @@ static const GLint pose2VertexAttrIndex = 2;
 static const GLint pose2NormalAttrIndex = 3;
 static const GLint texCoordsAttrIndex = 4;
 
-extern GLuint r_meshvbo;
-extern GLuint r_meshindexesvbo;
-
 /*
 =============
 GLARB_GetXYZOffset
@@ -238,8 +234,8 @@ void GL_DrawAliasFrame_GLSL (aliashdr_t *paliashdr, lerpdata_t lerpdata, gltextu
 
 	GL_UseProgramFunc (r_alias_program);
 
-	GL_BindBuffer (GL_ARRAY_BUFFER, r_meshvbo);
-	GL_BindBuffer (GL_ELEMENT_ARRAY_BUFFER, r_meshindexesvbo);
+	GL_BindBuffer (GL_ARRAY_BUFFER, currententity->model->meshvbo);
+	GL_BindBuffer (GL_ELEMENT_ARRAY_BUFFER, currententity->model->meshindexesvbo);
 
 	GL_EnableVertexAttribArrayFunc (texCoordsAttrIndex);
 	GL_EnableVertexAttribArrayFunc (pose1VertexAttrIndex);
@@ -412,7 +408,7 @@ void R_SetupAliasFrame (aliashdr_t *paliashdr, int frame, lerpdata_t *lerpdata)
 
 	if ((frame >= paliashdr->numframes) || (frame < 0))
 	{
-		Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
+		Con_DPrintf ("R_AliasSetupFrame: no such frame %d for '%s'\n", frame, e->model->name);
 		frame = 0;
 	}
 
@@ -686,7 +682,7 @@ void R_DrawAliasModel (entity_t *e)
 	anim = (int)(cl.time*10) & 3;
 	if ((e->skinnum >= paliashdr->numskins) || (e->skinnum < 0))
 	{
-		Con_DPrintf ("R_DrawAliasModel: no such skin # %dn", e->skinnum);
+		Con_DPrintf ("R_DrawAliasModel: no such skin # %d for '%s'\n", e->skinnum, e->model->name);
 		tx = NULL; // NULL will give the checkerboard texture
 		fb = NULL;
 	}
diff --git a/Quake/r_brush.c b/Quake/r_brush.c
index c4d8daa..bb9e5e7 100644
--- a/Quake/r_brush.c
+++ b/Quake/r_brush.c
@@ -248,7 +248,7 @@ void R_DrawSequentialPoly (msurface_t *s)
 	if (s->flags & SURF_DRAWTURB)
 	{
 		if (currententity->alpha == ENTALPHA_DEFAULT)
-			entalpha = CLAMP(0.0,r_wateralpha.value,1.0);
+			entalpha = CLAMP(0.0, GL_WaterAlphaForSurface(s), 1.0);
 
 		if (entalpha < 1)
 		{
@@ -961,15 +961,26 @@ void GL_BuildLightmaps (void)
 
 GLuint gl_bmodel_vbo = 0;
 
+void GL_DeleteBModelVertexBuffer (void)
+{
+	if (!(gl_vbo_able && gl_mtexable && gl_max_texture_units >= 3))
+		return;
+
+	GL_DeleteBuffersFunc (1, &gl_bmodel_vbo);
+	gl_bmodel_vbo = 0;
+
+	GL_ClearBufferBindings ();
+}
+
 /*
 ==================
-GL_BuildVBOs
+GL_BuildBModelVertexBuffer
 
 Deletes gl_bmodel_vbo if it already exists, then rebuilds it with all
 surfaces from world + all brush models
 ==================
 */
-void GL_BuildVBOs (void)
+void GL_BuildBModelVertexBuffer (void)
 {
 	unsigned int	numverts, varray_bytes, varray_index;
 	int		i, j;
diff --git a/Quake/r_sprite.c b/Quake/r_sprite.c
index 3b764c7..6765e97 100644
--- a/Quake/r_sprite.c
+++ b/Quake/r_sprite.c
@@ -41,7 +41,7 @@ mspriteframe_t *R_GetSpriteFrame (entity_t *currentent)
 
 	if ((frame >= psprite->numframes) || (frame < 0))
 	{
-		Con_DPrintf ("R_DrawSprite: no such frame %d\n", frame);
+		Con_DPrintf ("R_DrawSprite: no such frame %d for '%s'\n", frame, currentent->model->name);
 		frame = 0;
 	}
 
diff --git a/Quake/r_world.c b/Quake/r_world.c
index 05adcea..95e957e 100644
--- a/Quake/r_world.c
+++ b/Quake/r_world.c
@@ -638,6 +638,23 @@ void R_DrawTextureChains_TextureOnly (qmodel_t *model, entity_t *ent, texchain_t
 
 /*
 ================
+GL_WaterAlphaForEntitySurface -- ericw
+ 
+Returns the water alpha to use for the entity and surface combination.
+================
+*/
+float GL_WaterAlphaForEntitySurface (entity_t *ent, msurface_t *s)
+{
+	float entalpha;
+	if (ent == NULL || ent->alpha == ENTALPHA_DEFAULT)
+		entalpha = GL_WaterAlphaForSurface(s);
+	else
+		entalpha = ENTALPHA_DECODE(ent->alpha);
+	return entalpha;
+}
+
+/*
+================
 R_DrawTextureChains_Water -- johnfitz
 ================
 */
@@ -653,13 +670,6 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
 	if (r_drawflat_cheatsafe || r_lightmap_cheatsafe) // ericw -- !r_drawworld_cheatsafe check moved to R_DrawWorld_Water ()
 		return;
 
-	if (ent == NULL || ent->alpha == ENTALPHA_DEFAULT)
-		entalpha = r_wateralpha.value;
-	else
-		entalpha = ENTALPHA_DECODE(ent->alpha);
-
-	R_BeginTransparentDrawing (entalpha);
-
 	if (r_oldwater.value)
 	{
 		for (i=0 ; i<model->numtextures ; i++)
@@ -668,11 +678,14 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
 			if (!t || !t->texturechains[chain] || !(t->texturechains[chain]->flags & SURF_DRAWTURB))
 				continue;
 			bound = false;
+			entalpha = 1.0f;
 			for (s = t->texturechains[chain]; s; s = s->texturechain)
 				if (!s->culled)
 				{
 					if (!bound) //only bind once we are sure we need this texture
 					{
+						entalpha = GL_WaterAlphaForEntitySurface (ent, s);
+						R_BeginTransparentDrawing (entalpha);
 						GL_Bind (t->gltexture);
 						bound = true;
 					}
@@ -682,6 +695,7 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
 						rs_brushpasses++;
 					}
 				}
+			R_EndTransparentDrawing (entalpha);
 		}
 	}
 	else
@@ -692,11 +706,14 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
 			if (!t || !t->texturechains[chain] || !(t->texturechains[chain]->flags & SURF_DRAWTURB))
 				continue;
 			bound = false;
+			entalpha = 1.0f;
 			for (s = t->texturechains[chain]; s; s = s->texturechain)
 				if (!s->culled)
 				{
 					if (!bound) //only bind once we are sure we need this texture
 					{
+						entalpha = GL_WaterAlphaForEntitySurface (ent, s);
+						R_BeginTransparentDrawing (entalpha);
 						GL_Bind (t->warpimage);
 
 						if (model != cl.worldmodel)
@@ -712,10 +729,9 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
 					DrawGLPoly (s->polys);
 					rs_brushpasses++;
 				}
+			R_EndTransparentDrawing (entalpha);
 		}
 	}
-
-	R_EndTransparentDrawing (entalpha);
 }
 
 /*
diff --git a/Quake/sbar.c b/Quake/sbar.c
index d2c0164..38998e3 100644
--- a/Quake/sbar.c
+++ b/Quake/sbar.c
@@ -285,7 +285,7 @@ void Sbar_DrawPicAlpha (int x, int y, qpic_t *pic, float alpha)
 	glEnable (GL_BLEND);
 	glColor4f(1,1,1,alpha);
 	Draw_Pic (x, y + 24, pic);
-	glColor3f(1,1,1);
+	glColor4f(1,1,1,1); // ericw -- changed from glColor3f to work around intel 855 bug with "r_oldwater 0" and "scr_sbaralpha 0"
 	glDisable (GL_BLEND);
 	glEnable (GL_ALPHA_TEST);
 }
diff --git a/Quake/snd_dma.c b/Quake/snd_dma.c
index e3f8917..cc5df69 100644
--- a/Quake/snd_dma.c
+++ b/Quake/snd_dma.c
@@ -62,7 +62,7 @@ int		s_rawend;
 portable_samplepair_t	s_rawsamples[MAX_RAW_SAMPLES];
 
 
-#define	MAX_SFX		512
+#define	MAX_SFX		1024
 static sfx_t	*known_sfx = NULL;	// hunk allocated [MAX_SFX]
 static int	num_sfx;
 
diff --git a/Quake/snd_mp3.c b/Quake/snd_mp3.c
index 8a5348c..42ba434 100644
--- a/Quake/snd_mp3.c
+++ b/Quake/snd_mp3.c
@@ -8,7 +8,7 @@
  * functions were adapted from the GPL-licensed libid3tag library, see at
  * http://www.underbit.com/products/mad/.  Adapted to Quake and Hexen II
  * game engines by O.Sezer :
- * Copyright (C) 2010-2013 O.Sezer <sezero at users.sourceforge.net>
+ * Copyright (C) 2010-2015 O.Sezer <sezero at users.sourceforge.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -89,16 +89,36 @@ static inline qboolean tag_is_id3v2(const unsigned char *data, size_t length)
 	return false;
 }
 
-static int mp3_tagsize(const unsigned char *data, size_t length)
+/* http://wiki.hydrogenaud.io/index.php?title=APEv1_specification
+ * http://wiki.hydrogenaud.io/index.php?title=APEv2_specification
+ * Detect an APEv2 tag. (APEv1 has no header, so no luck.)
+ */
+static inline qboolean tag_is_apetag(const unsigned char *data, size_t length)
+{
+	unsigned int v;
+
+	if (length < 32) return false;
+	if (memcmp(data,"APETAGEX",8) != 0)
+		return false;
+	v = (data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8];
+	if (v != 2000U/* && v != 1000U*/)
+		return false;
+	v = 0;
+	if (memcmp(&data[24],&v,4) != 0 || memcmp(&data[28],&v,4) != 0)
+		return false;
+	return true;
+}
+
+static size_t mp3_tagsize(const unsigned char *data, size_t length)
 {
+	size_t size;
+
 	if (tag_is_id3v1(data, length))
 		return 128;
 
 	if (tag_is_id3v2(data, length))
 	{
-		unsigned char flags;
-		unsigned int size;
-		flags = data[5];
+		unsigned char flags = data[5];
 		size = 10 + (data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9];
 		if (flags & ID3_TAG_FLAG_FOOTERPRESENT)
 			size += 10;
@@ -107,6 +127,13 @@ static int mp3_tagsize(const unsigned char *data, size_t length)
 		return size;
 	}
 
+	if (tag_is_apetag(data, length))
+	{
+		size = (data[15]<<24) | (data[14]<<16) | (data[13]<<8) | data[12];
+		size += 32;
+		return size;
+	}
+
 	return 0;
 }
 
@@ -495,16 +522,12 @@ static qboolean S_MP3_CodecOpenStream (snd_stream_t *stream)
 {
 	int err;
 
-#if 0 /*defined(CODECS_USE_ZONE)*/
-	stream->priv = Z_Malloc(sizeof(mp3_priv_t));
-#else
 	stream->priv = calloc(1, sizeof(mp3_priv_t));
 	if (!stream->priv)
 	{
 		Con_Printf("Insufficient memory for MP3 audio\n");
 		return false;
 	}
-#endif
 	err = mp3_startread(stream);
 	if (err != 0)
 	{
@@ -519,11 +542,7 @@ static qboolean S_MP3_CodecOpenStream (snd_stream_t *stream)
 	{
 		return true;
 	}
-#if 0 /*defined(CODECS_USE_ZONE)*/
-	Z_Free(stream->priv);
-#else
 	free(stream->priv);
-#endif
 	return false;
 }
 
@@ -536,11 +555,7 @@ static int S_MP3_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer)
 static void S_MP3_CodecCloseStream (snd_stream_t *stream)
 {
 	mp3_stopread(stream);
-#if 0 /*defined(CODECS_USE_ZONE)*/
-	Z_Free(stream->priv);
-#else
 	free(stream->priv);
-#endif
 	S_CodecUtilClose(&stream);
 }
 
diff --git a/Quake/sys_sdl_win.c b/Quake/sys_sdl_win.c
index 67a3da9..8921794 100644
--- a/Quake/sys_sdl_win.c
+++ b/Quake/sys_sdl_win.c
@@ -175,8 +175,8 @@ static void Sys_GetBasedir (char *argv0, char *dst, size_t dstsize)
 }
 
 typedef enum { dpi_unaware = 0, dpi_system_aware = 1, dpi_monitor_aware = 2 } dpi_awareness;
-typedef BOOL(*SetProcessDPIAwareFunc)();
-typedef HRESULT(*SetProcessDPIAwarenessFunc)(dpi_awareness value);
+typedef BOOL (WINAPI *SetProcessDPIAwareFunc)();
+typedef HRESULT (WINAPI *SetProcessDPIAwarenessFunc)(dpi_awareness value);
 
 static void Sys_SetDPIAware (void)
 {
diff --git a/Quake/zone.c b/Quake/zone.c
index 835b00c..05936bb 100644
--- a/Quake/zone.c
+++ b/Quake/zone.c
@@ -23,11 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-#if defined(_LP64) || defined(__LP64__) || defined(_WIN64)
-#define	DYNAMIC_SIZE	0x80000	// 512*1024
-#else
-#define	DYNAMIC_SIZE	0x60000	// 384*1024
-#endif
+#define	DYNAMIC_SIZE	(4 * 1024 * 1024) // ericw -- was 512KB (64-bit) / 384KB (32-bit)
 
 #define	ZONEID	0x1d4a11
 #define MINFRAGMENT	64
@@ -37,8 +33,8 @@ typedef struct memblock_s
 	int	size;		// including the header and possibly tiny fragments
 	int	tag;		// a tag of 0 is a free block
 	int	id;		// should be ZONEID
-	struct	memblock_s	*next, *prev;
 	int	pad;		// pad to 64 bit boundary
+	struct	memblock_s	*next, *prev;
 } memblock_t;
 
 typedef struct
@@ -804,7 +800,6 @@ void Cache_Flush (void)
 		Cache_Free ( cache_head.next->user, true); // reclaim the space //johnfitz -- added second argument
 }
 
-
 /*
 ============
 Cache_Print
diff --git a/Quakespasm.html b/Quakespasm.html
index 16067e1..5e3c172 100644
--- a/Quakespasm.html
+++ b/Quakespasm.html
@@ -12,7 +12,7 @@
 <PRE>
 </PRE>
 </P>
-<P><EM>Page last edited June 4, 2015</EM></P>
+<P><EM>Page last edited: December 2015</EM></P>
 
 <P>
 <H2><A NAME="toc1">1.</A> <A HREF="Quakespasm.html#s1">About </A></H2>
@@ -41,17 +41,18 @@
 <H2><A NAME="toc6">6.</A> <A HREF="Quakespasm.html#s6">Changes</A></H2>
 
 <UL>
-<LI><A NAME="toc6.1">6.1</A> <A HREF="Quakespasm.html#ss6.1">Changes in 0.90.1</A>
-<LI><A NAME="toc6.2">6.2</A> <A HREF="Quakespasm.html#ss6.2">Changes in 0.90.0</A>
-<LI><A NAME="toc6.3">6.3</A> <A HREF="Quakespasm.html#ss6.3">Changes in 0.85.9</A>
-<LI><A NAME="toc6.4">6.4</A> <A HREF="Quakespasm.html#ss6.4">Changes in 0.85.8</A>
-<LI><A NAME="toc6.5">6.5</A> <A HREF="Quakespasm.html#ss6.5">Changes in 0.85.7</A>
-<LI><A NAME="toc6.6">6.6</A> <A HREF="Quakespasm.html#ss6.6">Changes in 0.85.6</A>
-<LI><A NAME="toc6.7">6.7</A> <A HREF="Quakespasm.html#ss6.7">Changes in 0.85.5</A>
-<LI><A NAME="toc6.8">6.8</A> <A HREF="Quakespasm.html#ss6.8">Changes in 0.85.4</A>
-<LI><A NAME="toc6.9">6.9</A> <A HREF="Quakespasm.html#ss6.9">Changes in 0.85.3</A>
-<LI><A NAME="toc6.10">6.10</A> <A HREF="Quakespasm.html#ss6.10">Changes in 0.85.2</A>
-<LI><A NAME="toc6.11">6.11</A> <A HREF="Quakespasm.html#ss6.11">Changes in 0.85.1</A>
+<LI><A NAME="toc6.1">6.1</A> <A HREF="Quakespasm.html#ss6.1">Changes in 0.91.1</A>
+<LI><A NAME="toc6.2">6.2</A> <A HREF="Quakespasm.html#ss6.2">Changes in 0.90.1</A>
+<LI><A NAME="toc6.3">6.3</A> <A HREF="Quakespasm.html#ss6.3">Changes in 0.90.0</A>
+<LI><A NAME="toc6.4">6.4</A> <A HREF="Quakespasm.html#ss6.4">Changes in 0.85.9</A>
+<LI><A NAME="toc6.5">6.5</A> <A HREF="Quakespasm.html#ss6.5">Changes in 0.85.8</A>
+<LI><A NAME="toc6.6">6.6</A> <A HREF="Quakespasm.html#ss6.6">Changes in 0.85.7</A>
+<LI><A NAME="toc6.7">6.7</A> <A HREF="Quakespasm.html#ss6.7">Changes in 0.85.6</A>
+<LI><A NAME="toc6.8">6.8</A> <A HREF="Quakespasm.html#ss6.8">Changes in 0.85.5</A>
+<LI><A NAME="toc6.9">6.9</A> <A HREF="Quakespasm.html#ss6.9">Changes in 0.85.4</A>
+<LI><A NAME="toc6.10">6.10</A> <A HREF="Quakespasm.html#ss6.10">Changes in 0.85.3</A>
+<LI><A NAME="toc6.11">6.11</A> <A HREF="Quakespasm.html#ss6.11">Changes in 0.85.2</A>
+<LI><A NAME="toc6.12">6.12</A> <A HREF="Quakespasm.html#ss6.12">Changes in 0.85.1</A>
 </UL>
 <P>
 <H2><A NAME="toc7">7.</A> <A HREF="Quakespasm.html#s7">Todo </A></H2>
@@ -85,7 +86,7 @@ sound driver, some graphical niceities, and numerous bug-fixes and other improve
 <LI>
 <A HREF="http://quakespasm.sourceforge.net/download.htm">Project Downloads</A></LI>
 <LI>
-<A HREF="http://quakespasm.ericwa.com/job/quakespasm/">Automatic Builds</A></LI>
+<A HREF="http://quakespasm.ericwa.com/job/quakespasm-sdl2/">Automatic Builds</A></LI>
 </UL>
 </P>
 
@@ -110,7 +111,8 @@ sound driver, some graphical niceities, and numerous bug-fixes and other improve
 <LI>There is currently no CD Music volume support and SDL2 doesn't support CD audio. cd_sdl.c needs replacing with cd_linux.c, cd_bsd.c etc..</LI>
 <LI>In windows, alternative CD drives are accessible by "<B>quakespasm -cddev F</B>" (for example)
 </LI>
-<LI>Quakespasm allows loading new games (mods) on the fly with "<B>game</B> <EM>GAMENAME {-quoth/hipnotic/rogue}</EM>"</LI>
+<LI>Quakespasm allows loading new games (mods) on the fly with "<B>game</B> <EM>GAMENAME {-quoth/hipnotic/rogue}</EM>"
+</LI>
 <LI>Use "<B>quakespasm -condebug</B>" to save console log to "qconsole.log". SDL2 builds no longer generate stdout.txt/stderr.txt.</LI>
 </UL>
 </P>
@@ -186,7 +188,67 @@ these patched libSDL binaries may help.
 
 
 
-<H2><A NAME="ss6.1">6.1</A> <A HREF="#toc6.1">Changes in 0.90.1</A>
+<H2><A NAME="ss6.1">6.1</A> <A HREF="#toc6.1">Changes in 0.91.1</A>
+</H2>
+
+
+<H3>Bugfixes</H3>
+
+<P>
+<UL>
+<LI> Fix unwanted fog mode change upon video restart.</LI>
+<LI> Work around Intel 855 bug in status bar drawing with "r_oldwater 0" and "scr_sbaralpha 0".</LI>
+<LI> Fix an obscure GLSL bug where changing gamma would result in the screen turning to noise.</LI>
+<LI> Fix GLSL gamma causing the tiled screen border to turn white when "sizedown" is used.</LI>
+<LI> Fix an alias model VBO renderer bug where a model not precached during map start wouldn't be drawn.</LI>
+<LI> Fix the order of OpenGL context creation and window creation in SDL2 video.</LI>
+<LI> Fix a calling convention issue in windows DPI awareness function pointers.</LI>
+<LI> Fix a random texture recoloring after video mode change.</LI>
+<LI> Fix a liquid turning to garbage after several video mode changes and "r_oldwater 0".</LI>
+<LI> Fix a wrong alpha-sorting bug introduced in 0.90.1.</LI>
+<LI> Fix "flush" command not reloading mdl's from disk (bug introduced in 0.90.1).</LI>
+<LI> Prevent a possible buffer overflow in Cbuf_Execute (old Q1/Q2 bug).</LI>
+<LI> Prevent a possible vulnerability in MSG_ReadString (old Q1/Q2 bug).</LI>
+</UL>
+</P>
+
+<H3>Visual improvements</H3>
+
+<P>
+<UL>
+<LI> New cvars r_lavaalpha, r_slimealpha, r_telealpha for fine-tuning specific liquid opacities (from DirectQ/RMQEngine, non-archived, default to 0), and new worldspawn keys _wateralpha, _lavaalpha, _slimealpha, _telealpha, _skyfog (unique to Quakespasm, similar to the behaviour of the "fog" worldspawn key).</LI>
+<LI> GLSL gamma is now supported on older hardware without NPOT extension.</LI>
+</UL>
+</P>
+
+<H3>Interface improvements</H3>
+
+<P>
+<UL>
+<LI> New r_pos command to show player position.</LI>
+<LI> NaN detection in traceline with "developer 1" set now warns instead of errors.</LI>
+</UL>
+</P>
+
+<H3>Code cleanup / Other</H3>
+
+<P>
+<UL>
+<LI> Update third-party libraries.</LI>
+</UL>
+</P>
+
+<H3>Raised limits</H3>
+
+<P>
+<UL>
+<LI> Default max_edicts 8192 (was 2048) and no longer saved to config.cfg.</LI>
+<LI> Default heapsize 256 MB (was 64 MB).</LI>
+<LI> Default zone 4 MB (was 384 KB).</LI>
+<LI> Raised MAX_SFX to 1024 (was 512).</LI>
+</UL>
+</P>
+<H2><A NAME="ss6.2">6.2</A> <A HREF="#toc6.2">Changes in 0.90.1</A>
 </H2>
 
 
@@ -197,7 +259,7 @@ these patched libSDL binaries may help.
 <LI> Fix dynamic light artifact where changing lightmap are rendered one frame late (bug introduced in 0.90.0).</LI>
 <LI> Fix texture memory leak when changing video modes with SDL2.</LI>
 <LI> Fix rare incorrect mdl lighting on 64-bit builds. 
-<A HREF="http://forums.inside3d.com/viewtopic.php?f=3&t=5620">(details here.)</A></LI>
+<A HREF="http://forums.insideqc.com/viewtopic.php?f=3&t=5620">(details here.)</A></LI>
 <LI> Fix fullbrights turning black after "kill" command (bug introduced in 0.90.0).</LI>
 <LI> Clear all fog values on map change to prevent colored fog carrying over to jam3_tronyn.bsp.</LI>
 <LI> Allow loading saves with } character in quoted strings, fixes issue with retrojam1_skacky.bsp.</LI>
@@ -246,7 +308,7 @@ these patched libSDL binaries may help.
 <LI> Update 3rd-party libraries.</LI>
 </UL>
 </P>
-<H2><A NAME="ss6.2">6.2</A> <A HREF="#toc6.2">Changes in 0.90.0</A>
+<H2><A NAME="ss6.3">6.3</A> <A HREF="#toc6.3">Changes in 0.90.0</A>
 </H2>
 
 <P>
@@ -291,7 +353,7 @@ these patched libSDL binaries may help.
 <LI> Other fixes and clean-ups.</LI>
 </UL>
 </P>
-<H2><A NAME="ss6.3">6.3</A> <A HREF="#toc6.3">Changes in 0.85.9</A>
+<H2><A NAME="ss6.4">6.4</A> <A HREF="#toc6.4">Changes in 0.85.9</A>
 </H2>
 
 <P>
@@ -315,7 +377,7 @@ these patched libSDL binaries may help.
 <LI> Several other minor fixes/cleanups.</LI>
 </UL>
 </P>
-<H2><A NAME="ss6.4">6.4</A> <A HREF="#toc6.4">Changes in 0.85.8</A>
+<H2><A NAME="ss6.5">6.5</A> <A HREF="#toc6.5">Changes in 0.85.8</A>
 </H2>
 
 <P>
@@ -340,7 +402,7 @@ these patched libSDL binaries may help.
 <LI> Miscellaneous source code cleanups.</LI>
 </UL>
 </P>
-<H2><A NAME="ss6.5">6.5</A> <A HREF="#toc6.5">Changes in 0.85.7</A>
+<H2><A NAME="ss6.6">6.6</A> <A HREF="#toc6.6">Changes in 0.85.7</A>
 </H2>
 
 <P>
@@ -358,7 +420,7 @@ these patched libSDL binaries may help.
 <LI> Several other small changes mostly invisible to the end-user</LI>
 </UL>
 </P>
-<H2><A NAME="ss6.6">6.6</A> <A HREF="#toc6.6">Changes in 0.85.6</A>
+<H2><A NAME="ss6.7">6.7</A> <A HREF="#toc6.7">Changes in 0.85.6</A>
 </H2>
 
 <P>
@@ -369,7 +431,7 @@ these patched libSDL binaries may help.
 <LI> Minor SDL video fixes.</LI>
 </UL>
 </P>
-<H2><A NAME="ss6.7">6.7</A> <A HREF="#toc6.7">Changes in 0.85.5</A>
+<H2><A NAME="ss6.8">6.8</A> <A HREF="#toc6.8">Changes in 0.85.5</A>
 </H2>
 
 <P>
@@ -388,7 +450,7 @@ these patched libSDL binaries may help.
 <LI> Several code updates from uHexen2 project, several code cleanups.</LI>
 </UL>
 </P>
-<H2><A NAME="ss6.8">6.8</A> <A HREF="#toc6.8">Changes in 0.85.4</A>
+<H2><A NAME="ss6.9">6.9</A> <A HREF="#toc6.9">Changes in 0.85.4</A>
 </H2>
 
 <P>
@@ -406,7 +468,7 @@ these patched libSDL binaries may help.
 <LI> Other minor sound and cdaudio updates</LI>
 </UL>
 </P>
-<H2><A NAME="ss6.9">6.9</A> <A HREF="#toc6.9">Changes in 0.85.3</A>
+<H2><A NAME="ss6.10">6.10</A> <A HREF="#toc6.10">Changes in 0.85.3</A>
 </H2>
 
 <P>
@@ -429,7 +491,7 @@ these patched libSDL binaries may help.
 </UL>
 </P>
 
-<H2><A NAME="ss6.10">6.10</A> <A HREF="#toc6.10">Changes in 0.85.2</A>
+<H2><A NAME="ss6.11">6.11</A> <A HREF="#toc6.11">Changes in 0.85.2</A>
 </H2>
 
 <P>
@@ -448,7 +510,7 @@ these patched libSDL binaries may help.
 </UL>
 </P>
 
-<H2><A NAME="ss6.11">6.11</A> <A HREF="#toc6.11">Changes in 0.85.1</A>
+<H2><A NAME="ss6.12">6.12</A> <A HREF="#toc6.12">Changes in 0.85.1</A>
 </H2>
 
 <P>
@@ -523,7 +585,7 @@ these patched libSDL binaries may help.
 <LI>
 <A HREF="http://www.celephais.net/board/view_thread.php?id=60452">Func Quakespasm forum</A></LI>
 <LI>
-<A HREF="http://forums.inside3d.com/viewforum.php?f=14">Inside 3D forums</A></LI>
+<A HREF="http://forums.insideqc.com">Inside3D forums</A></LI>
 </UL>
 </P>
 
diff --git a/Quakespasm.txt b/Quakespasm.txt
index 218b684..4757e4e 100644
--- a/Quakespasm.txt
+++ b/Quakespasm.txt
@@ -16,22 +16,28 @@
 
   5. Known Bugs
   6. Changes
-     6.1 Changes in 0.90.1
+     6.1 Changes in 0.91.1
         6.1.1 Bugfixes
-        6.1.2 Performance
-        6.1.3 Visual improvements
-        6.1.4 Interface improvements
-        6.1.5 Code cleanup
-     6.2 Changes in 0.90.0
-     6.3 Changes in 0.85.9
-     6.4 Changes in 0.85.8
-     6.5 Changes in 0.85.7
-     6.6 Changes in 0.85.6
-     6.7 Changes in 0.85.5
-     6.8 Changes in 0.85.4
-     6.9 Changes in 0.85.3
-     6.10 Changes in 0.85.2
-     6.11 Changes in 0.85.1
+        6.1.2 Visual improvements
+        6.1.3 Interface improvements
+        6.1.4 Code cleanup / Other
+        6.1.5 Raised limits
+     6.2 Changes in 0.90.1
+        6.2.1 Bugfixes
+        6.2.2 Performance
+        6.2.3 Visual improvements
+        6.2.4 Interface improvements
+        6.2.5 Code cleanup
+     6.3 Changes in 0.90.0
+     6.4 Changes in 0.85.9
+     6.5 Changes in 0.85.8
+     6.6 Changes in 0.85.7
+     6.7 Changes in 0.85.6
+     6.8 Changes in 0.85.5
+     6.9 Changes in 0.85.4
+     6.10 Changes in 0.85.3
+     6.11 Changes in 0.85.2
+     6.12 Changes in 0.85.1
 
   7. Todo
   8. Copyright
@@ -41,7 +47,7 @@
   ______________________________________________________________________
 
 
-  Page last edited June 4, 2015
+  Page last edited: December 2015
 
 
   1.  About
@@ -59,7 +65,7 @@
 
   o  Project Downloads: http://quakespasm.sourceforge.net/download.htm
 
-  o  Automatic Builds: http://quakespasm.ericwa.com/job/quakespasm/
+  o  Automatic Builds: http://quakespasm.ericwa.com/job/quakespasm-sdl2/
 
 
   3.  Hints
@@ -192,17 +198,89 @@
   6.  Changes
 
 
-  6.1.  Changes in 0.90.1
+  6.1.  Changes in 0.91.1
 
   6.1.1.  Bugfixes
 
+  o  Fix unwanted fog mode change upon video restart.
+
+  o  Work around Intel 855 bug in status bar drawing with "r_oldwater 0"
+     and "scr_sbaralpha 0".
+
+  o  Fix an obscure GLSL bug where changing gamma would result in the
+     screen turning to noise.
+
+  o  Fix GLSL gamma causing the tiled screen border to turn white when
+     "sizedown" is used.
+
+  o  Fix an alias model VBO renderer bug where a model not precached
+     during map start wouldn't be drawn.
+
+  o  Fix the order of OpenGL context creation and window creation in
+     SDL2 video.
+
+  o  Fix a calling convention issue in windows DPI awareness function
+     pointers.
+
+  o  Fix a random texture recoloring after video mode change.
+
+  o  Fix a liquid turning to garbage after several video mode changes
+     and "r_oldwater 0".
+
+  o  Fix a wrong alpha-sorting bug introduced in 0.90.1.
+
+  o  Fix "flush" command not reloading mdl's from disk (bug introduced
+     in 0.90.1).
+
+  o  Prevent a possible buffer overflow in Cbuf_Execute (old Q1/Q2 bug).
+
+  o  Prevent a possible vulnerability in MSG_ReadString (old Q1/Q2 bug).
+
+  6.1.2.  Visual improvements
+
+  o  New cvars r_lavaalpha, r_slimealpha, r_telealpha for fine-tuning
+     specific liquid opacities (from DirectQ/RMQEngine, non-archived,
+     default to 0), and new worldspawn keys _wateralpha, _lavaalpha,
+     _slimealpha, _telealpha, _skyfog (unique to Quakespasm, similar to
+     the behaviour of the "fog" worldspawn key).
+
+  o  GLSL gamma is now supported on older hardware without NPOT
+     extension.
+
+  6.1.3.  Interface improvements
+
+  o  New r_pos command to show player position.
+
+  o  NaN detection in traceline with "developer 1" set now warns instead
+     of errors.
+
+  6.1.4.  Code cleanup / Other
+
+  o  Update third-party libraries.
+
+  6.1.5.  Raised limits
+
+  o  Default max_edicts 8192 (was 2048) and no longer saved to
+     config.cfg.
+
+  o  Default heapsize 256 MB (was 64 MB).
+
+  o  Default zone 4 MB (was 384 KB).
+
+  o  Raised MAX_SFX to 1024 (was 512).
+
+
+  6.2.  Changes in 0.90.1
+
+  6.2.1.  Bugfixes
+
   o  Fix dynamic light artifact where changing lightmap are rendered one
      frame late (bug introduced in 0.90.0).
 
   o  Fix texture memory leak when changing video modes with SDL2.
 
   o  Fix rare incorrect mdl lighting on 64-bit builds. (details here:
-     http://forums.inside3d.com/viewtopic.php?f=3&t=5620)
+     http://forums.insideqc.com/viewtopic.php?f=3&t=5620)
 
   o  Fix fullbrights turning black after "kill" command (bug introduced
      in 0.90.0).
@@ -217,13 +295,13 @@
 
   o  Fix crash on out-of-bounds skin number.
 
-  6.1.2.  Performance
+  6.2.2.  Performance
 
   o  Use multithreaded OpenGL on OS X for better performance.
 
   o  New, faster mdl renderer using GLSL. Disable with "-noglslalias".
 
-  6.1.3.  Visual improvements
+  6.2.3.  Visual improvements
 
   o  New gamma correction implementation using GLSL. Fixes all known
      gamma issues (affecting the full display, persisting after
@@ -237,7 +315,7 @@
 
   o  r_noshadow_list cvar added (from MarkV.)
 
-  6.1.4.  Interface improvements
+  6.2.4.  Interface improvements
 
   o  Support pausing demo playback with the "pause" command.
 
@@ -254,14 +332,14 @@
      "trying to load ent", "bad chunk length", "meshing",
      "PR_AlocStringSlots: realloc'ing"
 
-  6.1.5.  Code cleanup
+  6.2.5.  Code cleanup
 
   o  Clean up IDE project files to build on fresh systems.
 
   o  Update 3rd-party libraries.
 
 
-  6.2.  Changes in 0.90.0
+  6.3.  Changes in 0.90.0
 
   o  Fix issues on Windows systems with DPI scaling.
 
@@ -369,7 +447,7 @@
   o  Other fixes and clean-ups.
 
 
-  6.3.  Changes in 0.85.9
+  6.4.  Changes in 0.85.9
 
   o  Fixes for several undefined behaviors in C code (gcc-4.8 support.)
 
@@ -416,7 +494,7 @@
   o  Several other minor fixes/cleanups.
 
 
-  6.4.  Changes in 0.85.8
+  6.5.  Changes in 0.85.8
 
   o  Made Quake shareware 1.00 and 1.01 versions to be recognized
      properly.
@@ -463,7 +541,7 @@
   o  Miscellaneous source code cleanups.
 
 
-  6.5.  Changes in 0.85.7
+  6.6.  Changes in 0.85.7
 
   o  Added support for cross-level demo playback
 
@@ -489,7 +567,7 @@
   o  Several other small changes mostly invisible to the end-user
 
 
-  6.6.  Changes in 0.85.6
+  6.7.  Changes in 0.85.6
 
   o  More work for string buffer safety
 
@@ -502,7 +580,7 @@
   o  Minor SDL video fixes.
 
 
-  6.7.  Changes in 0.85.5
+  6.8.  Changes in 0.85.5
 
   o  SDL input driver updated adding native keymap and dead key support
      to the console
@@ -533,7 +611,7 @@
   o  Several code updates from uHexen2 project, several code cleanups.
 
 
-  6.8.  Changes in 0.85.4
+  6.9.  Changes in 0.85.4
 
   o  Implement music (OGG, MP3, WAV) playback
 
@@ -561,7 +639,7 @@
   o  Other minor sound and cdaudio updates
 
 
-  6.9.  Changes in 0.85.3
+  6.10.  Changes in 0.85.3
 
   o  Fix the "-dedicated" option (thanks Oz) and add platform specific
      networking code (default) rather than SDL_net
@@ -598,7 +676,7 @@
      some other CD tweaks.
 
 
-  6.10.  Changes in 0.85.2
+  6.11.  Changes in 0.85.2
 
   o  Replace the old "Screen size" slider with a "Scale" slider
 
@@ -626,7 +704,7 @@
   o  Add OSX Makefile (tested?)
 
 
-  6.11.  Changes in 0.85.1
+  6.12.  Changes in 0.85.1
 
   o  64 bit CPU support
 
@@ -707,4 +785,4 @@
   o  Func Quakespasm forum:
      http://www.celephais.net/board/view_thread.php?id=60452
 
-  o  Inside 3D forums: http://forums.inside3d.com/viewforum.php?f=14
+  o  Inside3D forums: http://forums.insideqc.com

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/quakespasm.git



More information about the Pkg-games-commits mailing list