From e33ed45b7b774a819812d4f7887bd93c107206cc Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 15:59:31 -0400
Subject: [PATCH 01/48] Colormap overhaul in r_data.c

* Split R_CreateColormap to R_CreateLightTable
* Replace extra_colormaps array with next/prev pointer chain
* Remove foundcolormaps; instead store lumpnum in extracolormap_t
* Add properties to extracolormap_t for portability
---
 src/r_data.c  | 333 ++++++++++++++++++++++++++++++++------------------
 src/r_data.h  |   3 +-
 src/r_defs.h  |  12 +-
 src/r_state.h |   3 +-
 4 files changed, 226 insertions(+), 125 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index 18c93787c..1c964993f 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1311,8 +1311,6 @@ void R_ReInitColormaps(UINT16 num)
 	R_ClearColormaps();
 }
 
-static lumpnum_t foundcolormaps[MAXCOLORMAPS];
-
 //
 // R_ClearColormaps
 //
@@ -1320,48 +1318,73 @@ static lumpnum_t foundcolormaps[MAXCOLORMAPS];
 //
 void R_ClearColormaps(void)
 {
-	size_t i;
+	extracolormap_t *exc, *exc_next;
 
-	num_extra_colormaps = 0;
+	for (exc = extra_colormaps; exc; exc = exc_next)
+	{
+		exc_next = exc->next;
+		memset(exc, 0, sizeof(exc));
+	}
 
-	for (i = 0; i < MAXCOLORMAPS; i++)
-		foundcolormaps[i] = LUMPERROR;
+	extra_colormaps = NULL;
+}
 
-	memset(extra_colormaps, 0, sizeof (extra_colormaps));
+//
+// R_AddColormapToList
+//
+// Sets prev/next chain for extra_colormaps var
+// Copypasta from P_AddFFloorToList
+//
+void R_AddColormapToList(extracolormap_t *extra_colormap)
+{
+	extracolormap_t *exc;
+
+	if (!extra_colormaps)
+	{
+		extra_colormaps = extra_colormap;
+		extra_colormap->next = 0;
+		extra_colormap->prev = 0;
+		return;
+	}
+
+	for (exc = extra_colormaps; exc->next; exc = exc->next);
+
+	exc->next = extra_colormap;
+	extra_colormap->prev = exc;
+	extra_colormap->next = 0;
 }
 
 INT32 R_ColormapNumForName(char *name)
 {
-	lumpnum_t lump, i;
-
-	if (num_extra_colormaps == MAXCOLORMAPS)
-		I_Error("R_ColormapNumForName: Too many colormaps! the limit is %d\n", MAXCOLORMAPS);
+	lumpnum_t lump;
+	extracolormap_t *exc;
 
 	lump = R_CheckNumForNameList(name, colormaplumps, numcolormaplumps);
 	if (lump == LUMPERROR)
 		I_Error("R_ColormapNumForName: Cannot find colormap lump %.8s\n", name);
 
-	for (i = 0; i < num_extra_colormaps; i++)
-		if (lump == foundcolormaps[i])
-			return i;
+	for (exc = extra_colormaps; exc; exc = exc->next)
+		if (lump == exc->lump)
+			return exc;
 
-	foundcolormaps[num_extra_colormaps] = lump;
+	exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
+
+	exc->lump = lump;
 
 	// aligned on 8 bit for asm code
-	extra_colormaps[num_extra_colormaps].colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16);
-	W_ReadLump(lump, extra_colormaps[num_extra_colormaps].colormap);
+	exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16);
+	W_ReadLump(lump, exc->colormap);
 
 	// We set all params of the colormap to normal because there
 	// is no real way to tell how GL should handle a colormap lump anyway..
-	extra_colormaps[num_extra_colormaps].maskcolor = 0xffff;
-	extra_colormaps[num_extra_colormaps].fadecolor = 0x0;
-	extra_colormaps[num_extra_colormaps].maskamt = 0x0;
-	extra_colormaps[num_extra_colormaps].fadestart = 0;
-	extra_colormaps[num_extra_colormaps].fadeend = 31;
-	extra_colormaps[num_extra_colormaps].fog = 0;
+	exc->maskcolor = 0xffff;
+	exc->fadecolor = 0x0;
+	exc->maskamt = 0x0;
+	exc->fadestart = 0;
+	exc->fadeend = 31;
+	exc->fog = 0;
 
-	num_extra_colormaps++;
-	return (INT32)num_extra_colormaps - 1;
+	return exc;
 }
 
 //
@@ -1377,105 +1400,30 @@ static double deltas[256][3], map[256][3];
 static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
 static int RoundUp(double number);
 
-INT32 R_CreateColormap(char *p1, char *p2, char *p3)
+lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 {
-	double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
-	double maskamt = 0, othermask = 0;
-	int mask, fog = 0;
-	size_t mapnum = num_extra_colormaps;
-	size_t i;
-	UINT32 cr, cg, cb, maskcolor, fadecolor;
-	UINT32 fadestart = 0, fadeend = 31, fadedist = 31;
+	// "Unpackage" our variables for ease of reading below
+	UINT32 maskcolor = (UINT32)extra_colormap->maskcolor,
+		fadecolor = (UINT32)extra_colormap->fadecolor,
+		fadestart = (UINT16)extra_colormap->fadestart,
+		fadeend = (UINT16)extra_colormap->fadeend,
+		fadedist = extra_colormap->fadedist;
 
-#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
-	if (p1[0] == '#')
-	{
-		cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2]));
-		cmaskr = cr;
-		cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4]));
-		cmaskg = cg;
-		cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
-		cmaskb = cb;
-		// Create a rough approximation of the color (a 16 bit color)
-		maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11);
-		if (p1[7] >= 'a' && p1[7] <= 'z')
-			mask = (p1[7] - 'a');
-		else if (p1[7] >= 'A' && p1[7] <= 'Z')
-			mask = (p1[7] - 'A');
-		else
-			mask = 24;
+	double maskamt = extra_colormap->maskamt,
+		othermask = extra_colormap->othermask,
+		cmaskr = extra_colormap->cmaskr,
+		cmaskg = extra_colormap->cmaskg,
+		cmaskb = extra_colormap->cmaskb,
+		cdestr = extra_colormap->cdestr,
+		cdestg = extra_colormap->cdestg,
+		cdestb = extra_colormap->cdestb;
 
-		maskamt = (double)(mask/24.0l);
+	int fog = extra_colormap->fog;
 
-		othermask = 1 - maskamt;
-		maskamt /= 0xff;
-		cmaskr *= maskamt;
-		cmaskg *= maskamt;
-		cmaskb *= maskamt;
-	}
-	else
-	{
-		cmaskr = cmaskg = cmaskb = 0xff;
-		maskamt = 0;
-		maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11);
-	}
+	INT32 rgba = extra_colormap->rgba,
+		fadergba = extra_colormap->fadergba;
 
-#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0)
-	if (p2[0] == '#')
-	{
-		// Get parameters like fadestart, fadeend, and the fogflag
-		fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
-		fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
-		if (fadestart > 30)
-			fadestart = 0;
-		if (fadeend > 31 || fadeend < 1)
-			fadeend = 31;
-		fadedist = fadeend - fadestart;
-		fog = NUMFROMCHAR(p2[1]);
-	}
-#undef NUMFROMCHAR
-
-	if (p3[0] == '#')
-	{
-		cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
-		cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
-		cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
-		fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11));
-	}
-	else
-		cdestr = cdestg = cdestb = fadecolor = 0;
-#undef HEX2INT
-
-	for (i = 0; i < num_extra_colormaps; i++)
-	{
-		if (foundcolormaps[i] != LUMPERROR)
-			continue;
-		if (maskcolor == extra_colormaps[i].maskcolor
-			&& fadecolor == extra_colormaps[i].fadecolor
-			&& (float)maskamt == (float)extra_colormaps[i].maskamt
-			&& fadestart == extra_colormaps[i].fadestart
-			&& fadeend == extra_colormaps[i].fadeend
-			&& fog == extra_colormaps[i].fog)
-		{
-			return (INT32)i;
-		}
-	}
-
-	if (num_extra_colormaps == MAXCOLORMAPS)
-		I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS);
-
-	num_extra_colormaps++;
-
-	foundcolormaps[mapnum] = LUMPERROR;
-
-	// aligned on 8 bit for asm code
-	extra_colormaps[mapnum].colormap = NULL;
-	extra_colormaps[mapnum].maskcolor = (UINT16)maskcolor;
-	extra_colormaps[mapnum].fadecolor = (UINT16)fadecolor;
-	extra_colormaps[mapnum].maskamt = maskamt;
-	extra_colormaps[mapnum].fadestart = (UINT16)fadestart;
-	extra_colormaps[mapnum].fadeend = (UINT16)fadeend;
-	extra_colormaps[mapnum].fog = fog;
+	lighttable_t *lighttable;
 
 	// This code creates the colormap array used by software renderer
 	if (rendermode == render_soft)
@@ -1513,8 +1461,9 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
 		}
 
 		// Now allocate memory for the actual colormap array itself!
+		// aligned on 8 bit for asm code
 		colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8);
-		extra_colormaps[mapnum].colormap = (UINT8 *)colormap_p;
+		lighttable = (UINT8 *)colormap_p;
 
 		// Calculate the palette index for each palette index, for each light level
 		// (as well as the two unused colormap lines we inherited from Doom)
@@ -1549,7 +1498,149 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
 		}
 	}
 
-	return (INT32)mapnum;
+	return lighttable;
+}
+
+extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
+{
+	double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
+	double maskamt = 0, othermask = 0;
+	int mask, fog = 0;
+	extracolormap_t *extra_colormap, *exc;
+
+	UINT32 cr, cg, cb, maskcolor, fadecolor;
+	UINT32 fadestart = 0, fadeend = 31, fadedist = 31;
+
+	INT32 rgba, fadergba;
+
+#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
+	if (p1[0] == '#')
+	{
+		cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2]));
+		cmaskr = cr;
+		cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4]));
+		cmaskg = cg;
+		cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
+		cmaskb = cb;
+		// Create a rough approximation of the color (a 16 bit color)
+		maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11);
+		if (p1[7] >= 'a' && p1[7] <= 'z')
+			mask = (p1[7] - 'a');
+		else if (p1[7] >= 'A' && p1[7] <= 'Z')
+			mask = (p1[7] - 'A');
+		else
+			mask = 24;
+
+		maskamt = (double)(mask/24.0l);
+
+		othermask = 1 - maskamt;
+		maskamt /= 0xff;
+		cmaskr *= maskamt;
+		cmaskg *= maskamt;
+		cmaskb *= maskamt;
+
+		// package up cmask vars for passing around
+		maskrgba =
+
+		// for opengl; generate on software too for netsync
+		rgba = (HEX2INT(p1[1]) << 4) + (HEX2INT(p1[2]) << 0) +
+			(HEX2INT(p1[3]) << 12) + (HEX2INT(p1[4]) << 8) +
+			(HEX2INT(p1[5]) << 20) + (HEX2INT(p1[6]) << 16);
+
+		if (p1[7] >= 'a' && p1[7] <= 'z' || p1[7] >= 'A' && p1[7] <= 'Z')
+			rgba += (ALPHA2INT(p1[7]) << 24);
+		else
+			rgba += (25 << 24);
+	}
+	else
+	{
+		cmaskr = cmaskg = cmaskb = 0xff;
+		maskamt = 0;
+		maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11);
+		rgba = 0;
+	}
+
+#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0)
+	if (p2[0] == '#')
+	{
+		// Get parameters like fadestart, fadeend, and the fogflag
+		fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
+		fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
+		if (fadestart > 30)
+			fadestart = 0;
+		if (fadeend > 31 || fadeend < 1)
+			fadeend = 31;
+		fadedist = fadeend - fadestart;
+		fog = NUMFROMCHAR(p2[1]);
+	}
+#undef NUMFROMCHAR
+
+	if (p3[0] == '#')
+	{
+		cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
+		cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
+		cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
+		fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11));
+
+		// for opengl; generate on software too for netsync
+		fadergba = (HEX2INT(p3[1]) << 4) + (HEX2INT(p3[2]) << 0) +
+			(HEX2INT(p3[3]) << 12) + (HEX2INT(p3[4]) << 8) +
+			(HEX2INT(p3[5]) << 20) + (HEX2INT(p3[6]) << 16);
+
+		if (p3[7] >= 'a' && p3[7] <= 'z' || p3[7] >= 'A' && p3[7] <= 'Z')
+			fadergba += (ALPHA2INT(p3[7]) << 24);
+		else
+			fadergba += (25 << 24);
+	}
+	else
+	{
+		cdestr = cdestg = cdestb = fadecolor = 0;
+		fadergba = 0x19000000; // default alpha for fade, (25 << 24)
+	}
+#undef HEX2INT
+
+	for (exc = extra_colormaps; exc; exc = exc->next)
+	{
+		if (exc->lump)
+			continue;
+		if (maskcolor == exc->maskcolor
+			&& fadecolor == exc->fadecolor
+			&& (float)maskamt == (float)exc->maskamt
+			&& fadestart == exc->fadestart
+			&& fadeend == exc->fadeend
+			&& fog == exc->fog)
+			return exc;
+	}
+
+	extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL);
+
+	extra_colormap->maskcolor = (UINT16)maskcolor;
+	extra_colormap->fadecolor = (UINT16)fadecolor;
+	extra_colormap->maskamt = maskamt;
+	extra_colormap->othermask = othermask;
+	extra_colormap->fadestart = (UINT16)fadestart;
+	extra_colormap->fadeend = (UINT16)fadeend;
+	extra_colormap->fadedist = fadedist;
+	extra_colormap->fog = fog;
+
+	extra_colormap->cmaskr = cmaskr;
+	extra_colormap->cmaskg = cmaskg;
+	extra_colormap->cmaskb = cmaskb;
+	extra_colormap->cdestr = cdestr;
+	extra_colormap->cdestg = cdestg;
+	extra_colormap->cdestb = cdestb;
+
+	extra_colormap->rgba = rgba;
+	extra_colormap->fadergba = fadergba;
+
+	extra_colormap->lump = LUMPERROR;
+	extra_colormap->next = extra_colormap->prev = NULL;
+
+	extra_colormap->colormap = R_CreateLightTable(extra_colormap);
+
+	R_AddColormapToList(extra_colormap);
+
+	return extra_colormap;
 }
 
 // Thanks to quake2 source!
diff --git a/src/r_data.h b/src/r_data.h
index 250f4d7c2..612c184e4 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -99,7 +99,8 @@ INT32 R_CheckTextureNumForName(const char *name);
 void R_ReInitColormaps(UINT16 num);
 void R_ClearColormaps(void);
 INT32 R_ColormapNumForName(char *name);
-INT32 R_CreateColormap(char *p1, char *p2, char *p3);
+lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
+extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
 const char *R_ColormapNameForNum(INT32 num);
 
 extern INT32 numtextures;
diff --git a/src/r_defs.h b/src/r_defs.h
index 7c8f2a73f..15312114a 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -53,15 +53,25 @@ typedef UINT8 lighttable_t;
 typedef struct
 {
 	UINT16 maskcolor, fadecolor;
-	double maskamt;
+	double maskamt, othermask;
 	UINT16 fadestart, fadeend;
+	UINT32 fadedist;
 	INT32 fog;
 
+	// mask rgb for colormap table generation
+	double cmaskr, cmaskg, cmaskb;
+	double cdestr, cdestg, cdestb;
+
 	// rgba is used in hw mode for colored sector lighting
 	INT32 rgba; // similar to maskcolor in sw mode
 	INT32 fadergba; // The colour the colourmaps fade to
 
 	lighttable_t *colormap;
+
+	lumpnum_t lump; // for colormap lump matching, init to LUMPERROR
+
+	extracolormap_t *next;
+	extracolormap_t *prev;
 } extracolormap_t;
 
 //
diff --git a/src/r_state.h b/src/r_state.h
index ac3e1fa42..effa4e36c 100644
--- a/src/r_state.h
+++ b/src/r_state.h
@@ -43,8 +43,7 @@ extern lighttable_t *colormaps;
 // Had to put a limit on colormaps :(
 #define MAXCOLORMAPS 60
 
-extern size_t num_extra_colormaps;
-extern extracolormap_t extra_colormaps[MAXCOLORMAPS];
+extern extracolormap_t *extra_colormaps;
 
 // for global animation
 extern INT32 *texturetranslation;

From 574a591d434bc1574e54479a443b15b315e422b2 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 16:08:43 -0400
Subject: [PATCH 02/48] P_LoadRawSideDefs2 colormap cleanup (merge ogl and
 software to one block)

---
 src/p_setup.c | 82 +++++----------------------------------------------
 1 file changed, 7 insertions(+), 75 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index 5cc7279c5..a29a6080a 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1474,82 +1474,17 @@ static void P_LoadRawSideDefs2(void *data)
 				// Perhaps we should just call it instead of doing the calculations here.
 				if (rendermode == render_soft || rendermode == render_none)
 				{
-					if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#')
-					{
-						sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture,
-							msd->bottomtexture);
-						sd->toptexture = sd->bottomtexture = 0;
-					}
-					else
-					{
-						if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1)
-							sd->toptexture = 0;
-						else
-							sd->toptexture = num;
-						if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1)
-							sd->midtexture = 0;
-						else
-							sd->midtexture = num;
-						if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1)
-							sd->bottomtexture = 0;
-						else
-							sd->bottomtexture = num;
-					}
-					break;
-				}
+					if (
+						((rendermode == render_soft || rendermode == render_none) && (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#'))
 #ifdef HWRENDER
-				else
-				{
-					// for now, full support of toptexture only
-					if ((msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
-						|| (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]))
+						|| (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
+						|| (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])
+#endif
+					)
 					{
-						char *col;
-
-						sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture,
+						sec->extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
 							msd->bottomtexture);
 						sd->toptexture = sd->bottomtexture = 0;
-#define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
-#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0)
-						sec->extra_colormap = &extra_colormaps[sec->midmap];
-
-						if (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
-						{
-							col = msd->toptexture;
-
-							sec->extra_colormap->rgba =
-								(HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) +
-								(HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) +
-								(HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16);
-
-							// alpha
-							if (msd->toptexture[7])
-								sec->extra_colormap->rgba += (ALPHA2INT(col[7]) << 24);
-							else
-								sec->extra_colormap->rgba += (25 << 24);
-						}
-						else
-							sec->extra_colormap->rgba = 0;
-
-						if (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])
-						{
-							col = msd->bottomtexture;
-
-							sec->extra_colormap->fadergba =
-								(HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) +
-								(HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) +
-								(HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16);
-
-							// alpha
-							if (msd->bottomtexture[7])
-								sec->extra_colormap->fadergba += (ALPHA2INT(col[7]) << 24);
-							else
-								sec->extra_colormap->fadergba += (25 << 24);
-						}
-						else
-							sec->extra_colormap->fadergba = 0x19000000; // default alpha, (25 << 24)
-#undef ALPHA2INT
-#undef HEX2INT
 					}
 					else
 					{
@@ -1557,12 +1492,10 @@ static void P_LoadRawSideDefs2(void *data)
 							sd->toptexture = 0;
 						else
 							sd->toptexture = num;
-
 						if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1)
 							sd->midtexture = 0;
 						else
 							sd->midtexture = num;
-
 						if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1)
 							sd->bottomtexture = 0;
 						else
@@ -1570,7 +1503,6 @@ static void P_LoadRawSideDefs2(void *data)
 					}
 					break;
 				}
-#endif
 
 			case 413: // Change music
 			{

From e0d8a6eec0807afe4dc93fcb65e80e82d2131a73 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 16:16:04 -0400
Subject: [PATCH 03/48] Get rid of bottommap, midmap, topmap

---
 src/p_setup.c |  1 -
 src/p_spec.c  |  2 +-
 src/r_bsp.c   | 25 ++++---------------------
 src/r_defs.h  |  2 --
 4 files changed, 5 insertions(+), 25 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index a29a6080a..eb8489726 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -718,7 +718,6 @@ static void P_LoadRawSectors(UINT8 *data, size_t i)
 		ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0;
 		ss->floorpic_angle = ss->ceilingpic_angle = 0;
 		ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0;
-		ss->bottommap = ss->midmap = ss->topmap = -1;
 		ss->gravity = NULL;
 		ss->cullheight = NULL;
 		ss->verticalflip = false;
diff --git a/src/p_spec.c b/src/p_spec.c
index 6c359c9cc..698c8f4b1 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6760,7 +6760,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
 
 			case 606: // HACK! Copy colormaps. Just plain colormaps.
 				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-					sectors[s].midmap = lines[i].frontsector->midmap;
+					sectors[s].extra_colormap = lines[i].frontsector->extra_colormap;
 				break;
 
 #ifdef ESLOPE // Slope copy specials. Handled here for sanity.
diff --git a/src/r_bsp.c b/src/r_bsp.c
index 183def25a..512aab696 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -234,8 +234,6 @@ static INT32 R_DoorClosed(void)
 sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
 	INT32 *ceilinglightlevel, boolean back)
 {
-	INT32 mapnum = -1;
-
 	if (floorlightlevel)
 		*floorlightlevel = sec->floorlightsec == -1 ?
 			sec->lightlevel : sectors[sec->floorlightsec].lightlevel;
@@ -244,10 +242,10 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
 		*ceilinglightlevel = sec->ceilinglightsec == -1 ?
 			sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel;
 
-	// If the sector has a midmap, it's probably from 280 type
-	if (sec->midmap != -1)
-		mapnum = sec->midmap;
-	else if (sec->heightsec != -1)
+	// if (sec->midmap != -1)
+	//	mapnum = sec->midmap;
+	// In original colormap code, this block did not run if sec->midmap was set
+	if (!sec->extra_colormap && sec->heightsec != -1)
 	{
 		const sector_t *s = &sectors[sec->heightsec];
 		mobj_t *viewmobj = viewplayer->mo;
@@ -271,8 +269,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
 		tempsec->floorheight = s->floorheight;
 		tempsec->ceilingheight = s->ceilingheight;
 
-		mapnum = s->midmap;
-
 		if ((underwater && (tempsec->  floorheight = sec->floorheight,
 			tempsec->ceilingheight = s->floorheight - 1, !back)) || viewz <= s->floorheight)
 		{ // head-below-floor hack
@@ -298,7 +294,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
 					tempsec->ceiling_yoffs = s->ceiling_yoffs;
 					tempsec->ceilingpic_angle = s->ceilingpic_angle;
 				}
-				mapnum = s->bottommap;
 			}
 
 			tempsec->lightlevel = s->lightlevel;
@@ -322,8 +317,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
 			tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs;
 			tempsec->floorpic_angle = tempsec->ceilingpic_angle = s->ceilingpic_angle;
 
-			mapnum = s->topmap;
-
 			if (s->floorpic == skyflatnum) // SKYFIX?
 			{
 				tempsec->ceilingheight = tempsec->floorheight-1;
@@ -354,11 +347,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
 		sec = tempsec;
 	}
 
-	if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps)
-		sec->extra_colormap = &extra_colormaps[mapnum];
-	else
-		sec->extra_colormap = NULL;
-
 	return sec;
 }
 
@@ -1342,11 +1330,6 @@ void R_Prep3DFloors(sector_t *sector)
 		sector->lightlist[i].slope = bestslope;
 #endif
 		sec = &sectors[best->secnum];
-		mapnum = sec->midmap;
-		if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps)
-			sec->extra_colormap = &extra_colormaps[mapnum];
-		else
-			sec->extra_colormap = NULL;
 
 		if (best->flags & FF_NOSHADE)
 		{
diff --git a/src/r_defs.h b/src/r_defs.h
index 15312114a..257e36147 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -333,8 +333,6 @@ typedef struct sector_s
 	INT32 floorlightsec, ceilinglightsec;
 	INT32 crumblestate; // used for crumbling and bobbing
 
-	INT32 bottommap, midmap, topmap; // dynamic colormaps
-
 	// list of mobjs that are at least partially in the sector
 	// thinglist is a subset of touching_thinglist
 	struct msecnode_s *touching_thinglist;

From 2701976ba39124f1687da05018c30644c821f30e Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 16:28:39 -0400
Subject: [PATCH 04/48] Compiler fixes

---
 src/r_bsp.c  |  2 +-
 src/r_data.c | 43 +++++++++++++++----------------------------
 src/r_data.h |  2 +-
 src/r_defs.h |  6 +++---
 src/r_main.c |  3 +--
 5 files changed, 21 insertions(+), 35 deletions(-)

diff --git a/src/r_bsp.c b/src/r_bsp.c
index 512aab696..01676572e 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -1225,7 +1225,7 @@ void R_Prep3DFloors(sector_t *sector)
 	ffloor_t *rover;
 	ffloor_t *best;
 	fixed_t bestheight, maxheight;
-	INT32 count, i, mapnum;
+	INT32 count, i;
 	sector_t *sec;
 #ifdef ESLOPE
 	pslope_t *bestslope = NULL;
diff --git a/src/r_data.c b/src/r_data.c
index 1c964993f..eb5e27b0b 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1323,7 +1323,7 @@ void R_ClearColormaps(void)
 	for (exc = extra_colormaps; exc; exc = exc_next)
 	{
 		exc_next = exc->next;
-		memset(exc, 0, sizeof(exc));
+		memset(exc, 0, sizeof(*exc));
 	}
 
 	extra_colormaps = NULL;
@@ -1354,14 +1354,14 @@ void R_AddColormapToList(extracolormap_t *extra_colormap)
 	extra_colormap->next = 0;
 }
 
-INT32 R_ColormapNumForName(char *name)
+extracolormap_t *R_ColormapForName(char *name)
 {
 	lumpnum_t lump;
 	extracolormap_t *exc;
 
 	lump = R_CheckNumForNameList(name, colormaplumps, numcolormaplumps);
 	if (lump == LUMPERROR)
-		I_Error("R_ColormapNumForName: Cannot find colormap lump %.8s\n", name);
+		I_Error("R_ColormapForName: Cannot find colormap lump %.8s\n", name);
 
 	for (exc = extra_colormaps; exc; exc = exc->next)
 		if (lump == exc->lump)
@@ -1402,15 +1402,10 @@ static int RoundUp(double number);
 
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 {
-	// "Unpackage" our variables for ease of reading below
-	UINT32 maskcolor = (UINT32)extra_colormap->maskcolor,
-		fadecolor = (UINT32)extra_colormap->fadecolor,
-		fadestart = (UINT16)extra_colormap->fadestart,
-		fadeend = (UINT16)extra_colormap->fadeend,
+	UINT32 fadestart = (UINT16)extra_colormap->fadestart,
 		fadedist = extra_colormap->fadedist;
 
-	double maskamt = extra_colormap->maskamt,
-		othermask = extra_colormap->othermask,
+	double othermask = extra_colormap->othermask,
 		cmaskr = extra_colormap->cmaskr,
 		cmaskg = extra_colormap->cmaskg,
 		cmaskb = extra_colormap->cmaskb,
@@ -1418,12 +1413,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 		cdestg = extra_colormap->cdestg,
 		cdestb = extra_colormap->cdestb;
 
-	int fog = extra_colormap->fog;
-
-	INT32 rgba = extra_colormap->rgba,
-		fadergba = extra_colormap->fadergba;
-
-	lighttable_t *lighttable;
+	lighttable_t *lighttable = NULL;
+	size_t i;
 
 	// This code creates the colormap array used by software renderer
 	if (rendermode == render_soft)
@@ -1514,6 +1505,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	INT32 rgba, fadergba;
 
 #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
+#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0)
 	if (p1[0] == '#')
 	{
 		cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2]));
@@ -1539,15 +1531,12 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 		cmaskg *= maskamt;
 		cmaskb *= maskamt;
 
-		// package up cmask vars for passing around
-		maskrgba =
-
 		// for opengl; generate on software too for netsync
 		rgba = (HEX2INT(p1[1]) << 4) + (HEX2INT(p1[2]) << 0) +
 			(HEX2INT(p1[3]) << 12) + (HEX2INT(p1[4]) << 8) +
 			(HEX2INT(p1[5]) << 20) + (HEX2INT(p1[6]) << 16);
 
-		if (p1[7] >= 'a' && p1[7] <= 'z' || p1[7] >= 'A' && p1[7] <= 'Z')
+		if ((p1[7] >= 'a' && p1[7] <= 'z') || (p1[7] >= 'A' && p1[7] <= 'Z'))
 			rgba += (ALPHA2INT(p1[7]) << 24);
 		else
 			rgba += (25 << 24);
@@ -1587,7 +1576,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 			(HEX2INT(p3[3]) << 12) + (HEX2INT(p3[4]) << 8) +
 			(HEX2INT(p3[5]) << 20) + (HEX2INT(p3[6]) << 16);
 
-		if (p3[7] >= 'a' && p3[7] <= 'z' || p3[7] >= 'A' && p3[7] <= 'Z')
+		if ((p3[7] >= 'a' && p3[7] <= 'z') || (p3[7] >= 'A' && p3[7] <= 'Z'))
 			fadergba += (ALPHA2INT(p3[7]) << 24);
 		else
 			fadergba += (25 << 24);
@@ -1597,6 +1586,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 		cdestr = cdestg = cdestb = fadecolor = 0;
 		fadergba = 0x19000000; // default alpha for fade, (25 << 24)
 	}
+#undef ALPHA2INT
 #undef HEX2INT
 
 	for (exc = extra_colormaps; exc; exc = exc->next)
@@ -1683,18 +1673,15 @@ static int RoundUp(double number)
 	return (int)number;
 }
 
-const char *R_ColormapNameForNum(INT32 num)
+const char *R_ColormapNameForColormap(extracolormap_t *extra_colormap)
 {
-	if (num == -1)
+	if (!extra_colormap)
 		return "NONE";
 
-	if (num < 0 || num > MAXCOLORMAPS)
-		I_Error("R_ColormapNameForNum: num %d is invalid!\n", num);
-
-	if (foundcolormaps[num] == LUMPERROR)
+	if (extra_colormap->lump == LUMPERROR)
 		return "INLEVEL";
 
-	return W_CheckNameForNum(foundcolormaps[num]);
+	return W_CheckNameForNum(extra_colormap->lump);
 }
 
 
diff --git a/src/r_data.h b/src/r_data.h
index 612c184e4..db2749834 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -98,7 +98,7 @@ INT32 R_CheckTextureNumForName(const char *name);
 
 void R_ReInitColormaps(UINT16 num);
 void R_ClearColormaps(void);
-INT32 R_ColormapNumForName(char *name);
+extracolormap_t *R_ColormapForName(char *name);
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
 const char *R_ColormapNameForNum(INT32 num);
diff --git a/src/r_defs.h b/src/r_defs.h
index 257e36147..d8915cab8 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -50,7 +50,7 @@ typedef struct
 typedef UINT8 lighttable_t;
 
 // ExtraColormap type. Use for extra_colormaps from now on.
-typedef struct
+typedef struct extracolormap_s
 {
 	UINT16 maskcolor, fadecolor;
 	double maskamt, othermask;
@@ -70,8 +70,8 @@ typedef struct
 
 	lumpnum_t lump; // for colormap lump matching, init to LUMPERROR
 
-	extracolormap_t *next;
-	extracolormap_t *prev;
+	struct extracolormap_s *next;
+	struct extracolormap_s *prev;
 } extracolormap_t;
 
 //
diff --git a/src/r_main.c b/src/r_main.c
index 8e58906d4..281058362 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -118,8 +118,7 @@ lighttable_t *scalelightfixed[MAXLIGHTSCALE];
 lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
 
 // Hack to support extra boom colormaps.
-size_t num_extra_colormaps;
-extracolormap_t extra_colormaps[MAXCOLORMAPS];
+extracolormap_t *extra_colormaps;
 
 static CV_PossibleValue_t drawdist_cons_t[] = {
 	{256, "256"},	{512, "512"},	{768, "768"},

From 53733ddf76440a70cf414c67b8ff5c58e93fe1f3 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 16:32:54 -0400
Subject: [PATCH 05/48] Type 606 renderer check allow OGL again

---
 src/p_setup.c | 53 ++++++++++++++++++++++++---------------------------
 1 file changed, 25 insertions(+), 28 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index eb8489726..09ba553bf 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1471,37 +1471,34 @@ static void P_LoadRawSideDefs2(void *data)
 			case 606: //SoM: 4/4/2000: Just colormap transfer
 				// SoM: R_CreateColormap will only create a colormap in software mode...
 				// Perhaps we should just call it instead of doing the calculations here.
-				if (rendermode == render_soft || rendermode == render_none)
-				{
-					if (
-						((rendermode == render_soft || rendermode == render_none) && (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#'))
+				if (
+					((rendermode == render_soft || rendermode == render_none) && (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#'))
 #ifdef HWRENDER
-						|| (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
-						|| (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])
+					|| (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
+					|| (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])
 #endif
-					)
-					{
-						sec->extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
-							msd->bottomtexture);
-						sd->toptexture = sd->bottomtexture = 0;
-					}
-					else
-					{
-						if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1)
-							sd->toptexture = 0;
-						else
-							sd->toptexture = num;
-						if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1)
-							sd->midtexture = 0;
-						else
-							sd->midtexture = num;
-						if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1)
-							sd->bottomtexture = 0;
-						else
-							sd->bottomtexture = num;
-					}
-					break;
+				)
+				{
+					sec->extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
+						msd->bottomtexture);
+					sd->toptexture = sd->bottomtexture = 0;
 				}
+				else
+				{
+					if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1)
+						sd->toptexture = 0;
+					else
+						sd->toptexture = num;
+					if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1)
+						sd->midtexture = 0;
+					else
+						sd->midtexture = num;
+					if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1)
+						sd->bottomtexture = 0;
+					else
+						sd->bottomtexture = num;
+				}
+				break;
 
 			case 413: // Change music
 			{

From 7608583c6fbe134d6f9ef6677cd2d1b3c26c6cd5 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 16:42:07 -0400
Subject: [PATCH 06/48] Fix shared colormap matching

---
 src/r_data.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/r_data.c b/src/r_data.c
index eb5e27b0b..eef6434b0 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1591,7 +1591,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 
 	for (exc = extra_colormaps; exc; exc = exc->next)
 	{
-		if (exc->lump)
+		if (exc->lump != LUMPERROR)
 			continue;
 		if (maskcolor == exc->maskcolor
 			&& fadecolor == exc->fadecolor

From 7e9297d06e0fbfe104b8749c44d7aa54fa11ce86 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Sun, 9 Sep 2018 12:01:50 -0400
Subject: [PATCH 07/48] Savegame netsync for sector colormaps; add spawn_midmap
 and co for comparison

---
 src/p_saveg.c | 74 ++++++++++++++++++++++++++++++++++++++-------------
 src/p_setup.c |  3 ++-
 src/p_spec.c  |  2 +-
 src/r_defs.h  |  3 +++
 4 files changed, 61 insertions(+), 21 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 22d43f358..1c9589e8f 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -487,10 +487,16 @@ static void P_NetUnArchivePlayers(void)
 #define SD_FYOFFS    0x02
 #define SD_CXOFFS    0x04
 #define SD_CYOFFS    0x08
-#define SD_TAG       0x10
-#define SD_FLOORANG  0x20
-#define SD_CEILANG   0x40
-#define SD_TAGLIST   0x80
+#define SD_FLOORANG  0x10
+#define SD_CEILANG   0x20
+#define SD_TAG       0x40
+#define SD_DIFF3     0x80
+
+// diff3 flags
+#define SD_TAGLIST   0x01
+#define SD_BOTTOMMAP 0x02
+#define SD_MIDMAP    0x04
+#define SD_TOPMAP    0x08
 
 #define LD_FLAG     0x01
 #define LD_SPECIAL  0x02
@@ -523,7 +529,7 @@ static void P_NetArchiveWorld(void)
 	mapsidedef_t *msd;
 	maplinedef_t *mld;
 	const sector_t *ss = sectors;
-	UINT8 diff, diff2;
+	UINT8 diff, diff2, diff3;
 
 	WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
 	put = save_p;
@@ -550,7 +556,7 @@ static void P_NetArchiveWorld(void)
 
 	for (i = 0; i < numsectors; i++, ss++, ms++)
 	{
-		diff = diff2 = 0;
+		diff = diff2 = diff3 = 0;
 		if (ss->floorheight != SHORT(ms->floorheight)<<FRACBITS)
 			diff |= SD_FLOORHT;
 		if (ss->ceilingheight != SHORT(ms->ceilingheight)<<FRACBITS)
@@ -584,7 +590,13 @@ static void P_NetArchiveWorld(void)
 		if (ss->tag != SHORT(ms->tag))
 			diff2 |= SD_TAG;
 		if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag)
-			diff2 |= SD_TAGLIST;
+			diff3 |= SD_TAGLIST;
+		if (ss->bottommap != ss->spawn_bottommap)
+			diff3 |= SD_BOTTOMMAP;
+		if (ss->midmap != ss->spawn_midmap)
+			diff3 |= SD_MIDMAP;
+		if (ss->topmap != ss->spawn_topmap)
+			diff3 |= SD_TOPMAP;
 
 		// Check if any of the sector's FOFs differ from how they spawned
 		if (ss->ffloors)
@@ -601,6 +613,9 @@ static void P_NetArchiveWorld(void)
 			}
 		}
 
+		if (diff3)
+			diff2 |= SD_DIFF3;
+
 		if (diff2)
 			diff |= SD_DIFF2;
 
@@ -612,6 +627,8 @@ static void P_NetArchiveWorld(void)
 			WRITEUINT8(put, diff);
 			if (diff & SD_DIFF2)
 				WRITEUINT8(put, diff2);
+			if (diff2 & SD_DIFF3)
+				WRITEUINT8(put, diff3);
 			if (diff & SD_FLOORHT)
 				WRITEFIXED(put, ss->floorheight);
 			if (diff & SD_CEILHT)
@@ -632,17 +649,23 @@ static void P_NetArchiveWorld(void)
 				WRITEFIXED(put, ss->ceiling_xoffs);
 			if (diff2 & SD_CYOFFS)
 				WRITEFIXED(put, ss->ceiling_yoffs);
-			if (diff2 & SD_TAG) // save only the tag
-				WRITEINT16(put, ss->tag);
 			if (diff2 & SD_FLOORANG)
 				WRITEANGLE(put, ss->floorpic_angle);
 			if (diff2 & SD_CEILANG)
 				WRITEANGLE(put, ss->ceilingpic_angle);
-			if (diff2 & SD_TAGLIST) // save both firsttag and nexttag
+			if (diff2 & SD_TAG) // save only the tag
+				WRITEINT16(put, ss->tag);
+			if (diff3 & SD_TAGLIST) // save both firsttag and nexttag
 			{ // either of these could be changed even if tag isn't
 				WRITEINT32(put, ss->firsttag);
 				WRITEINT32(put, ss->nexttag);
 			}
+			if (diff3 & SD_BOTTOMMAP)
+				WRITEINT32(put, ss->bottommap);
+			if (diff3 & SD_MIDMAP)
+				WRITEINT32(put, ss->midmap);
+			if (diff3 & SD_TOPMAP)
+				WRITEINT32(put, ss->topmap);
 
 			// Special case: save the stats of all modified ffloors along with their ffloor "number"s
 			// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
@@ -680,7 +703,7 @@ static void P_NetArchiveWorld(void)
 	// do lines
 	for (i = 0; i < numlines; i++, mld++, li++)
 	{
-		diff = diff2 = 0;
+		diff = diff2 = diff3 = 0;
 
 		if (li->special != SHORT(mld->special))
 			diff |= LD_SPECIAL;
@@ -772,7 +795,7 @@ static void P_NetUnArchiveWorld(void)
 	line_t *li;
 	side_t *si;
 	UINT8 *get;
-	UINT8 diff, diff2;
+	UINT8 diff, diff2, diff3;
 
 	if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
 		I_Error("Bad $$$.sav at archive block World");
@@ -794,6 +817,10 @@ static void P_NetUnArchiveWorld(void)
 			diff2 = READUINT8(get);
 		else
 			diff2 = 0;
+		if (diff2 & SD_DIFF3)
+			diff3 = READUINT8(get);
+		else
+			diff3 = 0;
 
 		if (diff & SD_FLOORHT)
 			sectors[i].floorheight = READFIXED(get);
@@ -822,17 +849,23 @@ static void P_NetUnArchiveWorld(void)
 			sectors[i].ceiling_xoffs = READFIXED(get);
 		if (diff2 & SD_CYOFFS)
 			sectors[i].ceiling_yoffs = READFIXED(get);
-		if (diff2 & SD_TAG)
-			sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag
-		if (diff2 & SD_TAGLIST)
-		{
-			sectors[i].firsttag = READINT32(get);
-			sectors[i].nexttag = READINT32(get);
-		}
 		if (diff2 & SD_FLOORANG)
 			sectors[i].floorpic_angle  = READANGLE(get);
 		if (diff2 & SD_CEILANG)
 			sectors[i].ceilingpic_angle = READANGLE(get);
+		if (diff2 & SD_TAG)
+			sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag
+		if (diff3 & SD_TAGLIST)
+		{
+			sectors[i].firsttag = READINT32(get);
+			sectors[i].nexttag = READINT32(get);
+		}
+		if (diff3 & SD_BOTTOMMAP)
+			sectors[i].bottommap = READINT32(get);
+		if (diff3 & SD_MIDMAP)
+			sectors[i].midmap = READINT32(get);
+		if (diff3 & SD_TOPMAP)
+			sectors[i].topmap = READINT32(get);
 
 		if (diff & SD_FFLOORS)
 		{
@@ -891,6 +924,9 @@ static void P_NetUnArchiveWorld(void)
 			diff2 = READUINT8(get);
 		else
 			diff2 = 0;
+
+		diff3 = 0;
+
 		if (diff & LD_FLAG)
 			li->flags = READINT16(get);
 		if (diff & LD_SPECIAL)
diff --git a/src/p_setup.c b/src/p_setup.c
index 09ba553bf..b503b6a58 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -713,6 +713,7 @@ static void P_LoadRawSectors(UINT8 *data, size_t i)
 		ss->moved = true;
 
 		ss->extra_colormap = NULL;
+		ss->spawn_extra_colormap = NULL;
 
 		ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0;
 		ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0;
@@ -1479,7 +1480,7 @@ static void P_LoadRawSideDefs2(void *data)
 #endif
 				)
 				{
-					sec->extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
+					sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
 						msd->bottomtexture);
 					sd->toptexture = sd->bottomtexture = 0;
 				}
diff --git a/src/p_spec.c b/src/p_spec.c
index 698c8f4b1..5135676ab 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6760,7 +6760,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
 
 			case 606: // HACK! Copy colormaps. Just plain colormaps.
 				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-					sectors[s].extra_colormap = lines[i].frontsector->extra_colormap;
+					sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = lines[i].frontsector->extra_colormap;
 				break;
 
 #ifdef ESLOPE // Slope copy specials. Handled here for sanity.
diff --git a/src/r_defs.h b/src/r_defs.h
index d8915cab8..e81631eb9 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -401,6 +401,9 @@ typedef struct sector_s
 	// flag angles sector spawned with (via linedef type 7)
 	angle_t spawn_flrpic_angle;
 	angle_t spawn_ceilpic_angle;
+
+	// colormap structure
+	extracolormap_t *spawn_extra_colormap;
 } sector_t;
 
 //

From c92226890e002cee36d5b5700b59724a851ae445 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 09:03:58 -0400
Subject: [PATCH 08/48] Remove bottommap and topmap from savegame because
 unused

---
 src/p_saveg.c | 16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 1c9589e8f..42757faf2 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -494,9 +494,7 @@ static void P_NetUnArchivePlayers(void)
 
 // diff3 flags
 #define SD_TAGLIST   0x01
-#define SD_BOTTOMMAP 0x02
-#define SD_MIDMAP    0x04
-#define SD_TOPMAP    0x08
+#define SD_MIDMAP    0x02
 
 #define LD_FLAG     0x01
 #define LD_SPECIAL  0x02
@@ -591,12 +589,8 @@ static void P_NetArchiveWorld(void)
 			diff2 |= SD_TAG;
 		if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag)
 			diff3 |= SD_TAGLIST;
-		if (ss->bottommap != ss->spawn_bottommap)
-			diff3 |= SD_BOTTOMMAP;
 		if (ss->midmap != ss->spawn_midmap)
 			diff3 |= SD_MIDMAP;
-		if (ss->topmap != ss->spawn_topmap)
-			diff3 |= SD_TOPMAP;
 
 		// Check if any of the sector's FOFs differ from how they spawned
 		if (ss->ffloors)
@@ -660,12 +654,8 @@ static void P_NetArchiveWorld(void)
 				WRITEINT32(put, ss->firsttag);
 				WRITEINT32(put, ss->nexttag);
 			}
-			if (diff3 & SD_BOTTOMMAP)
-				WRITEINT32(put, ss->bottommap);
 			if (diff3 & SD_MIDMAP)
 				WRITEINT32(put, ss->midmap);
-			if (diff3 & SD_TOPMAP)
-				WRITEINT32(put, ss->topmap);
 
 			// Special case: save the stats of all modified ffloors along with their ffloor "number"s
 			// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
@@ -860,12 +850,8 @@ static void P_NetUnArchiveWorld(void)
 			sectors[i].firsttag = READINT32(get);
 			sectors[i].nexttag = READINT32(get);
 		}
-		if (diff3 & SD_BOTTOMMAP)
-			sectors[i].bottommap = READINT32(get);
 		if (diff3 & SD_MIDMAP)
 			sectors[i].midmap = READINT32(get);
-		if (diff3 & SD_TOPMAP)
-			sectors[i].topmap = READINT32(get);
 
 		if (diff & SD_FFLOORS)
 		{

From 8d78c2219474f91b8741854e1ecb67e486dd63c4 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 20:36:34 -0400
Subject: [PATCH 09/48] extracolormap_t refinement and netsyncing

* Store raw values per rgba in extracolormap_t (no maskcolor or fadecolor)
* Crunched some UINT16/32 into UINT8
* Calculate mask values in R_CreateLightTable
* ifdef out EXTRACOLORMAPLUMPS
---
 src/p_saveg.c | 116 +++++++++++++++++++++++++++++++++---
 src/r_data.c  | 160 ++++++++++++++++++++++++++++++++------------------
 src/r_data.h  |  11 +++-
 src/r_defs.h  |  16 ++---
 4 files changed, 228 insertions(+), 75 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 42757faf2..68d00a42c 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -21,6 +21,7 @@
 #include "p_local.h"
 #include "p_setup.h"
 #include "p_saveg.h"
+#include "r_data.h"
 #include "r_things.h"
 #include "r_state.h"
 #include "w_wad.h"
@@ -494,7 +495,7 @@ static void P_NetUnArchivePlayers(void)
 
 // diff3 flags
 #define SD_TAGLIST   0x01
-#define SD_MIDMAP    0x02
+#define SD_COLORMAP  0x02
 
 #define LD_FLAG     0x01
 #define LD_SPECIAL  0x02
@@ -589,8 +590,8 @@ static void P_NetArchiveWorld(void)
 			diff2 |= SD_TAG;
 		if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag)
 			diff3 |= SD_TAGLIST;
-		if (ss->midmap != ss->spawn_midmap)
-			diff3 |= SD_MIDMAP;
+		if (ss->extra_colormap != ss->spawn_extra_colormap)
+			diff3 |= SD_COLORMAP;
 
 		// Check if any of the sector's FOFs differ from how they spawned
 		if (ss->ffloors)
@@ -654,8 +655,30 @@ static void P_NetArchiveWorld(void)
 				WRITEINT32(put, ss->firsttag);
 				WRITEINT32(put, ss->nexttag);
 			}
-			if (diff3 & SD_MIDMAP)
-				WRITEINT32(put, ss->midmap);
+
+			if (diff3 & SD_COLORMAP)
+			{
+				WRITEUINT8(put, ss->extra_colormap->fadestart);
+				WRITEUINT8(put, ss->extra_colormap->fadeend);
+				WRITEUINT8(put, ss->extra_colormap->fadedist);
+				WRITEUINT8(put, (UINT8)ss->extra_colormap->fog);
+
+				WRITEUINT8(put, ss->extra_colormap->cr);
+				WRITEUINT8(put, ss->extra_colormap->cg);
+				WRITEUINT8(put, ss->extra_colormap->cb);
+				WRITEUINT8(put, ss->extra_colormap->ca);
+				WRITEUINT8(put, ss->extra_colormap->cfr);
+				WRITEUINT8(put, ss->extra_colormap->cfg);
+				WRITEUINT8(put, ss->extra_colormap->cfb);
+				WRITEUINT8(put, ss->extra_colormap->cfa);
+
+				WRITEINT32(put, ss->extra_colormap->rgba);
+				WRITEINT32(put, ss->extra_colormap->fadergba);
+
+#ifdef EXTRACOLORMAPLUMPS
+				WRITESTRINGN(put, ss->extra_colormap->lumpname, 9);
+#endif
+			}
 
 			// Special case: save the stats of all modified ffloors along with their ffloor "number"s
 			// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
@@ -850,8 +873,87 @@ static void P_NetUnArchiveWorld(void)
 			sectors[i].firsttag = READINT32(get);
 			sectors[i].nexttag = READINT32(get);
 		}
-		if (diff3 & SD_MIDMAP)
-			sectors[i].midmap = READINT32(get);
+
+		if (diff3 & SD_COLORMAP)
+		{
+			extracolormap_t *exc;
+
+			UINT8 fadestart = READUINT8(get),
+				fadeend = READUINT8(get),
+				fadedist = READUINT8(get);
+
+			boolean fog = (boolean)READUINT8(get);
+
+			UINT8 cr = READUINT8(get),
+				cg = READUINT8(get),
+				cb = READUINT8(get),
+				ca = READUINT8(get),
+				cfr = READUINT8(get),
+				cfg = READUINT8(get),
+				cfb = READUINT8(get),
+				cfa = READUINT8(get);
+
+			INT32 rgba = READINT32(get),
+				fadergba = READINT32(get);
+
+#ifdef EXTRACOLORMAPLUMPS
+			char lumpname[9];
+			READSTRINGN(get, lumpname, 9);
+
+			if (lumpname[0])
+				sectors[i].extra_colormap = R_ColormapForName(lumpname);
+			else
+			{
+#endif
+
+			for (exc = extra_colormaps; exc; exc = exc->next)
+			{
+#ifdef EXTRACOLORMAPLUMPS
+				if (exc->lump != LUMPERROR)
+					continue;
+#endif
+				if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca
+					&& cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa
+					&& fadestart == exc->fadestart
+					&& fadeend == exc->fadeend
+					&& fog == exc->fog)
+					break;
+			}
+
+			if (!exc)
+			{
+				exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
+
+				exc->fadestart = fadestart;
+				exc->fadeend = fadeend;
+				exc->fadedist = fadedist;
+				exc->fog = fog;
+
+				exc->cr = cr;
+				exc->cg = cg;
+				exc->cb = cb;
+				exc->ca = ca;
+				exc->cfr = cfr;
+				exc->cfg = cfg;
+				exc->cfb = cfb;
+				exc->cfa = cfa;
+
+				exc->rgba = rgba;
+				exc->fadergba = fadergba;
+
+				exc->colormap = R_CreateLightTable(exc);
+
+				R_AddColormapToList(exc);
+
+				sectors[i].extra_colormap = exc;
+
+#ifdef EXTRACOLORMAPLUMPS
+				exc->lump = LUMPERROR;
+				exc->lumpname[0] = 0;
+			} // if (!exc) // if (!lumpname[0] || !R_ColormapForName(lumpname))
+#endif
+			}
+		}
 
 		if (diff & SD_FFLOORS)
 		{
diff --git a/src/r_data.c b/src/r_data.c
index eef6434b0..32cf17fa9 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1160,6 +1160,7 @@ static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list
 	return LUMPERROR;
 }
 
+#ifdef EXTRACOLORMAPLUMPS
 static lumplist_t *colormaplumps = NULL; ///\todo free leak
 static size_t numcolormaplumps = 0;
 
@@ -1195,6 +1196,7 @@ static void R_InitExtraColormaps(void)
 	}
 	CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps));
 }
+#endif
 
 // Search for flat name through all
 lumpnum_t R_GetFlatNumForName(const char *name)
@@ -1291,7 +1293,9 @@ static void R_InitColormaps(void)
 
 	// Init Boom colormaps.
 	R_ClearColormaps();
+#ifdef EXTRACOLORMAPLUMPS
 	R_InitExtraColormaps();
+#endif
 }
 
 void R_ReInitColormaps(UINT16 num)
@@ -1354,6 +1358,7 @@ void R_AddColormapToList(extracolormap_t *extra_colormap)
 	extra_colormap->next = 0;
 }
 
+#ifdef EXTRACOLORMAPLUMPS
 extracolormap_t *R_ColormapForName(char *name)
 {
 	lumpnum_t lump;
@@ -1370,6 +1375,8 @@ extracolormap_t *R_ColormapForName(char *name)
 	exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
 
 	exc->lump = lump;
+	strncpy(exc->lumpname, name, 9);
+	exc->lumpname[8] = 0;
 
 	// aligned on 8 bit for asm code
 	exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16);
@@ -1377,15 +1384,21 @@ extracolormap_t *R_ColormapForName(char *name)
 
 	// We set all params of the colormap to normal because there
 	// is no real way to tell how GL should handle a colormap lump anyway..
-	exc->maskcolor = 0xffff;
-	exc->fadecolor = 0x0;
-	exc->maskamt = 0x0;
+	exc->cr = exc->cg = exc->cb = 0xff;
+	exc->ca = 0;
+	exc->cfr = exc->cfg = exc->cfb = 0;
+	exc->cfa = 18;
 	exc->fadestart = 0;
 	exc->fadeend = 31;
 	exc->fog = 0;
+	exc->rgba = 0;
+	exc->fadergba = 0x19000000;
+
+	R_AddColormapToList(exc);
 
 	return exc;
 }
+#endif
 
 //
 // R_CreateColormap
@@ -1402,21 +1415,58 @@ static int RoundUp(double number);
 
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 {
+	double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
+	double maskamt = 0, othermask = 0;
+
+	UINT8 cr = extra_colormap->cr,
+		cg = extra_colormap->cg,
+		cb = extra_colormap->cb,
+		ca = extra_colormap->ca,
+		cfr = extra_colormap->cfr,
+		cfg = extra_colormap->cfg,
+		cfb = extra_colormap->cfb;
+//		cfa = extra_colormap->cfa; // unused in software
+
 	UINT32 fadestart = (UINT16)extra_colormap->fadestart,
 		fadedist = extra_colormap->fadedist;
 
-	double othermask = extra_colormap->othermask,
-		cmaskr = extra_colormap->cmaskr,
-		cmaskg = extra_colormap->cmaskg,
-		cmaskb = extra_colormap->cmaskb,
-		cdestr = extra_colormap->cdestr,
-		cdestg = extra_colormap->cdestg,
-		cdestb = extra_colormap->cdestb;
-
 	lighttable_t *lighttable = NULL;
 	size_t i;
 
+	/////////////////////
+	// Calc the RGBA mask
+	/////////////////////
+	cmaskr = cr;
+	cmaskg = cg;
+	cmaskb = cb;
+
+	maskamt = (double)(ca/24.0l);
+	othermask = 1 - maskamt;
+	maskamt /= 0xff;
+
+	cmaskr *= maskamt;
+	cmaskg *= maskamt;
+	cmaskb *= maskamt;
+
+	/////////////////////
+	// Calc the RGBA fade mask
+	/////////////////////
+	cdestr = cfr;
+	cdestg = cfg;
+	cdestb = cfb;
+
+	// fade alpha unused in software
+	// maskamt = (double)(cfa/24.0l);
+	// othermask = 1 - maskamt;
+	// maskamt /= 0xff;
+
+	// cdestr *= maskamt;
+	// cdestg *= maskamt;
+	// cdestb *= maskamt;
+
+	/////////////////////
 	// This code creates the colormap array used by software renderer
+	/////////////////////
 	if (rendermode == render_soft)
 	{
 		double r, g, b, cbrightness;
@@ -1494,12 +1544,10 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 {
-	double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
-	double maskamt = 0, othermask = 0;
-	int mask, fog = 0;
+	boolean fog = false;
 	extracolormap_t *extra_colormap, *exc;
 
-	UINT32 cr, cg, cb, maskcolor, fadecolor;
+	UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa;
 	UINT32 fadestart = 0, fadeend = 31, fadedist = 31;
 
 	INT32 rgba, fadergba;
@@ -1509,27 +1557,15 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	if (p1[0] == '#')
 	{
 		cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2]));
-		cmaskr = cr;
 		cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4]));
-		cmaskg = cg;
 		cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
-		cmaskb = cb;
-		// Create a rough approximation of the color (a 16 bit color)
-		maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11);
+
 		if (p1[7] >= 'a' && p1[7] <= 'z')
-			mask = (p1[7] - 'a');
+			ca = (p1[7] - 'a');
 		else if (p1[7] >= 'A' && p1[7] <= 'Z')
-			mask = (p1[7] - 'A');
+			ca = (p1[7] - 'A');
 		else
-			mask = 24;
-
-		maskamt = (double)(mask/24.0l);
-
-		othermask = 1 - maskamt;
-		maskamt /= 0xff;
-		cmaskr *= maskamt;
-		cmaskg *= maskamt;
-		cmaskb *= maskamt;
+			ca = 24;
 
 		// for opengl; generate on software too for netsync
 		rgba = (HEX2INT(p1[1]) << 4) + (HEX2INT(p1[2]) << 0) +
@@ -1543,9 +1579,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	}
 	else
 	{
-		cmaskr = cmaskg = cmaskb = 0xff;
-		maskamt = 0;
-		maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11);
+		cr = cg = cb = 0xff;
+		ca = 0;
 		rgba = 0;
 	}
 
@@ -1560,16 +1595,22 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 		if (fadeend > 31 || fadeend < 1)
 			fadeend = 31;
 		fadedist = fadeend - fadestart;
-		fog = NUMFROMCHAR(p2[1]);
+		fog = (boolean)NUMFROMCHAR(p2[1]);
 	}
 #undef NUMFROMCHAR
 
 	if (p3[0] == '#')
 	{
-		cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
-		cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
-		cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
-		fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11));
+		cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
+		cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
+		cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
+
+		if (p1[7] >= 'a' && p1[7] <= 'z')
+			cfa = (p1[7] - 'a');
+		else if (p1[7] >= 'A' && p1[7] <= 'Z')
+			cfa = (p1[7] - 'A');
+		else
+			cfa = 18;
 
 		// for opengl; generate on software too for netsync
 		fadergba = (HEX2INT(p3[1]) << 4) + (HEX2INT(p3[2]) << 0) +
@@ -1583,7 +1624,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	}
 	else
 	{
-		cdestr = cdestg = cdestb = fadecolor = 0;
+		cfr = cfg = cfb = 0;
+		cfa = 18;
 		fadergba = 0x19000000; // default alpha for fade, (25 << 24)
 	}
 #undef ALPHA2INT
@@ -1591,40 +1633,41 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 
 	for (exc = extra_colormaps; exc; exc = exc->next)
 	{
+#ifdef EXTRACOLORMAPLUMPS
 		if (exc->lump != LUMPERROR)
 			continue;
-		if (maskcolor == exc->maskcolor
-			&& fadecolor == exc->fadecolor
-			&& (float)maskamt == (float)exc->maskamt
+#endif
+		if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca
+			&& cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa
 			&& fadestart == exc->fadestart
 			&& fadeend == exc->fadeend
 			&& fog == exc->fog)
-			return exc;
+			break;
 	}
 
 	extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL);
 
-	extra_colormap->maskcolor = (UINT16)maskcolor;
-	extra_colormap->fadecolor = (UINT16)fadecolor;
-	extra_colormap->maskamt = maskamt;
-	extra_colormap->othermask = othermask;
 	extra_colormap->fadestart = (UINT16)fadestart;
 	extra_colormap->fadeend = (UINT16)fadeend;
 	extra_colormap->fadedist = fadedist;
 	extra_colormap->fog = fog;
 
-	extra_colormap->cmaskr = cmaskr;
-	extra_colormap->cmaskg = cmaskg;
-	extra_colormap->cmaskb = cmaskb;
-	extra_colormap->cdestr = cdestr;
-	extra_colormap->cdestg = cdestg;
-	extra_colormap->cdestb = cdestb;
+	extra_colormap->cr = cr;
+	extra_colormap->cg = cg;
+	extra_colormap->cb = cb;
+	extra_colormap->ca = ca;
+	extra_colormap->cfr = cfr;
+	extra_colormap->cfg = cfg;
+	extra_colormap->cfb = cfb;
+	extra_colormap->cfa = cfa;
 
 	extra_colormap->rgba = rgba;
 	extra_colormap->fadergba = fadergba;
 
+#ifdef EXTRACOLORMAPLUMPS
 	extra_colormap->lump = LUMPERROR;
-	extra_colormap->next = extra_colormap->prev = NULL;
+	extra_colormap->lumpname[0] = 0;
+#endif
 
 	extra_colormap->colormap = R_CreateLightTable(extra_colormap);
 
@@ -1673,7 +1716,8 @@ static int RoundUp(double number)
 	return (int)number;
 }
 
-const char *R_ColormapNameForColormap(extracolormap_t *extra_colormap)
+#ifdef EXTRACOLORMAPLUMPS
+const char *R_NameForColormap(extracolormap_t *extra_colormap)
 {
 	if (!extra_colormap)
 		return "NONE";
@@ -1681,9 +1725,9 @@ const char *R_ColormapNameForColormap(extracolormap_t *extra_colormap)
 	if (extra_colormap->lump == LUMPERROR)
 		return "INLEVEL";
 
-	return W_CheckNameForNum(extra_colormap->lump);
+	return extra_colormap->lumpname;
 }
-
+#endif
 
 //
 // build a table for quick conversion from 8bpp to 15bpp
diff --git a/src/r_data.h b/src/r_data.h
index db2749834..5600d36dc 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -96,12 +96,19 @@ void R_ClearTextureNumCache(boolean btell);
 INT32 R_TextureNumForName(const char *name);
 INT32 R_CheckTextureNumForName(const char *name);
 
+// Extra Colormap lumps (C_START/C_END) are not used anywhere
+// Uncomment to enable
+//#define EXTRACOLORMAPLUMPS
+
 void R_ReInitColormaps(UINT16 num);
 void R_ClearColormaps(void);
-extracolormap_t *R_ColormapForName(char *name);
+void R_AddColormapToList(extracolormap_t *extra_colormap);
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
-const char *R_ColormapNameForNum(INT32 num);
+#ifdef EXTRACOLORMAPLUMPS
+extracolormap_t *R_ColormapForName(char *name);
+const char *R_NameForColormap(extracolormap_t *extra_colormap);
+#endif
 
 extern INT32 numtextures;
 
diff --git a/src/r_defs.h b/src/r_defs.h
index e81631eb9..8dd34cd15 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -52,15 +52,12 @@ typedef UINT8 lighttable_t;
 // ExtraColormap type. Use for extra_colormaps from now on.
 typedef struct extracolormap_s
 {
-	UINT16 maskcolor, fadecolor;
-	double maskamt, othermask;
-	UINT16 fadestart, fadeend;
-	UINT32 fadedist;
-	INT32 fog;
+	UINT8 fadestart, fadeend;
+	UINT8 fadedist;
+	boolean fog;
 
-	// mask rgb for colormap table generation
-	double cmaskr, cmaskg, cmaskb;
-	double cdestr, cdestg, cdestb;
+	// rgba for colormap table generation
+	UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa;
 
 	// rgba is used in hw mode for colored sector lighting
 	INT32 rgba; // similar to maskcolor in sw mode
@@ -68,7 +65,10 @@ typedef struct extracolormap_s
 
 	lighttable_t *colormap;
 
+#ifdef EXTRACOLORMAPLUMPS
 	lumpnum_t lump; // for colormap lump matching, init to LUMPERROR
+	char lumpname[9]; // for netsyncing
+#endif
 
 	struct extracolormap_s *next;
 	struct extracolormap_s *prev;

From 1e4f5e8d45db305297c3f23088b8eec91d4d6274 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 20:41:12 -0400
Subject: [PATCH 10/48] Remove MAXCOLORMAPS

---
 src/r_state.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/r_state.h b/src/r_state.h
index effa4e36c..91c2092e9 100644
--- a/src/r_state.h
+++ b/src/r_state.h
@@ -40,9 +40,6 @@ extern sprcache_t *spritecachedinfo;
 extern lighttable_t *colormaps;
 
 // Boom colormaps.
-// Had to put a limit on colormaps :(
-#define MAXCOLORMAPS 60
-
 extern extracolormap_t *extra_colormaps;
 
 // for global animation

From 3da38f2a9be36ab980a61fae3a0b18dc58a7d1c0 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 20:52:37 -0400
Subject: [PATCH 11/48] Fixed colormap matching code again * Added debug
 messages for matching code

---
 src/p_saveg.c | 26 ++++++++++++++++++++++++++
 src/r_data.c  | 15 ++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 68d00a42c..137b4ffd0 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -877,6 +877,7 @@ static void P_NetUnArchiveWorld(void)
 		if (diff3 & SD_COLORMAP)
 		{
 			extracolormap_t *exc;
+			size_t dbg_i = 0;
 
 			UINT8 fadestart = READUINT8(get),
 				fadeend = READUINT8(get),
@@ -920,8 +921,33 @@ static void P_NetUnArchiveWorld(void)
 					break;
 			}
 
+			for (exc = extra_colormaps; exc; exc = exc->next)
+			{
+#ifdef EXTRACOLORMAPLUMPS
+				if (exc->lump != LUMPERROR)
+				{
+					dbg_i++;
+					continue;
+				}
+#endif
+				if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca
+					&& cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa
+					&& fadestart == exc->fadestart
+					&& fadeend == exc->fadeend
+					&& fog == exc->fog)
+				{
+					CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+						dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
+					break;
+				}
+				dbg_i++;
+			}
+
 			if (!exc)
 			{
+				CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+					dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
+
 				exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
 
 				exc->fadestart = fadestart;
diff --git a/src/r_data.c b/src/r_data.c
index 32cf17fa9..e51eb32e9 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1552,6 +1552,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 
 	INT32 rgba, fadergba;
 
+	size_t dbg_i = 0;
+
 #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
 #define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0)
 	if (p1[0] == '#')
@@ -1635,16 +1637,27 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	{
 #ifdef EXTRACOLORMAPLUMPS
 		if (exc->lump != LUMPERROR)
+		{
+			dbg_i++;
 			continue;
+		}
 #endif
 		if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca
 			&& cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa
 			&& fadestart == exc->fadestart
 			&& fadeend == exc->fadeend
 			&& fog == exc->fog)
-			break;
+		{
+			CONS_Debug(DBG_RENDER, "R_CreateColormap: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+				dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
+			return exc;
+		}
+		dbg_i++;
 	}
 
+	CONS_Debug(DBG_RENDER, "R_CreateColormap: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+		dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
+
 	extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL);
 
 	extra_colormap->fadestart = (UINT16)fadestart;

From 22746c1d9140446edc1bac8b0a9358b273a43fd7 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 21:12:56 -0400
Subject: [PATCH 12/48] Savegame fixes

---
 src/p_saveg.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 137b4ffd0..66db8a383 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -877,7 +877,7 @@ static void P_NetUnArchiveWorld(void)
 		if (diff3 & SD_COLORMAP)
 		{
 			extracolormap_t *exc;
-			size_t dbg_i = 0;
+			//size_t dbg_i = 0;
 
 			UINT8 fadestart = READUINT8(get),
 				fadeend = READUINT8(get),
@@ -926,7 +926,7 @@ static void P_NetUnArchiveWorld(void)
 #ifdef EXTRACOLORMAPLUMPS
 				if (exc->lump != LUMPERROR)
 				{
-					dbg_i++;
+					//dbg_i++;
 					continue;
 				}
 #endif
@@ -936,17 +936,17 @@ static void P_NetUnArchiveWorld(void)
 					&& fadeend == exc->fadeend
 					&& fog == exc->fog)
 				{
-					CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-						dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
+					// CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+					// 	dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
 					break;
 				}
-				dbg_i++;
+				//dbg_i++;
 			}
 
 			if (!exc)
 			{
-				CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-					dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
+				// CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+				// 	dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
 
 				exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
 
@@ -971,14 +971,16 @@ static void P_NetUnArchiveWorld(void)
 
 				R_AddColormapToList(exc);
 
-				sectors[i].extra_colormap = exc;
-
 #ifdef EXTRACOLORMAPLUMPS
 				exc->lump = LUMPERROR;
 				exc->lumpname[0] = 0;
-			} // if (!exc) // if (!lumpname[0] || !R_ColormapForName(lumpname))
 #endif
 			}
+
+			sectors[i].extra_colormap = exc;
+#ifdef EXTRACOLORMAPLUMPS
+			}
+#endif
 		}
 
 		if (diff & SD_FFLOORS)

From 43ae25c4fd3b0e912e6ff433701aaa0c19f35224 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 21:56:09 -0400
Subject: [PATCH 13/48] Make default extracolormap on init

* Calc fadedist in R_CreateLightTable
---
 src/p_saveg.c |  5 +----
 src/r_data.c  | 28 ++++++++++++++++++++++------
 src/r_defs.h  |  1 -
 3 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 66db8a383..7ee41dffd 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -660,7 +660,6 @@ static void P_NetArchiveWorld(void)
 			{
 				WRITEUINT8(put, ss->extra_colormap->fadestart);
 				WRITEUINT8(put, ss->extra_colormap->fadeend);
-				WRITEUINT8(put, ss->extra_colormap->fadedist);
 				WRITEUINT8(put, (UINT8)ss->extra_colormap->fog);
 
 				WRITEUINT8(put, ss->extra_colormap->cr);
@@ -880,8 +879,7 @@ static void P_NetUnArchiveWorld(void)
 			//size_t dbg_i = 0;
 
 			UINT8 fadestart = READUINT8(get),
-				fadeend = READUINT8(get),
-				fadedist = READUINT8(get);
+				fadeend = READUINT8(get);
 
 			boolean fog = (boolean)READUINT8(get);
 
@@ -952,7 +950,6 @@ static void P_NetUnArchiveWorld(void)
 
 				exc->fadestart = fadestart;
 				exc->fadeend = fadeend;
-				exc->fadedist = fadedist;
 				exc->fog = fog;
 
 				exc->cr = cr;
diff --git a/src/r_data.c b/src/r_data.c
index e51eb32e9..f1f04b2d2 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1330,7 +1330,25 @@ void R_ClearColormaps(void)
 		memset(exc, 0, sizeof(*exc));
 	}
 
-	extra_colormaps = NULL;
+	// make a default extra_colormap
+	exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
+	exc->cr = exc->cg = exc->cb = 0xff;
+	exc->ca = 0;
+	exc->cfr = exc->cfg = exc->cfb = 0;
+	exc->cfa = 18;
+	exc->fadestart = 0;
+	exc->fadeend = 31;
+	exc->fog = 0;
+	exc->rgba = 0;
+	exc->fadergba = 0x19000000;
+	exc->colormap = R_CreateLightTable(exc);
+#ifdef EXTRACOLORMAPLUMPS
+	exc->lump = LUMPERROR;
+	exc->lumpname[0] = 0;
+#endif
+	exc->next = exc->prev = NULL;
+
+	extra_colormaps = exc;
 }
 
 //
@@ -1427,8 +1445,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 		cfb = extra_colormap->cfb;
 //		cfa = extra_colormap->cfa; // unused in software
 
-	UINT32 fadestart = (UINT16)extra_colormap->fadestart,
-		fadedist = extra_colormap->fadedist;
+	UINT8 fadestart = extra_colormap->fadestart,
+		fadedist = extra_colormap->fadeend - extra_colormap->fadestart;
 
 	lighttable_t *lighttable = NULL;
 	size_t i;
@@ -1548,7 +1566,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	extracolormap_t *extra_colormap, *exc;
 
 	UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa;
-	UINT32 fadestart = 0, fadeend = 31, fadedist = 31;
+	UINT32 fadestart = 0, fadeend = 31;
 
 	INT32 rgba, fadergba;
 
@@ -1596,7 +1614,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 			fadestart = 0;
 		if (fadeend > 31 || fadeend < 1)
 			fadeend = 31;
-		fadedist = fadeend - fadestart;
 		fog = (boolean)NUMFROMCHAR(p2[1]);
 	}
 #undef NUMFROMCHAR
@@ -1662,7 +1679,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 
 	extra_colormap->fadestart = (UINT16)fadestart;
 	extra_colormap->fadeend = (UINT16)fadeend;
-	extra_colormap->fadedist = fadedist;
 	extra_colormap->fog = fog;
 
 	extra_colormap->cr = cr;
diff --git a/src/r_defs.h b/src/r_defs.h
index 8dd34cd15..22d4fdf14 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -53,7 +53,6 @@ typedef UINT8 lighttable_t;
 typedef struct extracolormap_s
 {
 	UINT8 fadestart, fadeend;
-	UINT8 fadedist;
 	boolean fog;
 
 	// rgba for colormap table generation

From b7a216c78b6121642a9a9dafc501cfe565ac2ca3 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 10 Sep 2018 22:35:03 -0400
Subject: [PATCH 14/48] Add COLORMAPREVERSELIST ifdef to toggle Newest ->
 Oldest extra_colormaps order

---
 src/r_data.c | 9 +++++++++
 src/r_data.h | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/src/r_data.c b/src/r_data.c
index f1f04b2d2..ffc6cc7fd 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1359,7 +1359,9 @@ void R_ClearColormaps(void)
 //
 void R_AddColormapToList(extracolormap_t *extra_colormap)
 {
+#ifndef COLORMAPREVERSELIST
 	extracolormap_t *exc;
+#endif
 
 	if (!extra_colormaps)
 	{
@@ -1369,11 +1371,18 @@ void R_AddColormapToList(extracolormap_t *extra_colormap)
 		return;
 	}
 
+#ifdef COLORMAPREVERSELIST
+	extra_colormaps->prev = extra_colormap;
+	extra_colormap->next = extra_colormaps;
+	extra_colormaps = extra_colormap;
+	extra_colormap->prev = 0;
+#else
 	for (exc = extra_colormaps; exc->next; exc = exc->next);
 
 	exc->next = extra_colormap;
 	extra_colormap->prev = exc;
 	extra_colormap->next = 0;
+#endif
 }
 
 #ifdef EXTRACOLORMAPLUMPS
diff --git a/src/r_data.h b/src/r_data.h
index 5600d36dc..e6eec41b4 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -100,6 +100,9 @@ INT32 R_CheckTextureNumForName(const char *name);
 // Uncomment to enable
 //#define EXTRACOLORMAPLUMPS
 
+// Uncomment to make extra_colormaps order Newest -> Oldest
+//#define COLORMAPREVERSELIST
+
 void R_ReInitColormaps(UINT16 num);
 void R_ClearColormaps(void);
 void R_AddColormapToList(extracolormap_t *extra_colormap);

From a818b9a1dc0598e88eb24d912979f0cfcff0c06d Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 13:10:14 -0400
Subject: [PATCH 15/48] Remove cr/cg/cb/ca in favor of rgba * Change default
 colormap values to be in sync with rgba/fadergba

---
 src/p_saveg.c | 51 +++++----------------------------------
 src/r_data.c  | 66 +++++++++++++--------------------------------------
 src/r_defs.h  |  6 ++---
 3 files changed, 24 insertions(+), 99 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 7ee41dffd..710c24821 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -662,15 +662,6 @@ static void P_NetArchiveWorld(void)
 				WRITEUINT8(put, ss->extra_colormap->fadeend);
 				WRITEUINT8(put, (UINT8)ss->extra_colormap->fog);
 
-				WRITEUINT8(put, ss->extra_colormap->cr);
-				WRITEUINT8(put, ss->extra_colormap->cg);
-				WRITEUINT8(put, ss->extra_colormap->cb);
-				WRITEUINT8(put, ss->extra_colormap->ca);
-				WRITEUINT8(put, ss->extra_colormap->cfr);
-				WRITEUINT8(put, ss->extra_colormap->cfg);
-				WRITEUINT8(put, ss->extra_colormap->cfb);
-				WRITEUINT8(put, ss->extra_colormap->cfa);
-
 				WRITEINT32(put, ss->extra_colormap->rgba);
 				WRITEINT32(put, ss->extra_colormap->fadergba);
 
@@ -883,15 +874,6 @@ static void P_NetUnArchiveWorld(void)
 
 			boolean fog = (boolean)READUINT8(get);
 
-			UINT8 cr = READUINT8(get),
-				cg = READUINT8(get),
-				cb = READUINT8(get),
-				ca = READUINT8(get),
-				cfr = READUINT8(get),
-				cfg = READUINT8(get),
-				cfb = READUINT8(get),
-				cfa = READUINT8(get);
-
 			INT32 rgba = READINT32(get),
 				fadergba = READINT32(get);
 
@@ -905,20 +887,6 @@ static void P_NetUnArchiveWorld(void)
 			{
 #endif
 
-			for (exc = extra_colormaps; exc; exc = exc->next)
-			{
-#ifdef EXTRACOLORMAPLUMPS
-				if (exc->lump != LUMPERROR)
-					continue;
-#endif
-				if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca
-					&& cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa
-					&& fadestart == exc->fadestart
-					&& fadeend == exc->fadeend
-					&& fog == exc->fog)
-					break;
-			}
-
 			for (exc = extra_colormaps; exc; exc = exc->next)
 			{
 #ifdef EXTRACOLORMAPLUMPS
@@ -928,14 +896,15 @@ static void P_NetUnArchiveWorld(void)
 					continue;
 				}
 #endif
-				if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca
-					&& cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa
+				if (rgba == exc->rgba
+					&& fadergba == exc->fadergba
 					&& fadestart == exc->fadestart
 					&& fadeend == exc->fadeend
 					&& fog == exc->fog)
 				{
 					// CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-					// 	dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
+					// 	dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
+					//	(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
 					break;
 				}
 				//dbg_i++;
@@ -944,7 +913,8 @@ static void P_NetUnArchiveWorld(void)
 			if (!exc)
 			{
 				// CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-				// 	dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
+				// 	dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
+				//	(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
 
 				exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
 
@@ -952,15 +922,6 @@ static void P_NetUnArchiveWorld(void)
 				exc->fadeend = fadeend;
 				exc->fog = fog;
 
-				exc->cr = cr;
-				exc->cg = cg;
-				exc->cb = cb;
-				exc->ca = ca;
-				exc->cfr = cfr;
-				exc->cfg = cfg;
-				exc->cfb = cfb;
-				exc->cfa = cfa;
-
 				exc->rgba = rgba;
 				exc->fadergba = fadergba;
 
diff --git a/src/r_data.c b/src/r_data.c
index ffc6cc7fd..005056ec0 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1332,10 +1332,6 @@ void R_ClearColormaps(void)
 
 	// make a default extra_colormap
 	exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
-	exc->cr = exc->cg = exc->cb = 0xff;
-	exc->ca = 0;
-	exc->cfr = exc->cfg = exc->cfb = 0;
-	exc->cfa = 18;
 	exc->fadestart = 0;
 	exc->fadeend = 31;
 	exc->fog = 0;
@@ -1411,10 +1407,6 @@ extracolormap_t *R_ColormapForName(char *name)
 
 	// We set all params of the colormap to normal because there
 	// is no real way to tell how GL should handle a colormap lump anyway..
-	exc->cr = exc->cg = exc->cb = 0xff;
-	exc->ca = 0;
-	exc->cfr = exc->cfg = exc->cfb = 0;
-	exc->cfa = 18;
 	exc->fadestart = 0;
 	exc->fadeend = 31;
 	exc->fog = 0;
@@ -1445,14 +1437,14 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 	double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
 	double maskamt = 0, othermask = 0;
 
-	UINT8 cr = extra_colormap->cr,
-		cg = extra_colormap->cg,
-		cb = extra_colormap->cb,
-		ca = extra_colormap->ca,
-		cfr = extra_colormap->cfr,
-		cfg = extra_colormap->cfg,
-		cfb = extra_colormap->cfb;
-//		cfa = extra_colormap->cfa; // unused in software
+	UINT8 cr = (extra_colormap->rgba) & 0xFF,
+		cg = (extra_colormap->rgba >> 8) & 0xFF,
+		cb = (extra_colormap->rgba >> 16) & 0xFF,
+		ca = (extra_colormap->rgba >> 24) & 0xFF,
+		cfr = (extra_colormap->fadergba) & 0xFF,
+		cfg = (extra_colormap->fadergba >> 8) & 0xFF,
+		cfb = (extra_colormap->fadergba >> 16) & 0xFF;
+//		cfa = (extra_colormap->fadergba >> 24) & 0xFF; // unused in software
 
 	UINT8 fadestart = extra_colormap->fadestart,
 		fadedist = extra_colormap->fadeend - extra_colormap->fadestart;
@@ -1594,22 +1586,13 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 		else if (p1[7] >= 'A' && p1[7] <= 'Z')
 			ca = (p1[7] - 'A');
 		else
-			ca = 24;
+			ca = 25;
 
-		// for opengl; generate on software too for netsync
-		rgba = (HEX2INT(p1[1]) << 4) + (HEX2INT(p1[2]) << 0) +
-			(HEX2INT(p1[3]) << 12) + (HEX2INT(p1[4]) << 8) +
-			(HEX2INT(p1[5]) << 20) + (HEX2INT(p1[6]) << 16);
-
-		if ((p1[7] >= 'a' && p1[7] <= 'z') || (p1[7] >= 'A' && p1[7] <= 'Z'))
-			rgba += (ALPHA2INT(p1[7]) << 24);
-		else
-			rgba += (25 << 24);
+		rgba = cr + (cg << 8) + (cb << 16) + (ca << 24);
 	}
 	else
 	{
-		cr = cg = cb = 0xff;
-		ca = 0;
+		cr = cg = cb = ca = 0;
 		rgba = 0;
 	}
 
@@ -1638,22 +1621,14 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 		else if (p1[7] >= 'A' && p1[7] <= 'Z')
 			cfa = (p1[7] - 'A');
 		else
-			cfa = 18;
+			cfa = 25;
 
-		// for opengl; generate on software too for netsync
-		fadergba = (HEX2INT(p3[1]) << 4) + (HEX2INT(p3[2]) << 0) +
-			(HEX2INT(p3[3]) << 12) + (HEX2INT(p3[4]) << 8) +
-			(HEX2INT(p3[5]) << 20) + (HEX2INT(p3[6]) << 16);
-
-		if ((p3[7] >= 'a' && p3[7] <= 'z') || (p3[7] >= 'A' && p3[7] <= 'Z'))
-			fadergba += (ALPHA2INT(p3[7]) << 24);
-		else
-			fadergba += (25 << 24);
+		fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24);
 	}
 	else
 	{
 		cfr = cfg = cfb = 0;
-		cfa = 18;
+		cfa = 25;
 		fadergba = 0x19000000; // default alpha for fade, (25 << 24)
 	}
 #undef ALPHA2INT
@@ -1668,8 +1643,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 			continue;
 		}
 #endif
-		if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca
-			&& cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa
+		if (rgba == exc->rgba
+			&& fadergba == exc->fadergba
 			&& fadestart == exc->fadestart
 			&& fadeend == exc->fadeend
 			&& fog == exc->fog)
@@ -1690,15 +1665,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	extra_colormap->fadeend = (UINT16)fadeend;
 	extra_colormap->fog = fog;
 
-	extra_colormap->cr = cr;
-	extra_colormap->cg = cg;
-	extra_colormap->cb = cb;
-	extra_colormap->ca = ca;
-	extra_colormap->cfr = cfr;
-	extra_colormap->cfg = cfg;
-	extra_colormap->cfb = cfb;
-	extra_colormap->cfa = cfa;
-
 	extra_colormap->rgba = rgba;
 	extra_colormap->fadergba = fadergba;
 
diff --git a/src/r_defs.h b/src/r_defs.h
index 22d4fdf14..99fad2b44 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -55,10 +55,8 @@ typedef struct extracolormap_s
 	UINT8 fadestart, fadeend;
 	boolean fog;
 
-	// rgba for colormap table generation
-	UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa;
-
-	// rgba is used in hw mode for colored sector lighting
+	// store rgba values in combined bitwise
+	// also used in OpenGL instead lighttables
 	INT32 rgba; // similar to maskcolor in sw mode
 	INT32 fadergba; // The colour the colourmaps fade to
 

From 506ce43627c2d954da8f12bb1c76b2828a116189 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 13:31:09 -0400
Subject: [PATCH 16/48] Initialize extra_colormaps to NULL on program start

---
 src/r_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/r_main.c b/src/r_main.c
index 281058362..bfca180d0 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -118,7 +118,7 @@ lighttable_t *scalelightfixed[MAXLIGHTSCALE];
 lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
 
 // Hack to support extra boom colormaps.
-extracolormap_t *extra_colormaps;
+extracolormap_t *extra_colormaps = NULL;
 
 static CV_PossibleValue_t drawdist_cons_t[] = {
 	{256, "256"},	{512, "512"},	{768, "768"},

From 4ef016e40fe9fdb5b0abb9fd3e101e0efd2f7a98 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 13:46:34 -0400
Subject: [PATCH 17/48] Clear colormaps properly (resolve sigsegv crash)

---
 src/r_data.c | 23 +++++++++++------------
 src/r_data.h |  1 +
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index 005056ec0..4358f7536 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1322,29 +1322,28 @@ void R_ReInitColormaps(UINT16 num)
 //
 void R_ClearColormaps(void)
 {
-	extracolormap_t *exc, *exc_next;
+	// Purged by PU_LEVEL, just overwrite the pointer
+	extra_colormaps = R_CreateDefaultColormap(true);
+}
 
-	for (exc = extra_colormaps; exc; exc = exc_next)
-	{
-		exc_next = exc->next;
-		memset(exc, 0, sizeof(*exc));
-	}
-
-	// make a default extra_colormap
-	exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
+//
+// R_CreateDefaultColormap()
+//
+extracolormap_t *R_CreateDefaultColormap(boolean lighttable)
+{
+	extracolormap_t *exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
 	exc->fadestart = 0;
 	exc->fadeend = 31;
 	exc->fog = 0;
 	exc->rgba = 0;
 	exc->fadergba = 0x19000000;
-	exc->colormap = R_CreateLightTable(exc);
+	exc->colormap = lighttable ? R_CreateLightTable(exc) : NULL;
 #ifdef EXTRACOLORMAPLUMPS
 	exc->lump = LUMPERROR;
 	exc->lumpname[0] = 0;
 #endif
 	exc->next = exc->prev = NULL;
-
-	extra_colormaps = exc;
+	return exc;
 }
 
 //
diff --git a/src/r_data.h b/src/r_data.h
index e6eec41b4..718abeccc 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -105,6 +105,7 @@ INT32 R_CheckTextureNumForName(const char *name);
 
 void R_ReInitColormaps(UINT16 num);
 void R_ClearColormaps(void);
+extracolormap_t *R_CreateDefaultColormap(boolean lighttable);
 void R_AddColormapToList(extracolormap_t *extra_colormap);
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);

From ba88f8ebb66a55bf6d4966e72649f5151195e258 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 15:01:05 -0400
Subject: [PATCH 18/48] Smarter string digit parsing; allow alpha-only values

* GetDefaultColormap and CheckDefaultColormapValues methods
---
 src/p_setup.c |  11 ++-
 src/r_data.c  | 182 +++++++++++++++++++++++++++++++++++++++-----------
 src/r_data.h  |   2 +
 3 files changed, 149 insertions(+), 46 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index b503b6a58..77d53812c 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1472,12 +1472,11 @@ static void P_LoadRawSideDefs2(void *data)
 			case 606: //SoM: 4/4/2000: Just colormap transfer
 				// SoM: R_CreateColormap will only create a colormap in software mode...
 				// Perhaps we should just call it instead of doing the calculations here.
-				if (
-					((rendermode == render_soft || rendermode == render_none) && (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#'))
-#ifdef HWRENDER
-					|| (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
-					|| (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])
-#endif
+				if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#'
+					|| (msd->toptexture[0] >= 'a' && msd->toptexture[0] <= 'z' && !msd->toptexture[1])
+					|| (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'Z' && !msd->toptexture[1])
+					|| (msd->bottomtexture[0] >= 'a' && msd->bottomtexture[0] <= 'z' && !msd->bottomtexture[1])
+					|| (msd->bottomtexture[0] >= 'A' && msd->bottomtexture[0] <= 'Z' && !msd->bottomtexture[1])
 				)
 				{
 					sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
diff --git a/src/r_data.c b/src/r_data.c
index 4358f7536..958eeeb37 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1346,6 +1346,49 @@ extracolormap_t *R_CreateDefaultColormap(boolean lighttable)
 	return exc;
 }
 
+//
+// R_GetDefaultColormap()
+//
+extracolormap_t *R_GetDefaultColormap(void)
+{
+#ifdef COLORMAPREVERSELIST
+	extracolormap_t *exc;
+#endif
+
+	if (!extra_colormaps)
+		return (extra_colormaps = R_CreateDefaultColormap(true));
+
+#ifdef COLORMAPREVERSELIST
+	for (exc = extra_colormaps; exc->next; exc = exc->next);
+	return exc;
+#else
+	return extra_colormaps;
+#endif
+}
+
+//
+// R_CheckDefaultColormap()
+//
+boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams)
+{
+	if (!extra_colormap)
+		return true;
+	else
+		return (
+			(!checkparams ? true :
+				(extra_colormap->fadestart == 0
+					&& extra_colormap->fadeend == 31
+					&& !extra_colormap->fog)
+				)
+			&& (!checkrgba ? true : extra_colormap->rgba == 0)
+			&& (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000)
+#ifdef EXTRACOLORMAPLUMPS
+			&& extra_colormap->lump == LUMPERROR
+			&& extra_colormap->lumpname[0] == 0
+#endif
+			);
+}
+
 //
 // R_AddColormapToList
 //
@@ -1562,77 +1605,133 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 {
-	boolean fog = false;
 	extracolormap_t *extra_colormap, *exc;
 
-	UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa;
+	// default values
+	UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25;
 	UINT32 fadestart = 0, fadeend = 31;
-
-	INT32 rgba, fadergba;
+	boolean fog = false;
+	INT32 rgba = 0, fadergba = 0x19000000;
 
 	size_t dbg_i = 0;
 
 #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
 #define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0)
-	if (p1[0] == '#')
-	{
-		cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2]));
-		cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4]));
-		cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
 
-		if (p1[7] >= 'a' && p1[7] <= 'z')
-			ca = (p1[7] - 'a');
-		else if (p1[7] >= 'A' && p1[7] <= 'Z')
-			ca = (p1[7] - 'A');
+	// Get base colormap value
+	// First alpha-only, then full value
+	if (p1[0] >= 'a' && p1[0] <= 'z' && !p1[1])
+		ca = (p1[0] - 'a');
+	else if (p1[0] == '#' && p1[1] >= 'a' && p1[1] <= 'z' && !p1[2])
+		ca = (p1[1] - 'a');
+	else if (p1[0] >= 'A' && p1[0] <= 'Z' && !p1[1])
+		ca = (p1[0] - 'A');
+	else if (p1[0] == '#' && p1[1] >= 'A' && p1[1] <= 'Z' && !p1[2])
+		ca = (p1[1] - 'A');
+	else if (p1[0] == '#')
+	{
+		// For each subsequent value, the value before it must exist
+		// If we don't get every value, then set alpha to max
+		if (p1[1] && p1[2])
+		{
+			cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2]));
+			if (p1[3] && p1[4])
+			{
+				cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4]));
+				if (p1[5] && p1[6])
+				{
+					cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
+
+					if (p1[7] >= 'a' && p1[7] <= 'z')
+						ca = (p1[7] - 'a');
+					else if (p1[7] >= 'A' && p1[7] <= 'Z')
+						ca = (p1[7] - 'A');
+					else
+						ca = 25;
+				}
+				else
+					ca = 25;
+			}
+			else
+				ca = 25;
+		}
 		else
 			ca = 25;
-
-		rgba = cr + (cg << 8) + (cb << 16) + (ca << 24);
-	}
-	else
-	{
-		cr = cg = cb = ca = 0;
-		rgba = 0;
 	}
 
 #define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0)
+
+	// Get parameters like fadestart, fadeend, and the fogflag
 	if (p2[0] == '#')
 	{
-		// Get parameters like fadestart, fadeend, and the fogflag
-		fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
-		fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
+		if (p2[1])
+		{
+			fog = (boolean)NUMFROMCHAR(p2[1]);
+			if (p2[2] && p2[3])
+			{
+				fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
+				if (p2[4] && p2[5])
+					fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
+			}
+		}
+
 		if (fadestart > 30)
 			fadestart = 0;
 		if (fadeend > 31 || fadeend < 1)
 			fadeend = 31;
-		fog = (boolean)NUMFROMCHAR(p2[1]);
 	}
+
 #undef NUMFROMCHAR
 
-	if (p3[0] == '#')
+	// Get fade (dark) colormap value
+	// First alpha-only, then full value
+	if (p3[0] >= 'a' && p3[0] <= 'z' && !p3[1])
+		cfa = (p3[0] - 'a');
+	else if (p3[0] == '#' && p3[1] >= 'a' && p3[1] <= 'z' && !p3[2])
+		cfa = (p3[1] - 'a');
+	else if (p3[0] >= 'A' && p3[0] <= 'Z' && !p3[1])
+		cfa = (p3[0] - 'A');
+	else if (p3[0] == '#' && p3[1] >= 'A' && p3[1] <= 'Z' && !p3[2])
+		cfa = (p3[1] - 'A');
+	else if (p3[0] == '#')
 	{
-		cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
-		cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
-		cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
+		// For each subsequent value, the value before it must exist
+		// If we don't get every value, then set alpha to max
+		if (p3[1] && p3[2])
+		{
+			cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
+			if (p3[3] && p3[4])
+			{
+				cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
+				if (p3[5] && p3[6])
+				{
+					cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
 
-		if (p1[7] >= 'a' && p1[7] <= 'z')
-			cfa = (p1[7] - 'a');
-		else if (p1[7] >= 'A' && p1[7] <= 'Z')
-			cfa = (p1[7] - 'A');
+					if (p3[7] >= 'a' && p3[7] <= 'z')
+						cfa = (p3[7] - 'a');
+					else if (p3[7] >= 'A' && p3[7] <= 'Z')
+						cfa = (p3[7] - 'A');
+					else
+						cfa = 25;
+				}
+				else
+					cfa = 25;
+			}
+			else
+				cfa = 25;
+		}
 		else
 			cfa = 25;
-
-		fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24);
-	}
-	else
-	{
-		cfr = cfg = cfb = 0;
-		cfa = 25;
-		fadergba = 0x19000000; // default alpha for fade, (25 << 24)
 	}
 #undef ALPHA2INT
 #undef HEX2INT
 
+	// Pack rgba values into combined var
+	// OpenGL also uses this instead of lighttables for rendering
+	rgba = cr + (cg << 8) + (cb << 16) + (ca << 24);
+	fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24);
+
+	// Look for existing colormaps
 	for (exc = extra_colormaps; exc; exc = exc->next)
 	{
 #ifdef EXTRACOLORMAPLUMPS
@@ -1672,6 +1771,9 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	extra_colormap->lumpname[0] = 0;
 #endif
 
+	// Having lighttables for alpha-only entries is kind of pointless,
+	// but if there happens to be a matching rgba entry that is NOT alpha-only (but has same rgb values),
+	// then it needs this lighttable because we share matching entries.
 	extra_colormap->colormap = R_CreateLightTable(extra_colormap);
 
 	R_AddColormapToList(extra_colormap);
diff --git a/src/r_data.h b/src/r_data.h
index 718abeccc..95ea44a83 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -106,6 +106,8 @@ INT32 R_CheckTextureNumForName(const char *name);
 void R_ReInitColormaps(UINT16 num);
 void R_ClearColormaps(void);
 extracolormap_t *R_CreateDefaultColormap(boolean lighttable);
+extracolormap_t *R_GetDefaultColormap(void);
+boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
 void R_AddColormapToList(extracolormap_t *extra_colormap);
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);

From 85d89287de8521fe320275716b1e924b177e3a6d Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 15:20:30 -0400
Subject: [PATCH 19/48] Add R_CopyColormap

---
 src/r_data.c | 62 +++++++++++++++++++++++++++++++++++++++-------------
 src/r_data.h |  3 ++-
 2 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index 958eeeb37..ad27b442f 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1367,26 +1367,35 @@ extracolormap_t *R_GetDefaultColormap(void)
 }
 
 //
-// R_CheckDefaultColormap()
+// R_CopyColormap()
 //
-boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams)
+extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable)
 {
+	extracolormap_t *exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
+
 	if (!extra_colormap)
-		return true;
-	else
-		return (
-			(!checkparams ? true :
-				(extra_colormap->fadestart == 0
-					&& extra_colormap->fadeend == 31
-					&& !extra_colormap->fog)
-				)
-			&& (!checkrgba ? true : extra_colormap->rgba == 0)
-			&& (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000)
+		extra_colormap = R_GetDefaultColormap();
+
+	*exc = *extra_colormap;
+	exc->next = exc->prev = NULL;
+
 #ifdef EXTRACOLORMAPLUMPS
-			&& extra_colormap->lump == LUMPERROR
-			&& extra_colormap->lumpname[0] == 0
+	strncpy(exc->lumpname, extra_colormap->lumpname, 9);
+
+	if (exc->lump != LUMPERROR && lighttable)
+	{
+		// aligned on 8 bit for asm code
+		exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16);
+		W_ReadLump(lump, exc->colormap);
+	}
+	else
 #endif
-			);
+	if (lighttable)
+		exc->colormap = R_CreateLightTable(exc);
+	else
+		exc->colormap = NULL;
+
+	return exc;
 }
 
 //
@@ -1423,6 +1432,29 @@ void R_AddColormapToList(extracolormap_t *extra_colormap)
 #endif
 }
 
+//
+// R_CheckDefaultColormap()
+//
+boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams)
+{
+	if (!extra_colormap)
+		return true;
+	else
+		return (
+			(!checkparams ? true :
+				(extra_colormap->fadestart == 0
+					&& extra_colormap->fadeend == 31
+					&& !extra_colormap->fog)
+				)
+			&& (!checkrgba ? true : extra_colormap->rgba == 0)
+			&& (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000)
+#ifdef EXTRACOLORMAPLUMPS
+			&& extra_colormap->lump == LUMPERROR
+			&& extra_colormap->lumpname[0] == 0
+#endif
+			);
+}
+
 #ifdef EXTRACOLORMAPLUMPS
 extracolormap_t *R_ColormapForName(char *name)
 {
diff --git a/src/r_data.h b/src/r_data.h
index 95ea44a83..fc6d71299 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -107,8 +107,9 @@ void R_ReInitColormaps(UINT16 num);
 void R_ClearColormaps(void);
 extracolormap_t *R_CreateDefaultColormap(boolean lighttable);
 extracolormap_t *R_GetDefaultColormap(void);
-boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
+extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable);
 void R_AddColormapToList(extracolormap_t *extra_colormap);
+boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
 #ifdef EXTRACOLORMAPLUMPS

From c920827032429c013e410881f12102c7179b5e6e Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 15:50:12 -0400
Subject: [PATCH 20/48] Consolidate colormap matching into
 R_GetColormapFromList

---
 src/p_saveg.c | 30 +++----------------
 src/r_data.c  | 82 +++++++++++++++++++++++++++++++++++----------------
 src/r_data.h  |  6 ++++
 3 files changed, 66 insertions(+), 52 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 710c24821..b887b8a73 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -886,35 +886,13 @@ static void P_NetUnArchiveWorld(void)
 			else
 			{
 #endif
-
-			for (exc = extra_colormaps; exc; exc = exc->next)
-			{
-#ifdef EXTRACOLORMAPLUMPS
-				if (exc->lump != LUMPERROR)
-				{
-					//dbg_i++;
-					continue;
-				}
-#endif
-				if (rgba == exc->rgba
-					&& fadergba == exc->fadergba
-					&& fadestart == exc->fadestart
-					&& fadeend == exc->fadeend
-					&& fog == exc->fog)
-				{
-					// CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-					// 	dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
-					//	(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
-					break;
-				}
-				//dbg_i++;
-			}
+			exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
 
 			if (!exc)
 			{
-				// CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-				// 	dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
-				//	(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
+				// CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+				// 	(rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
+				// 	(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
 
 				exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
 
diff --git a/src/r_data.c b/src/r_data.c
index ad27b442f..e679f27ba 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1328,6 +1328,7 @@ void R_ClearColormaps(void)
 
 //
 // R_CreateDefaultColormap()
+// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself!
 //
 extracolormap_t *R_CreateDefaultColormap(boolean lighttable)
 {
@@ -1368,6 +1369,7 @@ extracolormap_t *R_GetDefaultColormap(void)
 
 //
 // R_CopyColormap()
+// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself!
 //
 extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable)
 {
@@ -1455,6 +1457,50 @@ boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean ch
 			);
 }
 
+//
+// R_GetColormapFromListByValues()
+// NOTE: Returns NULL if no match is found
+//
+#ifdef EXTRACOLORMAPLUMPS
+extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump)
+#else
+extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog)
+#endif
+{
+	extracolormap_t *exc;
+	size_t dbg_i = 0;
+
+	for (exc = extra_colormaps; exc; exc = exc->next)
+	{
+		if (rgba == exc->rgba
+			&& fadergba == exc->fadergba
+			&& fadestart == exc->fadestart
+			&& fadeend == exc->fadeend
+			&& fog == exc->fog
+#ifdef EXTRACOLORMAPLUMPS
+			&& (lump != LUMPERROR && lump == exc->lump)
+#endif
+		)
+		{
+			CONS_Debug(DBG_RENDER, "Found Colormap %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+				dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
+				(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
+			return exc;
+		}
+		dbg_i++;
+	}
+	return NULL;
+}
+
+extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap)
+{
+#ifdef EXTRACOLORMAPLUMPS
+	return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump);
+else
+	return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog);
+#endif
+}
+
 #ifdef EXTRACOLORMAPLUMPS
 extracolormap_t *R_ColormapForName(char *name)
 {
@@ -1465,9 +1511,9 @@ extracolormap_t *R_ColormapForName(char *name)
 	if (lump == LUMPERROR)
 		I_Error("R_ColormapForName: Cannot find colormap lump %.8s\n", name);
 
-	for (exc = extra_colormaps; exc; exc = exc->next)
-		if (lump == exc->lump)
-			return exc;
+	exc = R_GetColormapFromListByValues(0, 0x19000000, 0, 31, 0, lump);
+	if (exc)
+		return exc;
 
 	exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
 
@@ -1645,8 +1691,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	boolean fog = false;
 	INT32 rgba = 0, fadergba = 0x19000000;
 
-	size_t dbg_i = 0;
-
 #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
 #define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0)
 
@@ -1764,30 +1808,16 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24);
 
 	// Look for existing colormaps
-	for (exc = extra_colormaps; exc; exc = exc->next)
-	{
 #ifdef EXTRACOLORMAPLUMPS
-		if (exc->lump != LUMPERROR)
-		{
-			dbg_i++;
-			continue;
-		}
+	exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog, LUMPERROR);
+#else
+	exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
 #endif
-		if (rgba == exc->rgba
-			&& fadergba == exc->fadergba
-			&& fadestart == exc->fadestart
-			&& fadeend == exc->fadeend
-			&& fog == exc->fog)
-		{
-			CONS_Debug(DBG_RENDER, "R_CreateColormap: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-				dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
-			return exc;
-		}
-		dbg_i++;
-	}
+	if (exc)
+		return exc;
 
-	CONS_Debug(DBG_RENDER, "R_CreateColormap: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-		dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa);
+	CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+		cr, cg, cb, ca, cfr, cfg, cfb, cfa);
 
 	extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL);
 
diff --git a/src/r_data.h b/src/r_data.h
index fc6d71299..17d85fd8b 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -110,6 +110,12 @@ extracolormap_t *R_GetDefaultColormap(void);
 extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable);
 void R_AddColormapToList(extracolormap_t *extra_colormap);
 boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
+#ifdef EXTRACOLORMAPLUMPS
+extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump);
+#else
+extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog);
+#endif
+extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap);
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
 #ifdef EXTRACOLORMAPLUMPS

From 71ade23739a6eddce5b4c1c2d1b4210b4103a25d Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 15:59:13 -0400
Subject: [PATCH 21/48] Ifdef typo

---
 src/r_data.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/r_data.c b/src/r_data.c
index e679f27ba..e08600cae 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1496,7 +1496,7 @@ extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap)
 {
 #ifdef EXTRACOLORMAPLUMPS
 	return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump);
-else
+#else
 	return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog);
 #endif
 }

From 5975f261773418cd6eba4247582798e7d11ce0ec Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 17:06:44 -0400
Subject: [PATCH 22/48] Don't set sector's extra_colormap if we just made a
 default clone

* Allow colormap parsing to proceed in p_setup always
* Add R_CheckDefaultColormap
* Add R_GetRgbaR/G/B/A macros
---
 src/p_setup.c | 30 +++--------------------
 src/r_data.c  | 68 ++++++++++++++++++++++++++++++++++-----------------
 src/r_data.h  | 13 +++++++++-
 3 files changed, 61 insertions(+), 50 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index 77d53812c..edde5e701 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1438,7 +1438,6 @@ static inline void P_LoadSideDefs(lumpnum_t lumpnum)
 static void P_LoadRawSideDefs2(void *data)
 {
 	UINT16 i;
-	INT32 num;
 
 	for (i = 0; i < numsides; i++)
 	{
@@ -1472,32 +1471,9 @@ static void P_LoadRawSideDefs2(void *data)
 			case 606: //SoM: 4/4/2000: Just colormap transfer
 				// SoM: R_CreateColormap will only create a colormap in software mode...
 				// Perhaps we should just call it instead of doing the calculations here.
-				if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#'
-					|| (msd->toptexture[0] >= 'a' && msd->toptexture[0] <= 'z' && !msd->toptexture[1])
-					|| (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'Z' && !msd->toptexture[1])
-					|| (msd->bottomtexture[0] >= 'a' && msd->bottomtexture[0] <= 'z' && !msd->bottomtexture[1])
-					|| (msd->bottomtexture[0] >= 'A' && msd->bottomtexture[0] <= 'Z' && !msd->bottomtexture[1])
-				)
-				{
-					sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
-						msd->bottomtexture);
-					sd->toptexture = sd->bottomtexture = 0;
-				}
-				else
-				{
-					if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1)
-						sd->toptexture = 0;
-					else
-						sd->toptexture = num;
-					if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1)
-						sd->midtexture = 0;
-					else
-						sd->midtexture = num;
-					if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1)
-						sd->bottomtexture = 0;
-					else
-						sd->bottomtexture = num;
-				}
+				sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
+					msd->bottomtexture);
+				sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
 				break;
 
 			case 413: // Change music
diff --git a/src/r_data.c b/src/r_data.c
index e08600cae..529507e9a 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1435,26 +1435,41 @@ void R_AddColormapToList(extracolormap_t *extra_colormap)
 }
 
 //
-// R_CheckDefaultColormap()
+// R_CheckDefaultColormapByValues()
 //
-boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams)
+#ifdef EXTRACOLORMAPLUMPS
+boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
+	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump)
+#else
+boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
+	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog)
+#endif
+{
+	return (
+		(!checkparams ? true :
+			(fadestart == 0
+				&& fadeend == 31
+				&& !fog)
+			)
+		&& (!checkrgba ? true : rgba == 0)
+		&& (!checkfadergba ? true : fadergba == 0x19000000)
+#ifdef EXTRACOLORMAPLUMPS
+		&& lump == LUMPERROR
+		&& extra_colormap->lumpname[0] == 0
+#endif
+		);
+}
+
+boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams)
 {
 	if (!extra_colormap)
 		return true;
-	else
-		return (
-			(!checkparams ? true :
-				(extra_colormap->fadestart == 0
-					&& extra_colormap->fadeend == 31
-					&& !extra_colormap->fog)
-				)
-			&& (!checkrgba ? true : extra_colormap->rgba == 0)
-			&& (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000)
+
 #ifdef EXTRACOLORMAPLUMPS
-			&& extra_colormap->lump == LUMPERROR
-			&& extra_colormap->lumpname[0] == 0
+	return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump);
+#else
+	return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog);
 #endif
-			);
 }
 
 //
@@ -1557,14 +1572,14 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 	double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
 	double maskamt = 0, othermask = 0;
 
-	UINT8 cr = (extra_colormap->rgba) & 0xFF,
-		cg = (extra_colormap->rgba >> 8) & 0xFF,
-		cb = (extra_colormap->rgba >> 16) & 0xFF,
-		ca = (extra_colormap->rgba >> 24) & 0xFF,
-		cfr = (extra_colormap->fadergba) & 0xFF,
-		cfg = (extra_colormap->fadergba >> 8) & 0xFF,
-		cfb = (extra_colormap->fadergba >> 16) & 0xFF;
-//		cfa = (extra_colormap->fadergba >> 24) & 0xFF; // unused in software
+	UINT8 cr = R_GetRgbaR(extra_colormap->rgba),
+		cg = R_GetRgbaG(extra_colormap->rgba),
+		cb = R_GetRgbaB(extra_colormap->rgba),
+		ca = R_GetRgbaA(extra_colormap->rgba),
+		cfr = R_GetRgbaR(extra_colormap->fadergba),
+		cfg = R_GetRgbaG(extra_colormap->fadergba),
+		cfb = R_GetRgbaB(extra_colormap->fadergba);
+//		cfa = R_GetRgbaA(extra_colormap->fadergba); // unused in software
 
 	UINT8 fadestart = extra_colormap->fadestart,
 		fadedist = extra_colormap->fadeend - extra_colormap->fadestart;
@@ -1807,6 +1822,15 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	rgba = cr + (cg << 8) + (cb << 16) + (ca << 24);
 	fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24);
 
+	// Did we just make a default colormap?
+#ifdef EXTRACOLORMAPLUMPS
+	if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog, LUMPERROR))
+		return NULL;
+#else
+	if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog))
+		return NULL;
+#endif
+
 	// Look for existing colormaps
 #ifdef EXTRACOLORMAPLUMPS
 	exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog, LUMPERROR);
diff --git a/src/r_data.h b/src/r_data.h
index 17d85fd8b..ee497d155 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -109,13 +109,19 @@ extracolormap_t *R_CreateDefaultColormap(boolean lighttable);
 extracolormap_t *R_GetDefaultColormap(void);
 extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable);
 void R_AddColormapToList(extracolormap_t *extra_colormap);
-boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
+
 #ifdef EXTRACOLORMAPLUMPS
+boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
+	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump);
 extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump);
 #else
+boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
+	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog);
 extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog);
 #endif
+boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
 extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap);
+
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
 #ifdef EXTRACOLORMAPLUMPS
@@ -123,6 +129,11 @@ extracolormap_t *R_ColormapForName(char *name);
 const char *R_NameForColormap(extracolormap_t *extra_colormap);
 #endif
 
+#define R_GetRgbaR(rgba) (rgba & 0xFF)
+#define R_GetRgbaG(rgba) ((rgba >> 8) & 0xFF)
+#define R_GetRgbaB(rgba) ((rgba >> 16) & 0xFF)
+#define R_GetRgbaA(rgba) ((rgba >> 24) & 0xFF)
+
 extern INT32 numtextures;
 
 #endif

From 548f02eea14ab963fa2e4519740c927bef2ae3f5 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 17:30:43 -0400
Subject: [PATCH 23/48] Extra macros R_GetRgbaRGB; R_PutRgbaR/G/B/A/RGB/RGBA

---
 src/r_data.c | 4 ++--
 src/r_data.h | 7 +++++++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index 529507e9a..e0899e4cf 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1819,8 +1819,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 
 	// Pack rgba values into combined var
 	// OpenGL also uses this instead of lighttables for rendering
-	rgba = cr + (cg << 8) + (cb << 16) + (ca << 24);
-	fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24);
+	rgba = R_PutRgbaRGBA(cr, cg, cb, ca);
+	fadergba = R_PutRgbaRGBA(cfr, cfg, cfb, cfa);
 
 	// Did we just make a default colormap?
 #ifdef EXTRACOLORMAPLUMPS
diff --git a/src/r_data.h b/src/r_data.h
index ee497d155..d980e9c56 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -133,6 +133,13 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap);
 #define R_GetRgbaG(rgba) ((rgba >> 8) & 0xFF)
 #define R_GetRgbaB(rgba) ((rgba >> 16) & 0xFF)
 #define R_GetRgbaA(rgba) ((rgba >> 24) & 0xFF)
+#define R_GetRgbaRGB(rgba) (rgba & 0xFFFFFF)
+#define R_PutRgbaR(r) (r)
+#define R_PutRgbaG(g) (g << 8)
+#define R_PutRgbaB(b) (b << 16)
+#define R_PutRgbaA(a) (a << 24)
+#define R_PutRgbaRGB(r, g, b) (R_PutRgbaR(r) + R_PutRgbaG(g) + R_PutRgbaB(b))
+#define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a))
 
 extern INT32 numtextures;
 

From f0c11eb13572e041b1f7762d569f9e821c336d10 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 21:02:58 -0400
Subject: [PATCH 24/48] R_AddColormaps method

---
 src/r_data.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/r_data.h |  5 +++
 2 files changed, 91 insertions(+)

diff --git a/src/r_data.c b/src/r_data.c
index e0899e4cf..c84e61fce 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1867,6 +1867,92 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	return extra_colormap;
 }
 
+//
+// R_AddColormaps()
+// NOTE: The result colormap DOES get added to the extra_colormaps chain!
+//
+extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
+	boolean subR, boolean subG, boolean subB, boolean subA,
+	boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
+	boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
+	boolean lighttable)
+{
+	extracolormap_t *exc;
+
+	// exc_augend is added (or subtracted) onto by exc_addend
+	// In Rennaisance times, the first number was considered the augend, the second number the addend
+	// But since the commutative property was discovered, today they're both called addends!
+	// So let's be Olde English for a hot second.
+
+	exc_augend = R_CopyColormap(exc_augend, false);
+	if(!exc_addend)
+		exc_addend = R_GetDefaultColormap();
+
+	INT16 red, green, blue, alpha;
+
+	// base rgba
+	red = max(min(
+		R_GetRgbaR(exc_augend->rgba)
+			+ (subR ? -1 : 1) // subtract R
+			* R_GetRgbaR(exc_addend->rgba)
+		, 255), 0);
+
+	green = max(min(
+		R_GetRgbaG(exc_augend->rgba)
+			+ (subG ? -1 : 1) // subtract G
+			* R_GetRgbaG(exc_addend->rgba)
+		, 255), 0);
+
+	blue = max(min(
+		R_GetRgbaB(exc_augend->rgba)
+			+ (subB ? -1 : 1) // subtract B
+			* R_GetRgbaB(exc_addend->rgba)
+		, 255), 0);
+
+	alpha = useAltAlpha ? altAlpha : R_GetRgbaA(exc_addend->rgba);
+	alpha = max(min(R_GetRgbaA(exc_augend->rgba) + (subA ? -1 : 1) * alpha, 25), 0);
+
+	exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha);
+
+	// fade rgba
+	red = max(min(
+		R_GetRgbaR(exc_augend->fadergba)
+			+ (subFadeR ? -1 : 1) // subtract R
+			* R_GetRgbaR(exc_addend->fadergba)
+		, 255), 0);
+
+	green = max(min(
+		R_GetRgbaG(exc_augend->fadergba)
+			+ (subFadeG ? -1 : 1) // subtract G
+			* R_GetRgbaG(exc_addend->fadergba)
+		, 255), 0);
+
+	blue = max(min(
+		R_GetRgbaB(exc_augend->fadergba)
+			+ (subFadeB ? -1 : 1) // subtract B
+			* R_GetRgbaB(exc_addend->fadergba)
+		, 255), 0);
+
+	alpha = useAltAlpha ? altFadeAlpha : R_GetRgbaA(exc_addend->fadergba);
+	if (alpha == 25)
+		alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case
+	alpha = max(min(R_GetRgbaA(exc_augend->fadergba) + (subFadeA ? -1 : 1) * alpha, 25), 0);
+
+	exc_augend->fadergba = R_PutRgbaRGBA(red, green, blue, alpha);
+
+	if (!(exc = R_GetColormapFromList(exc_augend)))
+	{
+		exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL;
+		R_AddColormapToList(exc_augend);
+		return exc_augend;
+	}
+	else
+	{
+		Z_Free(exc_augend);
+		return exc;
+	}
+}
+
 // Thanks to quake2 source!
 // utils3/qdata/images.c
 static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b)
diff --git a/src/r_data.h b/src/r_data.h
index d980e9c56..6f8d08120 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -124,6 +124,11 @@ extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap);
 
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
+extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
+	boolean subR, boolean subG, boolean subB, boolean subA,
+	boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
+	boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
+	boolean lighttable);
 #ifdef EXTRACOLORMAPLUMPS
 extracolormap_t *R_ColormapForName(char *name);
 const char *R_NameForColormap(extracolormap_t *extra_colormap);

From 90aeac5058bae5cdc6c7097ce13bc1f4dd688df3 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 22:34:29 -0400
Subject: [PATCH 25/48] Add R_CheckEqualColormaps comparison method

---
 src/r_data.c | 27 +++++++++++++++++++++++++++
 src/r_data.h |  1 +
 2 files changed, 28 insertions(+)

diff --git a/src/r_data.c b/src/r_data.c
index c84e61fce..1de51fedd 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1472,6 +1472,33 @@ boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgb
 #endif
 }
 
+boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams)
+{
+	// Treat NULL as default colormap
+	// We need this because what if one exc is a default colormap, and the other is NULL? They're really both equal.
+	if (!exc_a)
+		exc_a = R_GetDefaultColormap();
+	if (!exc_b)
+		exc_b = R_GetDefaultColormap();
+
+	if (exc_a == exc_b)
+		return true;
+
+	return (
+		(!checkparams ? true :
+			(exc_a->fadestart == exc_b->fadestart
+				&& exc_a->fadeend == exc_b->fadeend
+				&& exc_a->fog == exc_b->fog)
+			)
+		&& (!checkrgba ? true : exc_a->rgba == exc_b->rgba)
+		&& (!checkfadergba ? true : exc_a->fadergba == exc_b->fadergba)
+#ifdef EXTRACOLORMAPLUMPS
+		&& exc_a->lump == exc_b->lump
+		&& !strncmp(exc_a->lumpname, exc_b->lumpname, 9)
+#endif
+		);
+}
+
 //
 // R_GetColormapFromListByValues()
 // NOTE: Returns NULL if no match is found
diff --git a/src/r_data.h b/src/r_data.h
index 6f8d08120..df0fe75b3 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -120,6 +120,7 @@ boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba,
 extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog);
 #endif
 boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
+boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams);
 extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap);
 
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);

From 92a97fb1a64ec3e2b88203011a5ca11abfeacef8 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 22:44:31 -0400
Subject: [PATCH 26/48] Split colormap netsync to Load/SaveExtraColormap
 methods

---
 src/p_saveg.c | 131 +++++++++++++++++++++++++-------------------------
 1 file changed, 66 insertions(+), 65 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index b887b8a73..fc767d9cf 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -474,6 +474,70 @@ static void P_NetUnArchivePlayers(void)
 	}
 }
 
+static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc)
+{
+	WRITEUINT8(put, exc->fadestart);
+	WRITEUINT8(put, exc->fadeend);
+	WRITEUINT8(put, (UINT8)exc->fog);
+
+	WRITEINT32(put, exc->rgba);
+	WRITEINT32(put, exc->fadergba);
+
+#ifdef EXTRACOLORMAPLUMPS
+	WRITESTRINGN(put, exc->lumpname, 9);
+#endif
+}
+
+static extracolormap_t *LoadExtraColormap(UINT8 *get)
+{
+	extracolormap_t *exc;
+	//size_t dbg_i = 0;
+
+	UINT8 fadestart = READUINT8(get),
+		fadeend = READUINT8(get);
+
+	boolean fog = (boolean)READUINT8(get);
+
+	INT32 rgba = READINT32(get),
+		fadergba = READINT32(get);
+
+#ifdef EXTRACOLORMAPLUMPS
+	char lumpname[9];
+	READSTRINGN(get, lumpname, 9);
+
+	if (lumpname[0])
+		return R_ColormapForName(lumpname);
+#endif
+	exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
+
+	if (!exc)
+	{
+		// CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+		// 	(rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
+		// 	(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
+
+		exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
+
+		exc->fadestart = fadestart;
+		exc->fadeend = fadeend;
+		exc->fog = fog;
+
+		exc->rgba = rgba;
+		exc->fadergba = fadergba;
+
+		exc->colormap = R_CreateLightTable(exc);
+
+		R_AddColormapToList(exc);
+
+#ifdef EXTRACOLORMAPLUMPS
+		exc->lump = LUMPERROR;
+		exc->lumpname[0] = 0;
+#endif
+	}
+
+	return exc;
+}
+
 #define SD_FLOORHT  0x01
 #define SD_CEILHT   0x02
 #define SD_FLOORPIC 0x04
@@ -657,18 +721,7 @@ static void P_NetArchiveWorld(void)
 			}
 
 			if (diff3 & SD_COLORMAP)
-			{
-				WRITEUINT8(put, ss->extra_colormap->fadestart);
-				WRITEUINT8(put, ss->extra_colormap->fadeend);
-				WRITEUINT8(put, (UINT8)ss->extra_colormap->fog);
-
-				WRITEINT32(put, ss->extra_colormap->rgba);
-				WRITEINT32(put, ss->extra_colormap->fadergba);
-
-#ifdef EXTRACOLORMAPLUMPS
-				WRITESTRINGN(put, ss->extra_colormap->lumpname, 9);
-#endif
-			}
+				SaveExtraColormap(put, ss->extra_colormap);
 
 			// Special case: save the stats of all modified ffloors along with their ffloor "number"s
 			// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
@@ -865,59 +918,7 @@ static void P_NetUnArchiveWorld(void)
 		}
 
 		if (diff3 & SD_COLORMAP)
-		{
-			extracolormap_t *exc;
-			//size_t dbg_i = 0;
-
-			UINT8 fadestart = READUINT8(get),
-				fadeend = READUINT8(get);
-
-			boolean fog = (boolean)READUINT8(get);
-
-			INT32 rgba = READINT32(get),
-				fadergba = READINT32(get);
-
-#ifdef EXTRACOLORMAPLUMPS
-			char lumpname[9];
-			READSTRINGN(get, lumpname, 9);
-
-			if (lumpname[0])
-				sectors[i].extra_colormap = R_ColormapForName(lumpname);
-			else
-			{
-#endif
-			exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
-
-			if (!exc)
-			{
-				// CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-				// 	(rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
-				// 	(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
-
-				exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
-
-				exc->fadestart = fadestart;
-				exc->fadeend = fadeend;
-				exc->fog = fog;
-
-				exc->rgba = rgba;
-				exc->fadergba = fadergba;
-
-				exc->colormap = R_CreateLightTable(exc);
-
-				R_AddColormapToList(exc);
-
-#ifdef EXTRACOLORMAPLUMPS
-				exc->lump = LUMPERROR;
-				exc->lumpname[0] = 0;
-#endif
-			}
-
-			sectors[i].extra_colormap = exc;
-#ifdef EXTRACOLORMAPLUMPS
-			}
-#endif
-		}
+			sectors[i].extra_colormap = LoadExtraColormap(get);
 
 		if (diff & SD_FFLOORS)
 		{

From 133c3598a79828bbf140f844e306517a9aa79725 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 07:06:45 -0400
Subject: [PATCH 27/48] Add fadestart/fadeend/fog to R_AddColormaps

---
 src/r_data.c | 32 +++++++++++++++++++++++++++++++-
 src/r_data.h |  1 +
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/src/r_data.c b/src/r_data.c
index 1de51fedd..53044bc2e 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1901,6 +1901,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
 	boolean subR, boolean subG, boolean subB, boolean subA,
 	boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
+	boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog,
 	boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
 	boolean lighttable)
 {
@@ -1917,7 +1918,10 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
 
 	INT16 red, green, blue, alpha;
 
+	///////////////////
 	// base rgba
+	///////////////////
+
 	red = max(min(
 		R_GetRgbaR(exc_augend->rgba)
 			+ (subR ? -1 : 1) // subtract R
@@ -1941,7 +1945,10 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
 
 	exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha);
 
-	// fade rgba
+	///////////////////
+	// fade/dark rgba
+	///////////////////
+
 	red = max(min(
 		R_GetRgbaR(exc_augend->fadergba)
 			+ (subFadeR ? -1 : 1) // subtract R
@@ -1967,6 +1974,29 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
 
 	exc_augend->fadergba = R_PutRgbaRGBA(red, green, blue, alpha);
 
+	///////////////////
+	// parameters
+	///////////////////
+
+	exc_augend->fadestart = max(min(
+		exc_augend->fadestart
+			+ (subFadeStart ? -1 : 1) // subtract fadestart
+			* exc_addend->fadestart
+		, 31), 0);
+
+	exc_augend->fadeend = max(min(
+		exc_augend->fadeend
+			+ (subFadeEnd ? -1 : 1) // subtract fadeend
+			* exc_addend->fadeend
+		, 31), 0);
+
+	if (!ignoreFog) // overwrite fog with new value
+		exc_augend->fog = exc_addend->fog;
+
+	///////////////////
+	// put it together
+	///////////////////
+
 	if (!(exc = R_GetColormapFromList(exc_augend)))
 	{
 		exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL;
diff --git a/src/r_data.h b/src/r_data.h
index df0fe75b3..3a7740c96 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -128,6 +128,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
 extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
 	boolean subR, boolean subG, boolean subB, boolean subA,
 	boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
+	boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog,
 	boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
 	boolean lighttable);
 #ifdef EXTRACOLORMAPLUMPS

From 87ad2a87f79cb9fbfabee5a8dc8550c1f3305f2e Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 07:14:23 -0400
Subject: [PATCH 28/48] Smarter default fadergbaA and fadeend for relative calc

---
 src/r_data.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index 53044bc2e..5a642f1b2 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1968,7 +1968,7 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
 		, 255), 0);
 
 	alpha = useAltAlpha ? altFadeAlpha : R_GetRgbaA(exc_addend->fadergba);
-	if (alpha == 25)
+	if (alpha == 25 && !useAltAlpha && !R_GetRgbaRGB(exc_addend->fadergba))
 		alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case
 	alpha = max(min(R_GetRgbaA(exc_augend->fadergba) + (subFadeA ? -1 : 1) * alpha, 25), 0);
 
@@ -1987,7 +1987,8 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
 	exc_augend->fadeend = max(min(
 		exc_augend->fadeend
 			+ (subFadeEnd ? -1 : 1) // subtract fadeend
-			* exc_addend->fadeend
+			* (exc_addend->fadeend == 31 && !exc_addend->fadestart ? 0 : exc_addend->fadeend)
+				// HACK: fadeend defaults to 31, so don't add anything in this case
 		, 31), 0);
 
 	if (!ignoreFog) // overwrite fog with new value

From 55c43a2161201ae4382565f3fd4616c0faddbca1 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 07:24:22 -0400
Subject: [PATCH 29/48] R_AddColormap will not return an existing colormap, and
 new colormap is not added to chain

---
 src/r_data.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index 5a642f1b2..c8a648a0f 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1896,7 +1896,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 
 //
 // R_AddColormaps()
-// NOTE: The result colormap DOES get added to the extra_colormaps chain!
+// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself!
 //
 extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
 	boolean subR, boolean subG, boolean subB, boolean subA,
@@ -1998,17 +1998,9 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
 	// put it together
 	///////////////////
 
-	if (!(exc = R_GetColormapFromList(exc_augend)))
-	{
-		exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL;
-		R_AddColormapToList(exc_augend);
-		return exc_augend;
-	}
-	else
-	{
-		Z_Free(exc_augend);
-		return exc;
-	}
+	exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL;
+	exc_augend->next = exc_augend->prev = NULL;
+	return exc_augend;
 }
 
 // Thanks to quake2 source!

From 9a6a8b0b8255a34c6b85d31887cc2390a640c500 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 08:07:34 -0400
Subject: [PATCH 30/48] Outdated comment; unused var

---
 src/p_setup.c | 3 ---
 src/r_data.c  | 2 --
 2 files changed, 5 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index edde5e701..c08c2ac58 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1459,9 +1459,6 @@ static void P_LoadRawSideDefs2(void *data)
 			sd->sector = sec = &sectors[sector_num];
 		}
 
-		// refined to allow colormaps to work as wall textures if invalid as colormaps
-		// but valid as textures.
-
 		sd->sector = sec = &sectors[SHORT(msd->sector)];
 
 		// Colormaps!
diff --git a/src/r_data.c b/src/r_data.c
index c8a648a0f..c2e28fe9f 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1905,8 +1905,6 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
 	boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
 	boolean lighttable)
 {
-	extracolormap_t *exc;
-
 	// exc_augend is added (or subtracted) onto by exc_addend
 	// In Rennaisance times, the first number was considered the augend, the second number the addend
 	// But since the commutative property was discovered, today they're both called addends!

From 92c5cb82334a3066fd38c6881b236478611eca36 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 11:01:12 -0400
Subject: [PATCH 31/48] Colormap savegame failsafe - Handle NULL (default
 colormap)

---
 src/p_saveg.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index fc767d9cf..4084d8c13 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -476,6 +476,9 @@ static void P_NetUnArchivePlayers(void)
 
 static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc)
 {
+	if (!exc) // Just give it default values, we done goofed. (or sector->extra_colormap was intentionally set to default (NULL))
+		exc = R_GetDefaultColormap();
+
 	WRITEUINT8(put, exc->fadestart);
 	WRITEUINT8(put, exc->fadeend);
 	WRITEUINT8(put, (UINT8)exc->fog);
@@ -490,7 +493,7 @@ static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc)
 
 static extracolormap_t *LoadExtraColormap(UINT8 *get)
 {
-	extracolormap_t *exc;
+	extracolormap_t *exc, *exc_exist;
 	//size_t dbg_i = 0;
 
 	UINT8 fadestart = READUINT8(get),
@@ -525,14 +528,21 @@ static extracolormap_t *LoadExtraColormap(UINT8 *get)
 		exc->rgba = rgba;
 		exc->fadergba = fadergba;
 
-		exc->colormap = R_CreateLightTable(exc);
-
-		R_AddColormapToList(exc);
-
 #ifdef EXTRACOLORMAPLUMPS
 		exc->lump = LUMPERROR;
 		exc->lumpname[0] = 0;
 #endif
+
+		if (!(exc_exist = R_GetColormapFromList(exc)))
+		{
+			exc->colormap = R_CreateLightTable(exc);
+			R_AddColormapToList(exc);
+		}
+		else
+		{
+			Z_Free(exc);
+			exc = R_CheckDefaultColormap(exc_exist, true, true, true) ? NULL : exc_exist;
+		}
 	}
 
 	return exc;

From 7d36aae7c404b29f71dafacce4f09355e9a30de0 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 16:06:56 -0400
Subject: [PATCH 32/48] Make lightlists react to control sector colormap
 changes (double pointer)

---
 src/r_bsp.c    | 14 +++++++-------
 src/r_defs.h   |  2 +-
 src/r_segs.c   |  6 +++---
 src/r_things.c |  4 ++--
 4 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/r_bsp.c b/src/r_bsp.c
index 01676572e..cbb012b28 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -925,11 +925,11 @@ static void R_Subsector(size_t num)
 		light = R_GetPlaneLight(frontsector, floorcenterz, false);
 		if (frontsector->floorlightsec == -1)
 			floorlightlevel = *frontsector->lightlist[light].lightlevel;
-		floorcolormap = frontsector->lightlist[light].extra_colormap;
+		floorcolormap = *frontsector->lightlist[light].extra_colormap;
 		light = R_GetPlaneLight(frontsector, ceilingcenterz, false);
 		if (frontsector->ceilinglightsec == -1)
 			ceilinglightlevel = *frontsector->lightlist[light].lightlevel;
-		ceilingcolormap = frontsector->lightlist[light].extra_colormap;
+		ceilingcolormap = *frontsector->lightlist[light].extra_colormap;
 	}
 
 	sub->sector->extra_colormap = frontsector->extra_colormap;
@@ -1026,7 +1026,7 @@ static void R_Subsector(size_t num)
 
 				ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic,
 					*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs,
-					*rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover
+					*rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover
 #ifdef POLYOBJECTS_PLANES
 					, NULL
 #endif
@@ -1072,7 +1072,7 @@ static void R_Subsector(size_t num)
 
 				ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic,
 					*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle,
-					frontsector->lightlist[light].extra_colormap, rover
+					*frontsector->lightlist[light].extra_colormap, rover
 #ifdef POLYOBJECTS_PLANES
 					, NULL
 #endif
@@ -1264,7 +1264,7 @@ void R_Prep3DFloors(sector_t *sector)
 #endif
 	sector->lightlist[0].lightlevel = &sector->lightlevel;
 	sector->lightlist[0].caster = NULL;
-	sector->lightlist[0].extra_colormap = sector->extra_colormap;
+	sector->lightlist[0].extra_colormap = &sector->extra_colormap;
 	sector->lightlist[0].flags = 0;
 
 	maxheight = INT32_MAX;
@@ -1339,12 +1339,12 @@ void R_Prep3DFloors(sector_t *sector)
 		else if (best->flags & FF_COLORMAPONLY)
 		{
 			sector->lightlist[i].lightlevel = sector->lightlist[i-1].lightlevel;
-			sector->lightlist[i].extra_colormap = sec->extra_colormap;
+			sector->lightlist[i].extra_colormap = &sec->extra_colormap;
 		}
 		else
 		{
 			sector->lightlist[i].lightlevel = best->toplightlevel;
-			sector->lightlist[i].extra_colormap = sec->extra_colormap;
+			sector->lightlist[i].extra_colormap = &sec->extra_colormap;
 		}
 
 		if (best->flags & FF_DOUBLESHADOW)
diff --git a/src/r_defs.h b/src/r_defs.h
index 99fad2b44..63ca29aa1 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -194,7 +194,7 @@ typedef struct lightlist_s
 {
 	fixed_t height;
 	INT16 *lightlevel;
-	extracolormap_t *extra_colormap;
+	extracolormap_t **extra_colormap; // pointer-to-a-pointer, so we can react to colormap changes
 	INT32 flags;
 	ffloor_t *caster;
 #ifdef ESLOPE
diff --git a/src/r_segs.c b/src/r_segs.c
index a52b7cb61..cde019f66 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -413,7 +413,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 #endif
 			rlight->startheight = rlight->height; // keep starting value here to reset for each repeat
 			rlight->lightlevel = *light->lightlevel;
-			rlight->extra_colormap = light->extra_colormap;
+			rlight->extra_colormap = *light->extra_colormap;
 			rlight->flags = light->flags;
 
 			if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
@@ -944,7 +944,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 			}
 
 			rlight->lightlevel = *light->lightlevel;
-			rlight->extra_colormap = light->extra_colormap;
+			rlight->extra_colormap = *light->extra_colormap;
 
 			// Check if the current light effects the colormap/lightlevel
 			if (pfloor->flags & FF_FOG)
@@ -2808,7 +2808,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			}
 
 			rlight->lightlevel = *light->lightlevel;
-			rlight->extra_colormap = light->extra_colormap;
+			rlight->extra_colormap = *light->extra_colormap;
 			p++;
 		}
 
diff --git a/src/r_things.c b/src/r_things.c
index fb4664d90..f4a0fd28c 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -981,7 +981,7 @@ static void R_SplitSprite(vissprite_t *sprite)
 			else
 				spritelights = scalelight[lightnum];
 
-			newsprite->extra_colormap = sector->lightlist[i].extra_colormap;
+			newsprite->extra_colormap = *sector->lightlist[i].extra_colormap;
 
 			if (!((newsprite->cut & SC_FULLBRIGHT)
 				&& (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1))))
@@ -1360,7 +1360,7 @@ static void R_ProjectSprite(mobj_t *thing)
 	vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS);
 	vis->cut = cut;
 	if (thing->subsector->sector->numlights)
-		vis->extra_colormap = thing->subsector->sector->lightlist[light].extra_colormap;
+		vis->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap;
 	else
 		vis->extra_colormap = thing->subsector->sector->extra_colormap;
 

From 62b6950e3324e550a63234ef9c7aed5ef798b5e2 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 16:28:55 -0400
Subject: [PATCH 33/48] Use lightlist.extra_colormap double pointers in OpenGL

---
 src/hardware/hw_main.c | 30 +++++++++++++++---------------
 src/hardware/hw_md2.c  |  4 ++--
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 119be6b46..50399dbd6 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -1126,7 +1126,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 			else
 			{
 				lightnum = *list[i].lightlevel;
-				colormap = list[i].extra_colormap;
+				colormap = *list[i].extra_colormap;
 			}
 		}
 
@@ -3486,12 +3486,12 @@ static void HWR_Subsector(size_t num)
 		light = R_GetPlaneLight(gr_frontsector, locFloorHeight, false);
 		if (gr_frontsector->floorlightsec == -1)
 			floorlightlevel = *gr_frontsector->lightlist[light].lightlevel;
-		floorcolormap = gr_frontsector->lightlist[light].extra_colormap;
+		floorcolormap = *gr_frontsector->lightlist[light].extra_colormap;
 
 		light = R_GetPlaneLight(gr_frontsector, locCeilingHeight, false);
 		if (gr_frontsector->ceilinglightsec == -1)
 			ceilinglightlevel = *gr_frontsector->lightlist[light].lightlevel;
-		ceilingcolormap = gr_frontsector->lightlist[light].extra_colormap;
+		ceilingcolormap = *gr_frontsector->lightlist[light].extra_colormap;
 	}
 
 	sub->sector->extra_colormap = gr_frontsector->extra_colormap;
@@ -3617,7 +3617,7 @@ static void HWR_Subsector(size_t num)
 					                       *rover->bottomheight,
 					                       *gr_frontsector->lightlist[light].lightlevel,
 					                       rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent,
-					                       false, gr_frontsector->lightlist[light].extra_colormap);
+					                       false, *gr_frontsector->lightlist[light].extra_colormap);
 #endif
 				}
 				else
@@ -3625,7 +3625,7 @@ static void HWR_Subsector(size_t num)
 					HWR_GetFlat(levelflats[*rover->bottompic].lumpnum);
 					light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
 					HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum,
-					                rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap);
+					                rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
 				}
 			}
 
@@ -3680,7 +3680,7 @@ static void HWR_Subsector(size_t num)
 					                        *rover->topheight,
 					                        *gr_frontsector->lightlist[light].lightlevel,
 					                        rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent,
-					                        false, gr_frontsector->lightlist[light].extra_colormap);
+					                        false, *gr_frontsector->lightlist[light].extra_colormap);
 #endif
 
 				}
@@ -3689,7 +3689,7 @@ static void HWR_Subsector(size_t num)
 					HWR_GetFlat(levelflats[*rover->toppic].lumpnum);
 					light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
 					HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum,
-					                  rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap);
+					                  rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
 				}
 			}
 		}
@@ -4200,8 +4200,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
 				lightlevel = *sector->lightlist[light].lightlevel;
 
-			if (sector->lightlist[light].extra_colormap)
-				colormap = sector->lightlist[light].extra_colormap;
+			if (*sector->lightlist[light].extra_colormap)
+				colormap = *sector->lightlist[light].extra_colormap;
 		}
 		else
 		{
@@ -4362,7 +4362,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 
 	// Start with the lightlevel and colormap from the top of the sprite
 	lightlevel = *list[sector->numlights - 1].lightlevel;
-	colormap = list[sector->numlights - 1].extra_colormap;
+	colormap = *list[sector->numlights - 1].extra_colormap;
 	i = 0;
 	temp = FLOAT_TO_FIXED(realtop);
 
@@ -4378,7 +4378,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 		{
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
 				lightlevel = *list[i-1].lightlevel;
-			colormap = list[i-1].extra_colormap;
+			colormap = *list[i-1].extra_colormap;
 			break;
 		}
 	}
@@ -4386,7 +4386,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 	i = R_GetPlaneLight(sector, temp, false);
 	if (!(spr->mobj->frame & FF_FULLBRIGHT))
 		lightlevel = *list[i].lightlevel;
-	colormap = list[i].extra_colormap;
+	colormap = *list[i].extra_colormap;
 #endif
 
 	for (i = 0; i < sector->numlights; i++)
@@ -4402,7 +4402,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 		{
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
 				lightlevel = *list[i].lightlevel;
-			colormap = list[i].extra_colormap;
+			colormap = *list[i].extra_colormap;
 		}
 
 #ifdef ESLOPE
@@ -4734,8 +4734,8 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
 				lightlevel = *sector->lightlist[light].lightlevel;
 
-			if (sector->lightlist[light].extra_colormap)
-				colormap = sector->lightlist[light].extra_colormap;
+			if (*sector->lightlist[light].extra_colormap)
+				colormap = *sector->lightlist[light].extra_colormap;
 		}
 		else
 		{
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index bfb2638ee..d69233a9b 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -1194,8 +1194,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
 				lightlevel = *sector->lightlist[light].lightlevel;
 
-			if (sector->lightlist[light].extra_colormap)
-				colormap = sector->lightlist[light].extra_colormap;
+			if (*sector->lightlist[light].extra_colormap)
+				colormap = *sector->lightlist[light].extra_colormap;
 		}
 		else
 		{

From ad9ef5d59316246b647d456c170da6d98293914a Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 17:39:30 -0400
Subject: [PATCH 34/48] Merge errors

---
 src/p_saveg.c | 2 --
 src/p_spec.c  | 2 +-
 src/r_defs.h  | 1 -
 3 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index f2e8dcdb7..c9b474b1d 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -730,8 +730,6 @@ static void P_NetArchiveWorld(void)
 				WRITEINT32(put, ss->firsttag);
 				WRITEINT32(put, ss->nexttag);
 			}
-			if (diff3 & SD_MIDMAP)
-				WRITEINT32(put, ss->midmap);
 
 			if (diff3 & SD_COLORMAP)
 				SaveExtraColormap(put, ss->extra_colormap);
diff --git a/src/p_spec.c b/src/p_spec.c
index b5e862749..21380584b 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -3256,7 +3256,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			// This could even override existing colormaps I believe
 			// -- Monster Iestyn 14/06/18
 			for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;)
-				sectors[secnum].midmap = line->frontsector->midmap;
+				sectors[secnum].extra_colormap = line->frontsector->extra_colormap;
 			break;
 
 		case 448: // Change skybox viewpoint/centerpoint
diff --git a/src/r_defs.h b/src/r_defs.h
index 1d1d471e5..63ca29aa1 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -390,7 +390,6 @@ typedef struct sector_s
 
 	// these are saved for netgames, so do not let Lua touch these!
 	INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed
-	INT32 spawn_bottommap, spawn_midmap, spawn_topmap;
 
 	// offsets sector spawned with (via linedef type 7)
 	fixed_t spawn_flr_xoffs, spawn_flr_yoffs;

From f7ff440250ddaf9ee1a03a254cfad0834d6514e3 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 20:43:48 -0400
Subject: [PATCH 35/48] Add colormap_data to side_t and store colormaps there
 on setup

---
 src/p_setup.c | 2 +-
 src/p_spec.c  | 4 ++--
 src/r_defs.h  | 2 ++
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index 5d7fd3179..cc5ee3cc8 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1469,7 +1469,7 @@ static void P_LoadRawSideDefs2(void *data)
 			case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18
 				// SoM: R_CreateColormap will only create a colormap in software mode...
 				// Perhaps we should just call it instead of doing the calculations here.
-				sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
+				sd->colormap_data = R_CreateColormap(msd->toptexture, msd->midtexture,
 					msd->bottomtexture);
 				sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
 				break;
diff --git a/src/p_spec.c b/src/p_spec.c
index 21380584b..8e5a612c3 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -3256,7 +3256,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			// This could even override existing colormaps I believe
 			// -- Monster Iestyn 14/06/18
 			for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;)
-				sectors[secnum].extra_colormap = line->frontsector->extra_colormap;
+				sectors[secnum].extra_colormap = sides[line->sidenum[0]].colormap_data;
 			break;
 
 		case 448: // Change skybox viewpoint/centerpoint
@@ -6769,7 +6769,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
 
 			case 606: // HACK! Copy colormaps. Just plain colormaps.
 				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-					sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = lines[i].frontsector->extra_colormap;
+					sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = sides[lines[i].sidenum[0]].colormap_data;
 				break;
 
 #ifdef ESLOPE // Slope copy specials. Handled here for sanity.
diff --git a/src/r_defs.h b/src/r_defs.h
index 63ca29aa1..1f2afdb99 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -476,6 +476,8 @@ typedef struct
 	INT16 repeatcnt; // # of times to repeat midtexture
 
 	char *text; // a concatination of all top, bottom, and mid texture names, for linedef specials that require a string.
+
+	extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors.
 } side_t;
 
 //

From 0b2caa948fb89ab5a7d25d2164c01b01091237fa Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Wed, 12 Sep 2018 21:05:50 -0400
Subject: [PATCH 36/48] Init side->colormap_data pointer to NULL (for paranoia)

---
 src/p_setup.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/p_setup.c b/src/p_setup.c
index cc5ee3cc8..f0ce69598 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1461,6 +1461,8 @@ static void P_LoadRawSideDefs2(void *data)
 
 		sd->sector = sec = &sectors[SHORT(msd->sector)];
 
+		sd->colormap_data = NULL;
+
 		// Colormaps!
 		switch (sd->special)
 		{

From 6824e6a3596031a11e78b9c1d4706deee592c83c Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Thu, 13 Sep 2018 12:08:46 -0400
Subject: [PATCH 37/48] Make extracolormap_t->fog UINT8; it's not boolean, but
 categorical

---
 src/p_saveg.c |  7 +++----
 src/r_data.c  | 10 +++++-----
 src/r_data.h  |  8 ++++----
 src/r_defs.h  |  2 +-
 4 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index c9b474b1d..2d39ccfa2 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -481,7 +481,7 @@ static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc)
 
 	WRITEUINT8(put, exc->fadestart);
 	WRITEUINT8(put, exc->fadeend);
-	WRITEUINT8(put, (UINT8)exc->fog);
+	WRITEUINT8(put, exc->fog);
 
 	WRITEINT32(put, exc->rgba);
 	WRITEINT32(put, exc->fadergba);
@@ -497,9 +497,8 @@ static extracolormap_t *LoadExtraColormap(UINT8 *get)
 	//size_t dbg_i = 0;
 
 	UINT8 fadestart = READUINT8(get),
-		fadeend = READUINT8(get);
-
-	boolean fog = (boolean)READUINT8(get);
+		fadeend = READUINT8(get),
+		fog = READUINT8(get);
 
 	INT32 rgba = READINT32(get),
 		fadergba = READINT32(get);
diff --git a/src/r_data.c b/src/r_data.c
index c2e28fe9f..e987da066 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1439,10 +1439,10 @@ void R_AddColormapToList(extracolormap_t *extra_colormap)
 //
 #ifdef EXTRACOLORMAPLUMPS
 boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
-	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump)
+	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump)
 #else
 boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
-	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog)
+	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog)
 #endif
 {
 	return (
@@ -1504,9 +1504,9 @@ boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, bo
 // NOTE: Returns NULL if no match is found
 //
 #ifdef EXTRACOLORMAPLUMPS
-extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump)
+extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump)
 #else
-extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog)
+extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog)
 #endif
 {
 	extracolormap_t *exc;
@@ -1730,7 +1730,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	// default values
 	UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25;
 	UINT32 fadestart = 0, fadeend = 31;
-	boolean fog = false;
+	UINT8 fog = 0;
 	INT32 rgba = 0, fadergba = 0x19000000;
 
 #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
diff --git a/src/r_data.h b/src/r_data.h
index 3a7740c96..54857661a 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -112,12 +112,12 @@ void R_AddColormapToList(extracolormap_t *extra_colormap);
 
 #ifdef EXTRACOLORMAPLUMPS
 boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
-	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump);
-extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump);
+	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump);
+extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump);
 #else
 boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
-	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog);
-extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog);
+	INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog);
+extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog);
 #endif
 boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
 boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams);
diff --git a/src/r_defs.h b/src/r_defs.h
index 1f2afdb99..b9c6fd7dc 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -53,7 +53,7 @@ typedef UINT8 lighttable_t;
 typedef struct extracolormap_s
 {
 	UINT8 fadestart, fadeend;
-	boolean fog;
+	UINT8 fog; // 1 = disable sprite fullbright, 2 = force planes fullbright, see public gitlab !268
 
 	// store rgba values in combined bitwise
 	// also used in OpenGL instead lighttables

From 07af82aa8495101c8170a44b7f92cb5c3dc7eb69 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Thu, 13 Sep 2018 12:18:53 -0400
Subject: [PATCH 38/48] Missed fog boolean -> integer

---
 src/r_data.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/r_data.c b/src/r_data.c
index e987da066..f1cd519e0 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1784,7 +1784,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	{
 		if (p2[1])
 		{
-			fog = (boolean)NUMFROMCHAR(p2[1]);
+			fog = NUMFROMCHAR(p2[1]);
 			if (p2[2] && p2[3])
 			{
 				fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);

From 2f995f4cbeed00a5fb3646a4be8a086d0609fb5a Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Fri, 14 Sep 2018 22:35:08 -0400
Subject: [PATCH 39/48] Remove possibly wrong comment about
 extracolormap_t->fog

---
 src/r_defs.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/r_defs.h b/src/r_defs.h
index b9c6fd7dc..e1c1d45c2 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -53,7 +53,7 @@ typedef UINT8 lighttable_t;
 typedef struct extracolormap_s
 {
 	UINT8 fadestart, fadeend;
-	UINT8 fog; // 1 = disable sprite fullbright, 2 = force planes fullbright, see public gitlab !268
+	UINT8 fog; // categorical value, not boolean
 
 	// store rgba values in combined bitwise
 	// also used in OpenGL instead lighttables

From 57959522e20b0bce603fa51ff1d9f76abf30dafe Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Sat, 15 Sep 2018 00:48:34 -0400
Subject: [PATCH 40/48] Colormap overhaul r_data: Mixed D+C fix

---
 src/r_data.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index f1cd519e0..ce0213b36 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1905,6 +1905,8 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
 	boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
 	boolean lighttable)
 {
+	INT16 red, green, blue, alpha;
+
 	// exc_augend is added (or subtracted) onto by exc_addend
 	// In Rennaisance times, the first number was considered the augend, the second number the addend
 	// But since the commutative property was discovered, today they're both called addends!
@@ -1914,8 +1916,6 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
 	if(!exc_addend)
 		exc_addend = R_GetDefaultColormap();
 
-	INT16 red, green, blue, alpha;
-
 	///////////////////
 	// base rgba
 	///////////////////

From 6844ed37c5ae95dfb7294eaaaf84538cf45e6f27 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Sat, 15 Sep 2018 01:47:56 -0400
Subject: [PATCH 41/48] Colormap overhaul: %d format size_t -> UINT32 fix

---
 src/p_saveg.c | 5 ++---
 src/r_data.c  | 6 +++---
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 2d39ccfa2..f9841717e 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -494,7 +494,6 @@ static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc)
 static extracolormap_t *LoadExtraColormap(UINT8 *get)
 {
 	extracolormap_t *exc, *exc_exist;
-	//size_t dbg_i = 0;
 
 	UINT8 fadestart = READUINT8(get),
 		fadeend = READUINT8(get),
@@ -515,8 +514,8 @@ static extracolormap_t *LoadExtraColormap(UINT8 *get)
 	if (!exc)
 	{
 		// CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-		// 	(rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
-		// 	(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
+		// 	R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba),
+		//	R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba));
 
 		exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
 
diff --git a/src/r_data.c b/src/r_data.c
index ce0213b36..cfc1a734e 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1510,7 +1510,7 @@ extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8
 #endif
 {
 	extracolormap_t *exc;
-	size_t dbg_i = 0;
+	UINT32 dbg_i = 0;
 
 	for (exc = extra_colormaps; exc; exc = exc->next)
 	{
@@ -1525,8 +1525,8 @@ extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8
 		)
 		{
 			CONS_Debug(DBG_RENDER, "Found Colormap %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-				dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF,
-				(fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF);
+				dbg_i, R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba),
+				R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba));
 			return exc;
 		}
 		dbg_i++;

From efe0af960dd2d084f5a9ec8e9c56eda67ca57a65 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Sat, 15 Sep 2018 02:10:17 -0400
Subject: [PATCH 42/48] Colormap overhaul: Wrap R_CheckNumForNameList under
 ifdef EXTRACOLORMAPLUMPS

---
 src/r_data.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index cfc1a734e..08e3d91b6 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1144,6 +1144,10 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex)
 	Z_Free((void *)texturesText);
 }
 
+#ifdef EXTRACOLORMAPLUMPS
+static lumplist_t *colormaplumps = NULL; ///\todo free leak
+static size_t numcolormaplumps = 0;
+
 static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list, size_t listsize)
 {
 	size_t i;
@@ -1160,10 +1164,6 @@ static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list
 	return LUMPERROR;
 }
 
-#ifdef EXTRACOLORMAPLUMPS
-static lumplist_t *colormaplumps = NULL; ///\todo free leak
-static size_t numcolormaplumps = 0;
-
 static void R_InitExtraColormaps(void)
 {
 	lumpnum_t startnum, endnum;

From 4cdbc7249ff5a6af8d1b01994950359b16554c73 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Sun, 16 Sep 2018 20:02:29 -0400
Subject: [PATCH 43/48] Streamlined colormap netsyncing so duplicates are not
 saved to $$$.sav per sector

---
 src/p_saveg.c | 196 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 155 insertions(+), 41 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index f9841717e..a63ef1276 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -474,50 +474,144 @@ static void P_NetUnArchivePlayers(void)
 	}
 }
 
-static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc)
+///
+/// Colormaps
+///
+
+static extracolormap_t *net_colormaps = NULL;
+static UINT32 num_net_colormaps = 0;
+
+// Copypasta from r_data.c AddColormapToList
+// But also check for equality and return the matching index
+static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap)
 {
-	if (!exc) // Just give it default values, we done goofed. (or sector->extra_colormap was intentionally set to default (NULL))
-		exc = R_GetDefaultColormap();
+	extracolormap_t *exc;
+	UINT32 i = 0;
 
-	WRITEUINT8(put, exc->fadestart);
-	WRITEUINT8(put, exc->fadeend);
-	WRITEUINT8(put, exc->fog);
+	if (!net_colormaps)
+	{
+		net_colormaps = extra_colormap;
+		net_colormaps->next = 0;
+		net_colormaps->prev = 0;
+		return i;
+	}
 
-	WRITEINT32(put, exc->rgba);
-	WRITEINT32(put, exc->fadergba);
+	for (exc = net_colormaps; exc->next; exc = exc->next)
+	{
+		if (R_CheckEqualColormaps(exc, extra_colormap, true, true, true))
+			return i;
+		i++;
+	}
 
-#ifdef EXTRACOLORMAPLUMPS
-	WRITESTRINGN(put, exc->lumpname, 9);
-#endif
+	exc->next = extra_colormap;
+	extra_colormap->prev = exc;
+	extra_colormap->next = 0;
+
+	num_net_colormaps = i;
+	return i;
 }
 
-static extracolormap_t *LoadExtraColormap(UINT8 *get)
+static extracolormap_t *GetNetColormapFromList(UINT32 index)
 {
-	extracolormap_t *exc, *exc_exist;
+	// For loading, we have to be tricky:
+	// We load the sectors BEFORE knowing the colormap values
+	// So if an index doesn't exist, fill our list with dummy colormaps
+	// until we get the index we want
+	// Then when we load the color data, we set up the dummy colormaps
 
-	UINT8 fadestart = READUINT8(get),
-		fadeend = READUINT8(get),
-		fog = READUINT8(get);
+	extracolormap_t *exc, *last_exc = NULL;
+	UINT32 i = 0;
 
-	INT32 rgba = READINT32(get),
-		fadergba = READINT32(get);
+	for (exc = net_colormaps; exc; last_exc = exc, exc = exc->next)
+	{
+		if (i++ == index)
+			return exc;
+	}
+
+	// our index doesn't exist, so just make the entry
+	for (; i <= index && i < num_net_colormaps; i++)
+	{
+		exc = R_CreateDefaultColormap(false);
+		if (last_exc)
+			last_exc->next = exc;
+		exc->prev = last_exc;
+		exc->next = NULL;
+		last_exc = exc;
+	}
+	return exc;
+}
+
+static void ClearNetColormaps(void)
+{
+	// We're actually Z_Freeing each entry here,
+	// so don't call this in P_NetUnArchiveColormaps (where entries will be used in-game)
+	extracolormap_t *exc, *exc_next;
+
+	for (exc = net_colormaps; exc; exc = exc_next)
+	{
+		exc_next = exc->next;
+		Z_Free(exc);
+	}
+	num_net_colormaps = 0;
+	net_colormaps = NULL;
+}
+
+static void P_NetArchiveColormaps()
+{
+	// We save and then we clean up our colormap mess
+	extracolormap_t *exc, *exc_next;
+
+	WRITEUINT32(save_p, num_net_colormaps); // save for safety
+
+	for (exc = net_colormaps; exc; exc = exc_next)
+	{
+		WRITEUINT8(save_p, exc->fadestart);
+		WRITEUINT8(save_p, exc->fadeend);
+		WRITEUINT8(save_p, exc->fog);
+
+		WRITEINT32(save_p, exc->rgba);
+		WRITEINT32(save_p, exc->fadergba);
 
 #ifdef EXTRACOLORMAPLUMPS
-	char lumpname[9];
-	READSTRINGN(get, lumpname, 9);
-
-	if (lumpname[0])
-		return R_ColormapForName(lumpname);
+		WRITESTRINGN(save_p, exc->lumpname, 9);
 #endif
-	exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
 
-	if (!exc)
+		exc_next = exc->next;
+		Z_Free(exc); // don't need anymore
+	}
+
+	num_net_colormaps = 0;
+}
+
+static void P_NetUnArchiveColormaps()
+{
+	// When we reach this point, we already populated our list with
+	// dummy colormaps. Now that we are loading the color data,
+	// set up the dummies.
+	extracolormap_t *exc, *existing_exc;
+	num_net_colormaps = READUINT32(save_p);
+
+	for (exc = net_colormaps; exc; exc = exc->next)
 	{
-		// CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
-		// 	R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba),
-		//	R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba));
+		UINT8 fadestart = READUINT8(save_p),
+			fadeend = READUINT8(save_p),
+			fog = READUINT8(save_p);
 
-		exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
+		INT32 rgba = READINT32(save_p),
+			fadergba = READINT32(save_p);
+
+#ifdef EXTRACOLORMAPLUMPS
+		char lumpname[9];
+		READSTRINGN(save_p, lumpname, 9);
+
+		if (lumpname[0])
+		{
+			existing_exc = R_ColormapForName(lumpname);
+			*exc = *existing_exc;
+			R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates
+			continue;
+		}
+#endif
 
 		exc->fadestart = fadestart;
 		exc->fadeend = fadeend;
@@ -531,21 +625,32 @@ static extracolormap_t *LoadExtraColormap(UINT8 *get)
 		exc->lumpname[0] = 0;
 #endif
 
-		if (!(exc_exist = R_GetColormapFromList(exc)))
-		{
-			exc->colormap = R_CreateLightTable(exc);
-			R_AddColormapToList(exc);
-		}
+		existing_exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
+
+		if (existing_exc)
+			exc->colormap = existing_exc->colormap;
 		else
-		{
-			Z_Free(exc);
-			exc = R_CheckDefaultColormap(exc_exist, true, true, true) ? NULL : exc_exist;
-		}
+			// CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
+			// 	R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba),
+			//	R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba));
+			exc->colormap = R_CreateLightTable(exc);
+
+		// HACK: If this dummy is a duplicate, we're going to add it
+		// to the extra_colormaps list anyway. I think this is faster
+		// than going through every loaded sector and correcting their
+		// colormap address to the pre-existing one, PER net_colormap entry
+		R_AddColormapToList(exc);
 	}
 
-	return exc;
+	// Don't need these anymore
+	num_net_colormaps = 0;
+	net_colormaps = NULL;
 }
 
+///
+/// World Archiving
+///
+
 #define SD_FLOORHT  0x01
 #define SD_CEILHT   0x02
 #define SD_FLOORPIC 0x04
@@ -595,6 +700,9 @@ static void P_NetArchiveWorld(void)
 	const side_t *si;
 	UINT8 *put;
 
+	// initialize colormap vars because paranoia
+	ClearNetColormaps();
+
 	// reload the map just to see difference
 	mapsector_t *ms;
 	mapsidedef_t *msd;
@@ -730,7 +838,8 @@ static void P_NetArchiveWorld(void)
 			}
 
 			if (diff3 & SD_COLORMAP)
-				SaveExtraColormap(put, ss->extra_colormap);
+				WRITEUINT32(put, CheckAddNetColormapToList(ss->extra_colormap));
+					// returns existing index if already added, or appends to net_colormaps and returns new index
 
 			// Special case: save the stats of all modified ffloors along with their ffloor "number"s
 			// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
@@ -865,6 +974,9 @@ static void P_NetUnArchiveWorld(void)
 	if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
 		I_Error("Bad $$$.sav at archive block World");
 
+	// initialize colormap vars because paranoia
+	ClearNetColormaps();
+
 	get = save_p;
 
 	for (;;)
@@ -927,7 +1039,7 @@ static void P_NetUnArchiveWorld(void)
 		}
 
 		if (diff3 & SD_COLORMAP)
-			sectors[i].extra_colormap = LoadExtraColormap(get);
+			sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(get));
 
 		if (diff & SD_FFLOORS)
 		{
@@ -3536,6 +3648,7 @@ void P_SaveNetGame(void)
 #endif
 		P_NetArchiveThinkers();
 		P_NetArchiveSpecials();
+		P_NetArchiveColormaps();
 	}
 #ifdef HAVE_BLUA
 	LUA_Archive();
@@ -3578,6 +3691,7 @@ boolean P_LoadNetGame(void)
 #endif
 		P_NetUnArchiveThinkers();
 		P_NetUnArchiveSpecials();
+		P_NetUnArchiveColormaps();
 		P_RelinkPointers();
 		P_FinishMobjs();
 	}

From 4b55415add356e051d494cd5bc8d36c316f54456 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Sun, 16 Sep 2018 22:41:08 -0400
Subject: [PATCH 44/48] New colormap netsync fixes

---
 src/p_saveg.c | 79 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 59 insertions(+), 20 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index a63ef1276..34d08d709 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -485,29 +485,30 @@ static UINT32 num_net_colormaps = 0;
 // But also check for equality and return the matching index
 static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap)
 {
-	extracolormap_t *exc;
+	extracolormap_t *exc, *exc_prev;
 	UINT32 i = 0;
 
 	if (!net_colormaps)
 	{
-		net_colormaps = extra_colormap;
+		net_colormaps = R_CopyColormap(extra_colormap, false);
 		net_colormaps->next = 0;
 		net_colormaps->prev = 0;
+		num_net_colormaps = i+1;
 		return i;
 	}
 
-	for (exc = net_colormaps; exc->next; exc = exc->next)
+	for (exc = net_colormaps; exc; exc_prev = exc, exc = exc->next)
 	{
 		if (R_CheckEqualColormaps(exc, extra_colormap, true, true, true))
 			return i;
 		i++;
 	}
 
-	exc->next = extra_colormap;
-	extra_colormap->prev = exc;
+	exc_prev->next = R_CopyColormap(extra_colormap, false);
+	extra_colormap->prev = exc_prev;
 	extra_colormap->next = 0;
 
-	num_net_colormaps = i;
+	num_net_colormaps = i+1;
 	return i;
 }
 
@@ -522,14 +523,24 @@ static extracolormap_t *GetNetColormapFromList(UINT32 index)
 	extracolormap_t *exc, *last_exc = NULL;
 	UINT32 i = 0;
 
+	if (!net_colormaps) // initialize our list
+		net_colormaps = R_CreateDefaultColormap(false);
+
 	for (exc = net_colormaps; exc; last_exc = exc, exc = exc->next)
 	{
 		if (i++ == index)
 			return exc;
 	}
 
+
+	// LET'S HOPE that index is a sane value, because we create up to [index]
+	// entries in net_colormaps. At this point, we don't know
+	// what the total colormap count is
+	if (index >= numsectors*3) // if every sector had a unique colormap change AND a fade thinker which has two colormap entries
+		I_Error("Colormap %d from server is too high for sectors %d", index, numsectors);
+
 	// our index doesn't exist, so just make the entry
-	for (; i <= index && i < num_net_colormaps; i++)
+	for (; i <= index; i++)
 	{
 		exc = R_CreateDefaultColormap(false);
 		if (last_exc)
@@ -556,15 +567,20 @@ static void ClearNetColormaps(void)
 	net_colormaps = NULL;
 }
 
-static void P_NetArchiveColormaps()
+static void P_NetArchiveColormaps(void)
 {
 	// We save and then we clean up our colormap mess
 	extracolormap_t *exc, *exc_next;
-
+	UINT32 i = 0;
 	WRITEUINT32(save_p, num_net_colormaps); // save for safety
 
-	for (exc = net_colormaps; exc; exc = exc_next)
+	for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
 	{
+		// We must save num_net_colormaps worth of data
+		// So fill non-existent entries with default.
+		if (!exc)
+			exc = R_CreateDefaultColormap(false);
+
 		WRITEUINT8(save_p, exc->fadestart);
 		WRITEUINT8(save_p, exc->fadeend);
 		WRITEUINT8(save_p, exc->fog);
@@ -581,31 +597,44 @@ static void P_NetArchiveColormaps()
 	}
 
 	num_net_colormaps = 0;
+	net_colormaps = NULL;
 }
 
-static void P_NetUnArchiveColormaps()
+static void P_NetUnArchiveColormaps(void)
 {
 	// When we reach this point, we already populated our list with
 	// dummy colormaps. Now that we are loading the color data,
 	// set up the dummies.
-	extracolormap_t *exc, *existing_exc;
+	extracolormap_t *exc, *existing_exc, *exc_next = NULL;
 	num_net_colormaps = READUINT32(save_p);
+	UINT32 i = 0;
 
-	for (exc = net_colormaps; exc; exc = exc->next)
+	for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
 	{
-		UINT8 fadestart = READUINT8(save_p),
-			fadeend = READUINT8(save_p),
-			fog = READUINT8(save_p);
-
-		INT32 rgba = READINT32(save_p),
-			fadergba = READINT32(save_p);
-
+		UINT8 fadestart, fadeend, fog;
+		INT32 rgba, fadergba;
 #ifdef EXTRACOLORMAPLUMPS
 		char lumpname[9];
+#endif
+
+		fadestart = READUINT8(save_p);
+		fadeend = READUINT8(save_p);
+		fog = READUINT8(save_p);
+
+		rgba = READINT32(save_p);
+		fadergba = READINT32(save_p);
+
+#ifdef EXTRACOLORMAPLUMPS
 		READSTRINGN(save_p, lumpname, 9);
 
 		if (lumpname[0])
 		{
+			if (!exc)
+				// no point making a new entry since nothing points to it,
+				// but we needed to read the data so now continue
+				continue;
+
+			exc_next = exc->next; // this gets overwritten during our operations here, so get it now
 			existing_exc = R_ColormapForName(lumpname);
 			*exc = *existing_exc;
 			R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates
@@ -613,6 +642,13 @@ static void P_NetUnArchiveColormaps()
 		}
 #endif
 
+		if (!exc)
+			// no point making a new entry since nothing points to it,
+			// but we needed to read the data so now continue
+			continue;
+
+		exc_next = exc->next; // this gets overwritten during our operations here, so get it now
+
 		exc->fadestart = fadestart;
 		exc->fadeend = fadeend;
 		exc->fog = fog;
@@ -640,6 +676,9 @@ static void P_NetUnArchiveColormaps()
 		// than going through every loaded sector and correcting their
 		// colormap address to the pre-existing one, PER net_colormap entry
 		R_AddColormapToList(exc);
+
+		if (i < num_net_colormaps-1 && !exc_next)
+			exc_next = R_CreateDefaultColormap(false);
 	}
 
 	// Don't need these anymore

From f3e1d280d07a234c7070384f6d514fba32085808 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 17 Sep 2018 00:26:58 -0400
Subject: [PATCH 45/48] Colormap netsync: Mixed D+C fixes

---
 src/p_saveg.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 34d08d709..ec0ef2e7a 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -606,9 +606,10 @@ static void P_NetUnArchiveColormaps(void)
 	// dummy colormaps. Now that we are loading the color data,
 	// set up the dummies.
 	extracolormap_t *exc, *existing_exc, *exc_next = NULL;
-	num_net_colormaps = READUINT32(save_p);
 	UINT32 i = 0;
 
+	num_net_colormaps = READUINT32(save_p);
+
 	for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
 	{
 		UINT8 fadestart, fadeend, fog;
@@ -739,9 +740,6 @@ static void P_NetArchiveWorld(void)
 	const side_t *si;
 	UINT8 *put;
 
-	// initialize colormap vars because paranoia
-	ClearNetColormaps();
-
 	// reload the map just to see difference
 	mapsector_t *ms;
 	mapsidedef_t *msd;
@@ -749,6 +747,9 @@ static void P_NetArchiveWorld(void)
 	const sector_t *ss = sectors;
 	UINT8 diff, diff2, diff3;
 
+	// initialize colormap vars because paranoia
+	ClearNetColormaps();
+
 	WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
 	put = save_p;
 

From 752a9630372d787625459050053ffae98a8a6689 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 17 Sep 2018 08:05:51 -0400
Subject: [PATCH 46/48] Colormap netsync: String format numsectors to UINT32
 (thanks buildbot)

---
 src/p_saveg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index ec0ef2e7a..b98a34436 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -537,7 +537,7 @@ static extracolormap_t *GetNetColormapFromList(UINT32 index)
 	// entries in net_colormaps. At this point, we don't know
 	// what the total colormap count is
 	if (index >= numsectors*3) // if every sector had a unique colormap change AND a fade thinker which has two colormap entries
-		I_Error("Colormap %d from server is too high for sectors %d", index, numsectors);
+		I_Error("Colormap %d from server is too high for sectors %d", index, (UINT32)numsectors);
 
 	// our index doesn't exist, so just make the entry
 	for (; i <= index; i++)

From d417f733e5b00c54233c36d8b61b69f14d5ba996 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 17 Sep 2018 10:24:55 -0400
Subject: [PATCH 47/48] Colormap netsync: Handle unaccounted dummy colormaps
 properly

---
 src/p_saveg.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index b98a34436..c0f98d88b 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -682,6 +682,20 @@ static void P_NetUnArchiveColormaps(void)
 			exc_next = R_CreateDefaultColormap(false);
 	}
 
+	// if we still have a valid net_colormap after iterating up to num_net_colormaps,
+	// some sector had a colormap index higher than num_net_colormaps. We done goofed or $$$ was corrupted.
+	// In any case, add them to the colormap list too so that at least the sectors' colormap
+	// addresses are valid and accounted properly
+	if (exc_next)
+	{
+		existing_exc = R_GetDefaultColormap();
+		for (exc = exc_next; exc; exc = exc->next)
+		{
+			exc->colormap = existing_exc->colormap; // all our dummies are default values
+			R_AddColormapToList(exc);
+		}
+	}
+
 	// Don't need these anymore
 	num_net_colormaps = 0;
 	net_colormaps = NULL;

From 69a4906911aa206ac0dffc10a5b5536e692edbb7 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 17 Sep 2018 10:38:09 -0400
Subject: [PATCH 48/48] Colormap netsync: Count ffloors for colormap loading
 upper limit

---
 src/p_saveg.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index c0f98d88b..b8af7cff6 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -480,6 +480,7 @@ static void P_NetUnArchivePlayers(void)
 
 static extracolormap_t *net_colormaps = NULL;
 static UINT32 num_net_colormaps = 0;
+static UINT32 num_ffloors = 0; // for loading
 
 // Copypasta from r_data.c AddColormapToList
 // But also check for equality and return the matching index
@@ -536,7 +537,9 @@ static extracolormap_t *GetNetColormapFromList(UINT32 index)
 	// LET'S HOPE that index is a sane value, because we create up to [index]
 	// entries in net_colormaps. At this point, we don't know
 	// what the total colormap count is
-	if (index >= numsectors*3) // if every sector had a unique colormap change AND a fade thinker which has two colormap entries
+	if (index >= numsectors*3 + num_ffloors)
+		// if every sector had a unique colormap change AND a fade color thinker which has two colormap entries
+		// AND every ffloor had a fade FOF thinker with one colormap entry
 		I_Error("Colormap %d from server is too high for sectors %d", index, (UINT32)numsectors);
 
 	// our index doesn't exist, so just make the entry
@@ -564,6 +567,7 @@ static void ClearNetColormaps(void)
 		Z_Free(exc);
 	}
 	num_net_colormaps = 0;
+	num_ffloors = 0;
 	net_colormaps = NULL;
 }
 
@@ -597,6 +601,7 @@ static void P_NetArchiveColormaps(void)
 	}
 
 	num_net_colormaps = 0;
+	num_ffloors = 0;
 	net_colormaps = NULL;
 }
 
@@ -698,6 +703,7 @@ static void P_NetUnArchiveColormaps(void)
 
 	// Don't need these anymore
 	num_net_colormaps = 0;
+	num_ffloors = 0;
 	net_colormaps = NULL;
 }
 
@@ -1031,6 +1037,14 @@ static void P_NetUnArchiveWorld(void)
 	// initialize colormap vars because paranoia
 	ClearNetColormaps();
 
+	// count the level's ffloors so that colormap loading can have an upper limit
+	for (i = 0; i < numsectors; i++)
+	{
+		ffloor_t *rover;
+		for (rover = sectors[i].ffloors; rover; rover = rover->next)
+			num_ffloors++;
+	}
+
 	get = save_p;
 
 	for (;;)