diff --git a/src/asm_ia32/tmap2.asm b/src/asm_ia32/tmap2.asm index 9a7aa5534..ab1695d3c 100644 --- a/src/asm_ia32/tmap2.asm +++ b/src/asm_ia32/tmap2.asm @@ -198,7 +198,10 @@ SetTiltedSpanSize: mov [y8+2],cl mov [y9+2],cl mov [y10+2],cl + cmp eax,0 ; if x bits is 0, mask must be 0 too. + jz .notted not eax +.notted: pop ecx mov [m1+2],eax diff --git a/src/r_plane.cpp b/src/r_plane.cpp index f238c47d0..21cea7bcf 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -224,10 +224,26 @@ void R_MapPlane (int y, int x1) distance = planeheight * yslope[y]; - ds_xstep = xs_ToFixed(32-ds_xbits, distance * xstepscale); - ds_ystep = xs_ToFixed(32-ds_ybits, distance * ystepscale); - ds_xfrac = xs_ToFixed(32-ds_xbits, distance * basexfrac) + pviewx; - ds_yfrac = xs_ToFixed(32-ds_ybits, distance * baseyfrac) + pviewy; + if (ds_xbits != 0) + { + ds_xstep = xs_ToFixed(32 - ds_xbits, distance * xstepscale); + ds_xfrac = xs_ToFixed(32 - ds_xbits, distance * basexfrac) + pviewx; + } + else + { + ds_xstep = 0; + ds_xfrac = 0; + } + if (ds_ybits != 0) + { + ds_ystep = xs_ToFixed(32 - ds_ybits, distance * ystepscale); + ds_yfrac = xs_ToFixed(32 - ds_ybits, distance * baseyfrac) + pviewy; + } + else + { + ds_ystep = 0; + ds_yfrac = 0; + } if (plane_shade) { @@ -368,18 +384,18 @@ void R_MapTiltedPlane_C (int y, int x1) DWORD u, v; int i; - iz = plane_sz[2] + plane_sz[1]*(centery-y) + plane_sz[0]*(x1-centerx); + iz = plane_sz[2] + plane_sz[1] * (centery - y) + plane_sz[0] * (x1 - centerx); // Lighting is simple. It's just linear interpolation from start to end if (plane_shade) { - uz = (iz + plane_sz[0]*width) * planelightfloat; + uz = (iz + plane_sz[0] * width) * planelightfloat; vz = iz * planelightfloat; - R_CalcTiltedLighting (vz, uz, width); + R_CalcTiltedLighting(vz, uz, width); } - uz = plane_su[2] + plane_su[1]*(centery-y) + plane_su[0]*(x1-centerx); - vz = plane_sv[2] + plane_sv[1]*(centery-y) + plane_sv[0]*(x1-centerx); + uz = plane_su[2] + plane_su[1] * (centery - y) + plane_su[0] * (x1 - centerx); + vz = plane_sv[2] + plane_sv[1] * (centery - y) + plane_sv[0] * (x1 - centerx); fb = ylookup[y] + x1 + dc_destorg; @@ -2116,6 +2132,15 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t } } + // Hack in support for 1 x Z and Z x 1 texture sizes + if (ds_ybits == 0) + { + plane_sv[2] = plane_sv[1] = plane_sv[0] = 0; + } + if (ds_xbits == 0) + { + plane_su[2] = plane_su[1] = plane_su[0] = 0; + } #if defined(X86_ASM) if (!r_swtruecolor) { diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 8c00faa7f..108463e38 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1093,21 +1093,31 @@ WallscanSampler::WallscanSampler(int y1, float swal, double yrepeat, fixed_t xof if (!r_swtruecolor) { height = texture->GetHeight(); + int uv_fracbits = 32 - texture->HeightBits; - uv_max = height << uv_fracbits; + if (uv_fracbits != 32) + { + uv_max = height << uv_fracbits; - // Find start uv in [0-base_height[ range. - // Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range. - double uv_stepd = swal * yrepeat; - double v = (dc_texturemid + uv_stepd * (y1 - CenterY + 0.5)) / height; - v = v - floor(v); - v *= height; - v *= (1 << uv_fracbits); + // Find start uv in [0-base_height[ range. + // Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range. + double uv_stepd = swal * yrepeat; + double v = (dc_texturemid + uv_stepd * (y1 - CenterY + 0.5)) / height; + v = v - floor(v); + v *= height; + v *= (1 << uv_fracbits); - uv_pos = (uint32_t)v; - uv_step = xs_ToFixed(uv_fracbits, uv_stepd); - if (uv_step == 0) // To prevent divide by zero elsewhere - uv_step = 1; + uv_pos = (uint32_t)v; + uv_step = xs_ToFixed(uv_fracbits, uv_stepd); + if (uv_step == 0) // To prevent divide by zero elsewhere + uv_step = 1; + } + else + { // Hack for one pixel tall textures + uv_pos = 0; + uv_step = 0; + uv_max = 1; + } source = getcol(texture, xoffset >> FRACBITS); source2 = nullptr; @@ -1368,11 +1378,19 @@ void wallscan_any( return; fixed_t xoffset = rw_offset; + rw_pic->GetHeight(); // To ensure that rw_pic->HeightBits has been set + int fracbits = 32 - rw_pic->HeightBits; + if (fracbits == 32) + { // Hack for one pixel tall textures + fracbits = 0; + yrepeat = 0; + dc_texturemid = 0; + } DWORD(*draw1column)(); void(*draw4columns)(); - setupwallscan(r_swtruecolor ? FRACBITS : 32 - rw_pic->HeightBits, draw1column, draw4columns); + setupwallscan(r_swtruecolor ? FRACBITS : fracbits, draw1column, draw4columns); bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0); if (fixed) diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 04e62bed9..5774a0048 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -241,8 +241,9 @@ void FTexture::CalcBitSize () } WidthMask = (1 << WidthBits) - 1; - // The minimum height is 2, because we cannot shift right 32 bits. - for (i = 1; (1 << i) < Height; ++i) + //
The minimum height is 2, because we cannot shift right 32 bits. + // Scratch that. Somebody actually made a 1x1 texture, so now we have to handle it. + for (i = 0; (1 << i) < Height; ++i) { } HeightBits = i;