ref: 781eeead92f56bd399624c6f3edc0568935cf9b1
parent: 737261dbcd07d9dccd1fa76b3ef43c225dad4278
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
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;
}