Classic-noasm: fix drawing of walls and maskwalls with non-pow2 y size tiles.

Related to that, it looks like out-of-bounds accesses when drawing such walls/
maskwalls or *sprites* are fixed, too.  Sprites still show a stray lines on some
occasions, but Valgrind doesn't complain then.

git-svn-id: https://svn.eduke32.com/eduke32@2805 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2012-07-06 11:26:24 +00:00
parent 51331e11a0
commit 5a96b4e572
2 changed files with 114 additions and 26 deletions

View file

@ -88,6 +88,22 @@ void slopevlin(intptr_t p, int32_t i, intptr_t slopaloffs, int32_t cnt, int32_t
///// Wall,face sprite/wall sprite vertical line functions /////
extern int32_t globaltilesizy;
static inline uint32_t ourmulscale32(uint32_t a, uint32_t b)
{
return ((uint64_t)a*b)>>32;
}
static inline int32_t getpix(int32_t logy, const char *buf, uint32_t vplc)
{
if (logy != 0)
return buf[vplc>>logy];
else
return buf[ourmulscale32(vplc,globaltilesizy)];
}
void setupvlineasm(int32_t neglogy) { glogy = neglogy; }
// cnt+1 loop iterations!
int32_t vlineasm1(int32_t vinc, intptr_t paloffs, int32_t cnt, uint32_t vplc, intptr_t bufplc, intptr_t p)
@ -101,7 +117,11 @@ int32_t vlineasm1(int32_t vinc, intptr_t paloffs, int32_t cnt, uint32_t vplc, in
do
{
*pp = pal[buf[vplc>>logy]];
if (logy != 0)
*pp = pal[buf[vplc>>logy]];
else
*pp = pal[buf[ourmulscale32(vplc,globaltilesizy)]];
pp += ourbpl;
vplc += vinc;
}
@ -145,7 +165,8 @@ void vlineasm4(int32_t cnt, char *p)
{
for (i=0; i<4; i++)
{
ch = buf[i][vplc[i]>>logy]; p[i] = pal[i][ch];
ch = getpix(logy, buf[i], vplc[i]);
p[i] = pal[i][ch];
vplc[i] += vinc[i];
}
p += ourbpl;
@ -170,7 +191,8 @@ int32_t mvlineasm1(int32_t vinc, intptr_t paloffs, int32_t cnt, uint32_t vplc, i
do
{
ch = buf[vplc>>logy]; if (ch != 255) *pp = pal[ch];
ch = getpix(logy, buf, vplc);
if (ch != 255) *pp = pal[ch];
pp += ourbpl;
vplc += vinc;
}
@ -196,7 +218,8 @@ void mvlineasm4(int32_t cnt, char *p)
{
for (i=0; i<4; i++)
{
ch = buf[i][vplc[i]>>logy]; if (ch != 255) p[i] = pal[i][ch];
ch = getpix(logy, buf[i], vplc[i]);
if (ch != 255) p[i] = pal[i][ch];
vplc[i] += vinc[i];
}
p += ourbpl;
@ -225,7 +248,7 @@ int32_t tvlineasm1(int32_t vinc, intptr_t paloffs, int32_t cnt, uint32_t vplc, i
{
do
{
ch = buf[vplc>>logy];
ch = getpix(logy, buf, vplc);
if (ch != 255) *pp = trans[(*pp)|(pal[ch]<<8)];
pp += ourbpl;
vplc += vinc;
@ -236,7 +259,7 @@ int32_t tvlineasm1(int32_t vinc, intptr_t paloffs, int32_t cnt, uint32_t vplc, i
{
do
{
ch = buf[vplc>>logy];
ch = getpix(logy, buf, vplc);
if (ch != 255) *pp = trans[((*pp)<<8)|pal[ch]];
pp += ourbpl;
vplc += vinc;
@ -274,11 +297,11 @@ void tvlineasm2(uint32_t vplc2, int32_t vinc1, intptr_t bufplc1, intptr_t bufplc
{
do
{
ch = buf1[vplc1>>logy];
ch = getpix(logy, buf1, vplc1);
if (ch != 255) pp[0] = gtrans[pp[0]|(gpal[ch]<<8)];
vplc1 += vinc1;
ch = buf2[vplc2>>logy];
ch = getpix(logy, buf2, vplc2);
if (ch != 255) pp[1] = gtrans[pp[1]|(gpal2[ch]<<8)];
vplc2 += vinc2;
@ -290,11 +313,11 @@ void tvlineasm2(uint32_t vplc2, int32_t vinc1, intptr_t bufplc1, intptr_t bufplc
{
do
{
ch = buf1[vplc1>>logy];
ch = getpix(logy, buf1, vplc1);
if (ch != 255) pp[0] = gtrans[(pp[0]<<8)|gpal[ch]];
vplc1 += vinc1;
ch = buf2[vplc2>>logy];
ch = getpix(logy, buf2, vplc2);
if (ch != 255) pp[1] = gtrans[(pp[1]<<8)|gpal2[ch]];
vplc2 += vinc2;

View file

@ -2250,6 +2250,8 @@ static int32_t globalzd, globalyscale;
static int32_t globalxspan, globalyspan, globalispow2=1; // true if texture has power-of-two x and y size
static intptr_t globalbufplc;
int32_t globaltilesizy;
int32_t globalx1, globaly2, globalx3, globaly3;
static int32_t globaly1, globalx2, globalzx;
static int32_t globalx, globaly, globalz;
@ -4501,15 +4503,42 @@ static void setup_globals_wall1(const walltype *wal, int32_t dapicnum)
static void setup_globals_wall2(const walltype *wal, uint8_t secvisibility, int32_t topzref, int32_t botzref)
{
const int32_t logtilesizy = (picsiz[globalpicnum]>>4);
const int32_t tsizy = tilesizy[globalpicnum];
if (tsizy==0)
{
globalshiftval = -1;
return;
}
globvis = globalvisibility;
if (secvisibility != 0)
globvis = mulscale4(globvis, (int32_t)((uint8_t)(secvisibility+16)));
globalshiftval = (picsiz[globalpicnum]>>4);
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
globalshiftval = 32-globalshiftval;
globalshiftval = logtilesizy;
#if !defined ENGINE_USING_A_C
// before proper non-power-of-two tilesizy drawing
if (pow2long[logtilesizy] != tilesizy[globalpicnum])
globalshiftval++;
globalyscale = (wal->yrepeat<<(globalshiftval-19));
if (1)
#else
// non power-of-two y size textures!
if (pow2long[logtilesizy] == tsizy)
#endif
{
// globalshiftval==13 --> globalshiftval==19
// ==> upper texture y size limit *here* = 8192
globalshiftval = 32-globalshiftval;
globalyscale = wal->yrepeat<<(globalshiftval-19);
}
else
{
globaltilesizy = tsizy;
globalyscale = divscale13(wal->yrepeat, tsizy);
globalshiftval = 0;
}
if ((globalorientation&4) == 0)
globalzd = (((int64_t)(globalposz-topzref)*globalyscale)<<8);
@ -4789,8 +4818,11 @@ static void drawalls(int32_t bunch)
setup_globals_wall1(wal, wal->picnum);
setup_globals_wall2(wal, sec->visibility, nextsec->ceilingz, sec->ceilingz);
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
wallscan(x1,x2,uplc,dwall,swall,lwall);
if (globalshiftval >= 0)
{
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
wallscan(x1,x2,uplc,dwall,swall,lwall);
}
if ((cz[2] >= cz[0]) && (cz[3] >= cz[1]))
{
@ -4878,8 +4910,11 @@ static void drawalls(int32_t bunch)
setup_globals_wall2(wal, sec->visibility, nextsec->floorz, sec->ceilingz);
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
wallscan(x1,x2,uwall,dplc,swall,lwall);
if (globalshiftval >= 0)
{
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
wallscan(x1,x2,uwall,dplc,swall,lwall);
}
if ((fz[2] <= fz[0]) && (fz[3] <= fz[1]))
{
@ -4959,8 +4994,11 @@ static void drawalls(int32_t bunch)
(nextsectnum >= 0) ? nextsec->ceilingz : sec->ceilingz,
(nextsectnum >= 0) ? sec->ceilingz : sec->floorz);
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
wallscan(x1,x2,uplc,dplc,swall,lwall);
if (globalshiftval >= 0)
{
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
wallscan(x1,x2,uplc,dplc,swall,lwall);
}
#ifdef YAX_ENABLE
// TODO: slopes?
@ -5315,10 +5353,12 @@ static void drawvox(int32_t dasprx, int32_t daspry, int32_t dasprz, int32_t dasp
enddrawing(); //}}}
}
static void setup_globals_sprite1(const spritetype *tspr, const sectortype *sec,
int32_t yspan, int32_t yoff, int32_t tilenum,
int32_t cstat, int32_t *z1ptr, int32_t *z2ptr)
{
int32_t logtilesizy, tsizy;
int32_t z1, z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
if (cstat&128)
@ -5337,11 +5377,31 @@ static void setup_globals_sprite1(const spritetype *tspr, const sectortype *sec,
globvis = globalvisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16)));
globalshiftval = (picsiz[globalpicnum]>>4);
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
globalshiftval = 32-globalshiftval;
logtilesizy = (picsiz[globalpicnum]>>4);
tsizy = tilesizy[globalpicnum];
globalshiftval = logtilesizy;
#if !defined ENGINE_USING_A_C
// before proper non-power-of-two tilesizy drawing
if (pow2long[logtilesizy] != tilesizy[globalpicnum])
globalshiftval++;
if (1)
#else
// non power-of-two y size textures!
if (pow2long[logtilesizy] == tsizy)
#endif
{
globalshiftval = 32-globalshiftval;
globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
}
else
{
globaltilesizy = tsizy;
globalyscale = (1<<22)/(tsizy*tspr->yrepeat);
globalshiftval = 0;
}
globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
globalzd = ((int64_t)(globalposz-z1)*globalyscale)<<8;
if ((cstat&8) > 0)
{
@ -6373,14 +6433,19 @@ static void drawmaskwall(int16_t damaskwallcnt)
}
if ((globalorientation&128) == 0)
maskwallscan(xb1[z],xb2[z],uwall,dwall,swall,lwall);
{
if (globalshiftval >= 0)
maskwallscan(xb1[z],xb2[z],uwall,dwall,swall,lwall);
}
else
{
if (globalorientation&128)
{
if (globalorientation&512) settransreverse(); else settransnormal();
}
transmaskwallscan(xb1[z],xb2[z]);
if (globalshiftval >= 0)
transmaskwallscan(xb1[z],xb2[z]);
}
}