shithub: qk1

Download patch

ref: 781eeead92f56bd399624c6f3edc0568935cf9b1
parent: 737261dbcd07d9dccd1fa76b3ef43c225dad4278
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Wed Dec 13 09:18:57 EST 2023

bsp30: palette isn't always 256 colors, nor 'transparent' is _blue_. fix that

--- a/common.c
+++ b/common.c
@@ -7,18 +7,23 @@
 bool		standard_quake = true, rogue, hipnotic;
 
 void
-pal3torgbx(byte *in, pixel_t *out, int n, byte *pal)
+pal3torgbx(byte *in, pixel_t *out, int n, byte *pal, int palsz)
 {
 	int x;
 
+	palsz *= 3;
 	if(in < (byte*)out || in > (byte*)(out+n) || in+n < (byte*)out){
 		while(n-- > 0){
 			x = (*in++)*3;
+			if(x >= palsz)
+				x = 0;
 			*out++ = 0xff<<24 | pal[x+0]<<16 | pal[x+1]<<8 | pal[x+2];
 		}
 	}else{
 		while(n-- > 0){
 			x = in[n]*3;
+			if(x >= palsz)
+				x = 0;
 			out[n] = 0xff<<24 | pal[x+0]<<16 | pal[x+1]<<8 | pal[x+2];
 		}
 	}
--- a/model_bsp30.c
+++ b/model_bsp30.c
@@ -153,9 +153,15 @@
 		if(tx->offsets[0] >= 0){
 			// the pixels immediately follow the structures
 			x = p + pixels;
-			palsz = le16(x);
-			if(palsz == 256)
-				pal3torgbx(p, tx->pixels, pixels, x);
+			if((palsz = le16(x)) > 0){
+				pal3torgbx(p, tx->pixels, pixels, x, palsz);
+				if(tx->name[0] == '{'){
+					for(j = 0; j < pixels; j++){
+						if(p[j] == palsz-1)
+							tx->pixels[j] = 0;
+					}
+				}
+			}
 		}else{
 			// alternative: outside, in a wad
 			for(j = 0; j < mod->numwads; j++){
@@ -167,12 +173,6 @@
 		}
 		if(strncmp(tx->name, "sky", 3) == 0)
 			R_InitSky(nil); /* FIXME(sigrid): skybox */
-		else if(tx->name[0] == '{'){
-			for(j = 0; j < pixels; j++){
-				if((tx->pixels[j] & 0xffffff) == 0x0000ff)
-					tx->pixels[j] = 0;
-			}
-		}
 	}
 
 	// sequence the animations
--- a/quakedef.h
+++ b/quakedef.h
@@ -182,7 +182,7 @@
 #define opaque(p) ((p) != 0)
 
 extern pixel_t q1pal[256];
-void pal3torgbx(byte *in, pixel_t *out, int n, byte *pal);
+void pal3torgbx(byte *in, pixel_t *out, int n, byte *pal, int palsz);
 void paltorgbx(byte *in, pixel_t *out, int n, pixel_t *pal);
 void torgbx(byte *in, pixel_t *out, int n);
 
--- a/wad.c
+++ b/wad.c
@@ -157,7 +157,7 @@
 }
 
 static int
-W_ReadPixelsAt(Wad *wad, int off, int sz, pixel_t *out, int num)
+W_ReadPixelsAt(Wad *wad, char *name, int off, int sz, pixel_t *out, int num)
 {
 	int n, palsz, x;
 	byte *t, *pal;
@@ -175,14 +175,18 @@
 		}
 		pal = t + num;
 		palsz = le16(pal);
-		if(palsz < 0 || palsz > 256 || off+num+2+palsz*3 > wad->sz){
+		if(palsz <= 0 || palsz > 256 || off+num+2+palsz*3 > wad->sz){
 			werrstr("invalid palette: palsz=%d pal_end=%d wad_sz=%d",
 				palsz, off+num+2+palsz*3, wad->sz);
 			goto err;
 		}
-		for(n = 0; n < num; n++){
+		palsz *= 3;
+		for(n = 0; n < num; n++, out++){
 			x = (*t++)*3;
-			*out++ = x < palsz*3 ? (0xff<<24 | pal[x+0]<<16 | pal[x+1]<<8 | pal[x+2]) : 0;
+			if(x >= palsz || (wad->ver == WAD_VER3 && name[0] == '{' && x == palsz-3))
+				*out = 0;
+			else
+				*out = 0xff<<24 | pal[x+0]<<16 | pal[x+1]<<8 | pal[x+2];
 		}
 	}
 	return num;
@@ -210,7 +214,7 @@
 	for(i = 0; i < nelem(t->offsets); i++)
 		t->offsets[i] = le32(p) - (16+2*4+4*4);
 	off = p - wad->in;
-	if((n = W_ReadPixelsAt(wad, off, lmp->off+lmp->sz-off, (pixel_t*)(t+1), n)) < 0)
+	if((n = W_ReadPixelsAt(wad, name, off, lmp->off+lmp->sz-off, (pixel_t*)(t+1), n)) < 0)
 		werrstr("%s: %s", name, lerr());
 	return n;
 }
@@ -223,7 +227,7 @@
 
 	if((lmp = W_FindName(wad, name)) == nil)
 		return -1;
-	if((n = W_ReadPixelsAt(wad, lmp->off, lmp->sz, out, num)) < 0)
+	if((n = W_ReadPixelsAt(wad, name, lmp->off, lmp->sz, out, num)) < 0)
 		werrstr("%s: %s", name, lerr());
 	return n;
 }