diff --git a/src/console.c b/src/console.c index 751a6e5cad06a57a1c3d3e7f3653dac13e2e2964..93b9fb54d022d71b0917c6a4cd351d2acda4d1e1 100644 --- a/src/console.c +++ b/src/console.c @@ -1780,10 +1780,10 @@ static void CON_DrawBackpic(void) // then fill the sides with a solid color. if (x > 0) { - column_t *column = (column_t *)((UINT8 *)(con_backpic->columns) + (con_backpic->columnofs[0])); - if (!column->topdelta) + column_t *column = &con_backpic->columns[0]; + if (column->num_posts && !column->posts[0].topdelta) { - UINT8 *source = (UINT8 *)(column) + 3; + UINT8 *source = column->pixels; INT32 color = (source[0] | V_NOSCALESTART); // left side V_DrawFill(0, 0, x, con_curlines, color); diff --git a/src/doomdef.h b/src/doomdef.h index 4db1b87bdbc6f651df23ffc2cdb97533b8415469..4c843f9e2f07ad58439d2dcd3200726e6d62fa4d 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -733,9 +733,6 @@ extern int #define NO_PNG_LUMPS #endif -/// Render flats on walls -#define WALLFLATS - /// Maintain compatibility with older 2.2 demos #define OLD22DEMOCOMPAT diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index d6245df6490da4f1cfb2bc11271c8d798e7ba980..58e16d62361a9ca3f87479ea273343c7c36065bc 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -54,7 +54,6 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm fixed_t yfrac, position, count; UINT8 *dest; const UINT8 *source; - INT32 topdelta, prevdelta = -1; INT32 originy = 0; // for writing a pixel to dest @@ -68,18 +67,14 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm if (originPatch) // originPatch can be NULL here, unlike in the software version originy = originPatch->originy; - while (patchcol->topdelta != 0xff) + for (unsigned i = 0; i < patchcol->num_posts; i++) { - topdelta = patchcol->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)patchcol + 3; - count = ((patchcol->length * scale_y) + (FRACUNIT/2)) >> FRACBITS; - position = originy + topdelta; + post_t *post = &patchcol->posts[i]; + source = patchcol->pixels + post->data_offset; + count = ((post->length * scale_y) + (FRACUNIT/2)) >> FRACBITS; + position = originy + post->topdelta; yfrac = 0; - //yfracstep = (patchcol->length << FRACBITS) / count; if (position < 0) { yfrac = -position<<FRACBITS; @@ -106,53 +101,50 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) alpha = 0x00; - //Hurdler: 25/04/2000: now support colormap in hardware mode if (mipmap->colormap) texel = mipmap->colormap->data[texel]; - // hope compiler will get this switch out of the loops (dreams...) - // gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?) - // Alam: SRB2 uses Mingw, HUGS switch (bpp) { - case 2 : // uhhhhhhhh.......... - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); - texelu16 = (UINT16)((alpha<<8) | texel); - memcpy(dest, &texelu16, sizeof(UINT16)); - break; - case 3 : colortemp = V_GetColor(texel); - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - { - RGBA_t rgbatexel; - rgbatexel.rgba = *(UINT32 *)dest; - colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); - } - memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); - break; - case 4 : colortemp = V_GetColor(texel); - colortemp.s.alpha = alpha; - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - { - RGBA_t rgbatexel; - rgbatexel.rgba = *(UINT32 *)dest; - colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); - } - memcpy(dest, &colortemp, sizeof(RGBA_t)); - break; + case 2: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); + memcpy(dest, &texelu16, sizeof(UINT16)); + break; + case 3: + colortemp = V_GetColor(texel); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); + break; + case 4: + colortemp = V_GetColor(texel); + colortemp.s.alpha = alpha; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)); + break; // default is 1 default: - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); - else - *dest = texel; - break; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; + break; } dest += blockmodulo; yfrac += yfracstep; } - patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4); } } @@ -165,7 +157,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, fixed_t yfrac, position, count; UINT8 *dest; const UINT8 *source; - INT32 topdelta, prevdelta = -1; + INT32 topdelta; INT32 originy = 0; // for writing a pixel to dest @@ -177,18 +169,15 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, if (originPatch) // originPatch can be NULL here, unlike in the software version originy = originPatch->originy; - while (patchcol->topdelta != 0xff) + for (unsigned i = 0; i < patchcol->num_posts; i++) { - topdelta = patchcol->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topdelta = patchheight-patchcol->length-topdelta; - source = (const UINT8 *)patchcol + 3; - count = ((patchcol->length * scale_y) + (FRACUNIT/2)) >> FRACBITS; + post_t *post = &patchcol->posts[i]; + source = patchcol->pixels + post->data_offset; + topdelta = patchheight-post->length-post->topdelta; + count = ((post->length * scale_y) + (FRACUNIT/2)) >> FRACBITS; position = originy + topdelta; - yfrac = (patchcol->length-1) << FRACBITS; + yfrac = (post->length-1) << FRACBITS; if (position < 0) { @@ -216,57 +205,53 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) alpha = 0x00; - //Hurdler: 25/04/2000: now support colormap in hardware mode if (mipmap->colormap) texel = mipmap->colormap->data[texel]; - // hope compiler will get this switch out of the loops (dreams...) - // gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?) - // Alam: SRB2 uses Mingw, HUGS switch (bpp) { - case 2 : // uhhhhhhhh.......... - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); - texelu16 = (UINT16)((alpha<<8) | texel); - memcpy(dest, &texelu16, sizeof(UINT16)); - break; - case 3 : colortemp = V_GetColor(texel); - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - { - RGBA_t rgbatexel; - rgbatexel.rgba = *(UINT32 *)dest; - colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); - } - memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); - break; - case 4 : colortemp = V_GetColor(texel); - colortemp.s.alpha = alpha; - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - { - RGBA_t rgbatexel; - rgbatexel.rgba = *(UINT32 *)dest; - colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); - } - memcpy(dest, &colortemp, sizeof(RGBA_t)); - break; + case 2: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); + memcpy(dest, &texelu16, sizeof(UINT16)); + break; + case 3: + colortemp = V_GetColor(texel); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); + break; + case 4: + colortemp = V_GetColor(texel); + colortemp.s.alpha = alpha; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)); + break; // default is 1 default: - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); - else - *dest = texel; - break; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; + break; } dest += blockmodulo; yfrac -= yfracstep; } - patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4); } } - // Simplified patch caching function // for use by sprites and other patches that are not part of a wall texture // no alpha or flipping should be present since we do not want non-texture graphics to have them @@ -307,7 +292,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, // Draw each column to the block cache for (; ncols--; block += bpp, xfrac += xfracstep) { - patchcol = (const column_t *)((const UINT8 *)realpatch->columns + (realpatch->columnofs[xfrac>>FRACBITS])); + patchcol = &realpatch->columns[xfrac>>FRACBITS]; HWR_DrawColumnInCache(patchcol, block, mipmap, pblockheight, blockmodulo, @@ -321,7 +306,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 pblockheight, texture_t *texture, texpatch_t *patch, - const softwarepatch_t *realpatch) + const patch_t *realpatch) { INT32 x, x1, x2; INT32 col, ncols; @@ -345,8 +330,8 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; x1 = patch->originx; - width = SHORT(realpatch->width); - height = SHORT(realpatch->height); + width = realpatch->width; + height = realpatch->height; x2 = x1 + width; if (x1 > texture->width || x2 < 0) @@ -372,14 +357,6 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, col = x * pblockwidth / texture->width; ncols = ((x2 - x) * pblockwidth) / texture->width; -/* - CONS_Debug(DBG_RENDER, "patch %dx%d texture %dx%d block %dx%d\n", - width, height, - texture->width, texture->height, - pblockwidth, pblockheight); - CONS_Debug(DBG_RENDER, " col %d ncols %d x %d\n", col, ncols, x); -*/ - // source advance xfrac = 0; if (x1 < 0) @@ -401,9 +378,9 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep) { if (patch->flip & 1) - patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[(width-1)-(xfrac>>FRACBITS)])); + patchcol = &realpatch->columns[(width-1)-(xfrac>>FRACBITS)]; else - patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS])); + patchcol = &realpatch->columns[xfrac>>FRACBITS]; ColumnDrawerPointer(patchcol, block, mipmap, pblockheight, blockmodulo, @@ -447,8 +424,6 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) UINT8 *block; texture_t *texture; texpatch_t *patch; - softwarepatch_t *realpatch; - UINT8 *pdata; INT32 blockwidth, blockheight, blocksize; INT32 i; @@ -500,30 +475,35 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { - boolean dealloc = true; - size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); - pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); - realpatch = (softwarepatch_t *)pdata; + UINT16 wadnum = patch->wad; + lumpnum_t lumpnum = patch->lump; + UINT8 *pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + patch_t *realpatch = NULL; + boolean free_patch = true; #ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) - realpatch = (softwarepatch_t *)Picture_PNGConvert(pdata, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); + size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); + if (Picture_IsLumpPNG(pdata, lumplength)) + realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); else #endif -#ifdef WALLFLATS if (texture->type == TEXTURETYPE_FLAT) - realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); + realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); else -#endif { - (void)lumplength; - dealloc = false; + // If this patch has already been loaded, we just use it from the cache. + realpatch = W_GetCachedPatchNumPwad(wadnum, lumpnum); + free_patch = false; + + // Otherwise, we load it here. + if (realpatch == NULL) + realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH); } HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch); - if (dealloc) - Z_Unlock(realpatch); + if (free_patch) + Patch_Free(realpatch); } //Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :( if (format2bpp(grtex->mipmap.format)==4) @@ -753,7 +733,7 @@ void HWR_LoadMapTextures(size_t pnumtextures) gl_textures = calloc(gl_numtextures, sizeof(*gl_textures)); gl_flats = calloc(gl_numtextures, sizeof(*gl_flats)); - if ((gl_textures == NULL) || (gl_flats == NULL)) + if (gl_textures == NULL || gl_flats == NULL) I_Error("HWR_LoadMapTextures: ran out of memory for OpenGL textures"); gl_maptexturesloaded = true; @@ -818,26 +798,6 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) W_ReadLump(flatlumpnum, Z_Malloc(size, PU_HWRCACHE, &grMipmap->data)); } -static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum) -{ - UINT8 *flat; - UINT8 *converted; - size_t size; - - // setup the texture info - grMipmap->format = GL_TEXFMT_P_8; - grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; - - grMipmap->width = (UINT16)textures[texturenum]->width; - grMipmap->height = (UINT16)textures[texturenum]->height; - size = (grMipmap->width * grMipmap->height); - - flat = Z_Malloc(size, PU_HWRCACHE, &grMipmap->data); - converted = (UINT8 *)Picture_TextureToFlat(texturenum); - M_Memcpy(flat, converted, size); - Z_Free(converted); -} - // Download a Doom 'flat' to the hardware cache and make it ready for use void HWR_GetRawFlat(lumpnum_t flatlumpnum) { @@ -863,96 +823,40 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum) void HWR_GetLevelFlat(levelflat_t *levelflat) { - // Who knows? - if (levelflat == NULL) - return; - - if (levelflat->type == LEVELFLAT_FLAT) - HWR_GetRawFlat(levelflat->u.flat.lumpnum); - else if (levelflat->type == LEVELFLAT_TEXTURE) + if (levelflat->type == LEVELFLAT_NONE) { - GLMapTexture_t *grtex; - INT32 texturenum = levelflat->u.texture.num; -#ifdef PARANOIA - if ((unsigned)texturenum >= gl_numtextures) - I_Error("HWR_GetLevelFlat: texturenum >= numtextures"); -#endif - - // Who knows? - if (texturenum == 0 || texturenum == -1) - return; - - // Every texture in memory, stored as a 8-bit flat. Wow! - grtex = &gl_flats[texturenum]; - - // Generate flat if missing from the cache - if (!grtex->mipmap.data && !grtex->mipmap.downloaded) - HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum); - - // If hardware does not have the texture, then call pfnSetTexture to upload it - if (!grtex->mipmap.downloaded) - HWD.pfnSetTexture(&grtex->mipmap); - HWR_SetCurrentTexture(&grtex->mipmap); - - // The system-memory data can be purged now. - Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED); + HWR_SetCurrentTexture(NULL); + return; } - else if (levelflat->type == LEVELFLAT_PATCH) + + INT32 texturenum = texturetranslation[levelflat->texture_id]; + if (texturenum <= 0) { - patch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE); - levelflat->width = (UINT16)(patch->width); - levelflat->height = (UINT16)(patch->height); - HWR_GetPatch(patch); + HWR_SetCurrentTexture(NULL); + return; } -#ifndef NO_PNG_LUMPS - else if (levelflat->type == LEVELFLAT_PNG) - { - GLMipmap_t *mipmap = levelflat->mipmap; - - // Cache the picture. - if (!levelflat->mippic) - { - INT32 pngwidth = 0, pngheight = 0; - void *pic = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0); - Z_ChangeTag(pic, PU_LEVEL); - Z_SetUser(pic, &levelflat->mippic); + GLMapTexture_t *grtex = &gl_flats[texturenum]; + GLMipmap_t *grMipmap = &grtex->mipmap; - levelflat->width = (UINT16)pngwidth; - levelflat->height = (UINT16)pngheight; - } - - // Make the mipmap. - if (mipmap == NULL) - { - mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_STATIC, NULL); - mipmap->format = GL_TEXFMT_P_8; - mipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; - levelflat->mipmap = mipmap; - } + if (!grMipmap->data && !grMipmap->downloaded) + { + grMipmap->format = GL_TEXFMT_P_8; + grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; - if (!mipmap->data && !mipmap->downloaded) - { - UINT8 *flat; - size_t size; + grMipmap->width = (UINT16)textures[texturenum]->width; + grMipmap->height = (UINT16)textures[texturenum]->height; - if (levelflat->mippic == NULL) - I_Error("HWR_GetLevelFlat: levelflat->mippic == NULL"); + size_t size = grMipmap->width * grMipmap->height; + memcpy(Z_Malloc(size, PU_HWRCACHE, &grMipmap->data), R_GetFlatForTexture(texturenum), size); + } - mipmap->width = levelflat->width; - mipmap->height = levelflat->height; + if (!grMipmap->downloaded) + HWD.pfnSetTexture(&grtex->mipmap); - size = (mipmap->width * mipmap->height); - flat = Z_Malloc(size, PU_LEVEL, &mipmap->data); - M_Memcpy(flat, levelflat->mippic, size); - } + HWR_SetCurrentTexture(&grtex->mipmap); - // Tell the hardware driver to bind the current texture to the flat's mipmap - HWR_SetCurrentTexture(mipmap); - } -#endif - else // set no texture - HWR_SetCurrentTexture(NULL); + Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED); } // --------------------+ @@ -1066,145 +970,13 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch) Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED); } -static const INT32 picmode2GR[] = -{ - GL_TEXFMT_P_8, // PALETTE - 0, // INTENSITY (unsupported yet) - GL_TEXFMT_ALPHA_INTENSITY_88, // INTENSITY_ALPHA (corona use this) - 0, // RGB24 (unsupported yet) - GL_TEXFMT_RGBA, // RGBA32 (opengl only) -}; - -static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheight, - INT32 blockmodulo, pic_t *pic, INT32 bpp) -{ - INT32 i,j; - fixed_t posx, posy, stepx, stepy; - UINT8 *dest, *src, texel; - UINT16 texelu16; - INT32 picbpp; - RGBA_t col; - - stepy = ((INT32)SHORT(pic->height)<<FRACBITS)/pblockheight; - stepx = ((INT32)SHORT(pic->width)<<FRACBITS)/pblockwidth; - picbpp = format2bpp(picmode2GR[pic->mode]); - posy = 0; - for (j = 0; j < pblockheight; j++) - { - posx = 0; - dest = &block[j*blockmodulo]; - src = &pic->data[(posy>>FRACBITS)*SHORT(pic->width)*picbpp]; - for (i = 0; i < pblockwidth;i++) - { - switch (pic->mode) - { // source bpp - case PALETTE : - texel = src[(posx+FRACUNIT/2)>>FRACBITS]; - switch (bpp) - { // destination bpp - case 1 : - *dest++ = texel; break; - case 2 : - texelu16 = (UINT16)(texel | 0xff00); - memcpy(dest, &texelu16, sizeof(UINT16)); - dest += sizeof(UINT16); - break; - case 3 : - col = V_GetColor(texel); - memcpy(dest, &col, sizeof(RGBA_t)-sizeof(UINT8)); - dest += sizeof(RGBA_t)-sizeof(UINT8); - break; - case 4 : - memcpy(dest, &V_GetColor(texel), sizeof(RGBA_t)); - dest += sizeof(RGBA_t); - break; - } - break; - case INTENSITY : - *dest++ = src[(posx+FRACUNIT/2)>>FRACBITS]; - break; - case INTENSITY_ALPHA : // assume dest bpp = 2 - memcpy(dest, src + ((posx+FRACUNIT/2)>>FRACBITS)*sizeof(UINT16), sizeof(UINT16)); - dest += sizeof(UINT16); - break; - case RGB24 : - break; // not supported yet - case RGBA32 : // assume dest bpp = 4 - dest += sizeof(UINT32); - memcpy(dest, src + ((posx+FRACUNIT/2)>>FRACBITS)*sizeof(UINT32), sizeof(UINT32)); - break; - } - posx += stepx; - } - posy += stepy; - } -} - -// -----------------+ -// HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes') -// Returns : -// -----------------+ -patch_t *HWR_GetPic(lumpnum_t lumpnum) -{ - patch_t *patch = HWR_GetCachedGLPatch(lumpnum); - GLPatch_t *grPatch = (GLPatch_t *)(patch->hardware); - - if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data) - { - pic_t *pic; - UINT8 *block; - size_t len; - - pic = W_CacheLumpNum(lumpnum, PU_CACHE); - patch->width = SHORT(pic->width); - patch->height = SHORT(pic->height); - len = W_LumpLength(lumpnum) - sizeof (pic_t); - - grPatch->mipmap->width = (UINT16)patch->width; - grPatch->mipmap->height = (UINT16)patch->height; - - if (pic->mode == PALETTE) - grPatch->mipmap->format = textureformat; // can be set by driver - else - grPatch->mipmap->format = picmode2GR[pic->mode]; - - Z_Free(grPatch->mipmap->data); - - // allocate block - block = MakeBlock(grPatch->mipmap); - - if (patch->width == SHORT(pic->width) && - patch->height == SHORT(pic->height) && - format2bpp(grPatch->mipmap->format) == format2bpp(picmode2GR[pic->mode])) - { - // no conversion needed - M_Memcpy(grPatch->mipmap->data, pic->data,len); - } - else - HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height), - SHORT(pic->width)*format2bpp(grPatch->mipmap->format), - pic, - format2bpp(grPatch->mipmap->format)); - - Z_Unlock(pic); - Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); - - grPatch->mipmap->flags = 0; - grPatch->max_s = grPatch->max_t = 1.0f; - } - HWD.pfnSetTexture(grPatch->mipmap); - //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grPatch->mipmap->data, grPatch->mipmap->downloaded); - - return patch; -} - patch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) { lumpcache_t *lumpcache = wadfiles[wadnum]->patchcache; if (!lumpcache[lumpnum]) { - void *ptr = Z_Calloc(sizeof(patch_t), PU_PATCH, &lumpcache[lumpnum]); - Patch_Create(NULL, 0, ptr); + void *ptr = Patch_Create(0, 0); + Z_SetUser(ptr, &lumpcache[lumpnum]); Patch_AllocateHardwarePatch(ptr); } return (patch_t *)(lumpcache[lumpnum]); diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index bc473c1f8de04b8c2a1fcbfa3a46a8272592a28f..ba1f339d0fe9af16d7eee7ab0f73d7558de0936e 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -127,6 +127,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p float cy = FIXED_TO_FLOAT(y); UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); UINT8 blendmode = ((option & V_BLENDMASK) >> V_BLENDSHIFT); + UINT8 opacity = 0xFF; GLPatch_t *hwrPatch; // 3--2 @@ -145,6 +146,14 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p hwrPatch = ((GLPatch_t *)gpatch->hardware); + if (alphalevel) + { + if (alphalevel == 10) opacity = softwaretranstogl_lo[st_translucency]; // V_HUDTRANSHALF + else if (alphalevel == 11) opacity = softwaretranstogl[st_translucency]; // V_HUDTRANS + else if (alphalevel == 12) opacity = softwaretranstogl_hi[st_translucency]; // V_HUDTRANSDOUBLE + else opacity = softwaretranstogl[10-alphalevel]; + } + dup = (float)vid.dup; switch (option & V_SCALEPATCHMASK) @@ -261,13 +270,13 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // cx and cy are possibly *slightly* off from float maths // This is done before here compared to software because we directly alter cx and cy to centre - if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT) + if (opacity == 0xFF && cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT) { - const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0])); - if (!column->topdelta) + const column_t *column = &gpatch->columns[0]; + if (column->num_posts && !column->posts[0].topdelta) { - const UINT8 *source = (const UINT8 *)(column) + 3; - HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + const UINT8 *source = column->pixels; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, source[0]); } } // centre screen @@ -345,11 +354,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p { FSurfaceInfo Surf; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - - if (alphalevel == 10) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; // V_HUDTRANSHALF - else if (alphalevel == 11) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; // V_HUDTRANS - else if (alphalevel == 12) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; // V_HUDTRANSDOUBLE - else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; + Surf.PolyColor.s.alpha = opacity; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -648,46 +653,10 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, HWD.pfnDrawPolygon(NULL, v, 4, flags); } -void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) -{ - FOutVector v[4]; - const patch_t *patch; - - // make pic ready in hardware cache - patch = HWR_GetPic(lumpnum); - -// 3--2 -// | /| -// |/ | -// 0--1 - - v[0].x = v[3].x = 2.0f * (float)x/vid.width - 1; - v[2].x = v[1].x = 2.0f * (float)(x + patch->width*FIXED_TO_FLOAT(vid.fdup))/vid.width - 1; - v[0].y = v[1].y = 1.0f - 2.0f * (float)y/vid.height; - v[2].y = v[3].y = 1.0f - 2.0f * (float)(y + patch->height*FIXED_TO_FLOAT(vid.fdup))/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].s = v[3].s = 0; - v[2].s = v[1].s = ((GLPatch_t *)patch->hardware)->max_s; - v[0].t = v[1].t = 0; - v[2].t = v[3].t = ((GLPatch_t *)patch->hardware)->max_t; - - - //Hurdler: Boris, the same comment as above... but maybe for pics - // it not a problem since they don't have any transparent pixel - // if I'm right !? - // But then, the question is: why not 0 instead of PF_Masked ? - // or maybe PF_Environment ??? (like what I said above) - // BP: PF_Environment don't change anything ! and 0 is undifined - HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest); -} - // ========================================================================== // V_VIDEO.C STUFF // ========================================================================== - // -------------------------------------------------------------------------- // Fills a box of pixels using a flat texture as a pattern // -------------------------------------------------------------------------- diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 828f247674b4a85aae18de777aa558b0c9f6790d..fee1987683817c6183027f2095632ba8e5bdbec2 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -428,25 +428,9 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool // set texture for polygon if (levelflat != NULL) { - if (levelflat->type == LEVELFLAT_FLAT) - { - size_t len = W_LumpLength(levelflat->u.flat.lumpnum); - unsigned flatflag = R_GetFlatSize(len); - fflatwidth = fflatheight = (float)flatflag; - } - else - { - if (levelflat->type == LEVELFLAT_TEXTURE) - { - fflatwidth = textures[levelflat->u.texture.num]->width; - fflatheight = textures[levelflat->u.texture.num]->height; - } - else if (levelflat->type == LEVELFLAT_PATCH || levelflat->type == LEVELFLAT_PNG) - { - fflatwidth = levelflat->width; - fflatheight = levelflat->height; - } - } + texture_t *texture = textures[R_GetTextureNumForFlat(levelflat)]; + fflatwidth = texture->width; + fflatheight = texture->height; } else // set no texture HWR_SetCurrentTexture(NULL); @@ -2745,25 +2729,9 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, // set texture for polygon if (levelflat != NULL) { - if (levelflat->type == LEVELFLAT_FLAT) - { - size_t len = W_LumpLength(levelflat->u.flat.lumpnum); - unsigned flatflag = R_GetFlatSize(len); - fflatwidth = fflatheight = (float)flatflag; - } - else - { - if (levelflat->type == LEVELFLAT_TEXTURE) - { - fflatwidth = textures[levelflat->u.texture.num]->width; - fflatheight = textures[levelflat->u.texture.num]->height; - } - else if (levelflat->type == LEVELFLAT_PATCH || levelflat->type == LEVELFLAT_PNG) - { - fflatwidth = levelflat->width; - fflatheight = levelflat->height; - } - } + texture_t *texture = textures[R_GetTextureNumForFlat(levelflat)]; + fflatwidth = texture->width; + fflatheight = texture->height; } else // set no texture HWR_SetCurrentTexture(NULL); @@ -2810,8 +2778,6 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, } } - anglef = ANG2RAD(InvAngle(angle)); - for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) { // Go from the polysector's original vertex locations @@ -2825,6 +2791,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, tempxsow = v3d->s; tempytow = v3d->t; + anglef = ANG2RAD(InvAngle(angle)); + v3d->s = (tempxsow * cos(anglef)) - (tempytow * sin(anglef)); v3d->t = (tempxsow * sin(anglef)) + (tempytow * cos(anglef)); } diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 18648a4999a1263b012f4d71120fbb0687f03d53..9797a93312e2df6159f64ef472abe1beb5f2f024 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -379,7 +379,7 @@ static void md2_loadTexture(md2_t *model) Z_Free(grPatch->mipmap->data); } else - model->grpatch = patch = Patch_Create(NULL, 0, NULL); + model->grpatch = patch = Patch_Create(0, 0); if (!patch->hardware) Patch_AllocateHardwarePatch(patch); @@ -444,7 +444,7 @@ static void md2_loadBlendTexture(md2_t *model) Z_Free(grPatch->mipmap->data); } else - model->blendgrpatch = patch = Patch_Create(NULL, 0, NULL); + model->blendgrpatch = patch = Patch_Create(0, 0); if (!patch->hardware) Patch_AllocateHardwarePatch(patch); diff --git a/src/m_menu.c b/src/m_menu.c index 504a5c6cb86731ed25b4e7d0f34d3c7ad9ee3aa8..de23acbfb46b4402261cef08c54bd972d61553ec 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6331,18 +6331,11 @@ static void M_StopMessage(INT32 choice) // You can even put multiple images in one menu! static void M_DrawImageDef(void) { - // Grr. Need to autodetect for pic_ts. - pic_t *pictest = (pic_t *)W_CacheLumpName(currentMenu->menuitems[itemOn].text,PU_CACHE); - if (!pictest->zero) - V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text)); + patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].text, PU_PATCH); + if (patch->width <= BASEVIDWIDTH) + V_DrawScaledPatch(0,0,0,patch); else - { - patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_PATCH); - if (patch->width <= BASEVIDWIDTH) - V_DrawScaledPatch(0,0,0,patch); - else - V_DrawSmallScaledPatch(0,0,0,patch); - } + V_DrawSmallScaledPatch(0,0,0,patch); if (currentMenu->numitems > 1) V_DrawString(0,192,V_TRANSLUCENT, va("PAGE %d of %hd", itemOn+1, currentMenu->numitems)); diff --git a/src/p_setup.c b/src/p_setup.c index 614a820806ca714ba3d86c39b630b9b1ba6ab1bf..1d985beb4f07399a40607f1ec8f32f480df0e65c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -537,20 +537,14 @@ levelflat_t *foundflats; //SoM: Other files want this info. size_t P_PrecacheLevelFlats(void) { - lumpnum_t lump; size_t i; //SoM: 4/18/2000: New flat code to make use of levelflats. flatmemory = 0; for (i = 0; i < numlevelflats; i++) { - if (levelflats[i].type == LEVELFLAT_FLAT) - { - lump = levelflats[i].u.flat.lumpnum; - if (devparm) - flatmemory += W_LumpLength(lump); - R_GetFlat(lump); - } + if (levelflats[i].type != LEVELFLAT_NONE) + R_GetFlat(&levelflats[i]); } return flatmemory; } @@ -562,19 +556,8 @@ or NULL if we want to allocate it now. static INT32 Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize) { -#ifndef NO_PNG_LUMPS - UINT8 buffer[8]; -#endif - - lumpnum_t flatnum; - int texturenum; - UINT8 *flatpatch; - size_t lumplength; - - size_t i; - // Scan through the already found flats, return if it matches. - for (i = 0; i < numlevelflats; i++) + for (size_t i = 0; i < numlevelflats; i++) { if (strnicmp(levelflat[i].name, flatname, 8) == 0) return i; @@ -598,64 +581,35 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize) strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); strupr(levelflat->name); - /* If we can't find a flat, try looking for a texture! */ - if (( flatnum = R_GetFlatNumForName(levelflat->name) ) == LUMPERROR) + levelflat->type = LEVELFLAT_TEXTURE; + + // Look for a flat + int texturenum = R_CheckFlatNumForName(levelflat->name); + if (texturenum <= 0) { - if (( texturenum = R_CheckTextureNumForName(levelflat->name) ) == -1) - { - // check for REDWALL - if (( texturenum = R_CheckTextureNumForName("REDWALL") ) != -1) - goto texturefound; - // check for REDFLR - else if (( flatnum = R_GetFlatNumForName("REDFLR") ) != LUMPERROR) - goto flatfound; - // nevermind - levelflat->type = LEVELFLAT_NONE; - } - else + // If we can't find a flat, try looking for a texture! + texturenum = R_CheckTextureNumForName(levelflat->name); + if (texturenum <= 0) { -texturefound: - levelflat->type = LEVELFLAT_TEXTURE; - levelflat->u.texture. num = texturenum; - levelflat->u.texture.lastnum = texturenum; - /* start out unanimated */ - levelflat->u.texture.basenum = -1; + // Use "not found" texture + texturenum = R_CheckTextureNumForName("REDWALL"); + + // Give up? + if (texturenum <= 0) + { + levelflat->type = LEVELFLAT_NONE; + texturenum = -1; + } } } - else - { -flatfound: - /* This could be a flat, patch, or PNG. */ - flatpatch = W_CacheLumpNum(flatnum, PU_CACHE); - lumplength = W_LumpLength(flatnum); - if (Picture_CheckIfDoomPatch((softwarepatch_t *)flatpatch, lumplength)) - levelflat->type = LEVELFLAT_PATCH; - else - { -#ifndef NO_PNG_LUMPS - /* - Only need eight bytes for PNG headers. - FIXME: Put this elsewhere. - */ - W_ReadLumpHeader(flatnum, buffer, 8, 0); - if (Picture_IsLumpPNG(buffer, lumplength)) - levelflat->type = LEVELFLAT_PNG; - else -#endif/*NO_PNG_LUMPS*/ - levelflat->type = LEVELFLAT_FLAT;/* phew */ - } - if (flatpatch) - Z_Free(flatpatch); - levelflat->u.flat. lumpnum = flatnum; - levelflat->u.flat.baselumpnum = LUMPERROR; - } + levelflat->texture_id = texturenum; #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); #endif - return ( numlevelflats++ ); + return numlevelflats++; } // Auxiliary function. Find a flat in the active wad files, @@ -3238,9 +3192,6 @@ static boolean P_LoadMapData(const virtres_t *virt) levelflats = M_Memcpy(Z_Calloc(numlevelflats * sizeof (*levelflats), PU_LEVEL, NULL), foundflats, numlevelflats * sizeof (levelflat_t)); free(foundflats); - // search for animated flats and set up - P_SetupLevelFlatAnims(); - return true; } diff --git a/src/p_setup.h b/src/p_setup.h index c6f4f741c01c56fecfc5b0fa0fb267fb1c975b16..f9e51024d2dbcf55f61bd193d1e32edc278a31be 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -35,9 +35,6 @@ extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame enum { LEVELFLAT_NONE,/* HOM time my friend */ - LEVELFLAT_FLAT, - LEVELFLAT_PATCH, - LEVELFLAT_PNG, LEVELFLAT_TEXTURE, }; @@ -47,41 +44,8 @@ enum typedef struct { char name[9]; // resource name from wad - - UINT8 type; - union - { - struct - { - lumpnum_t lumpnum; // lump number of the flat - // for flat animation - lumpnum_t baselumpnum; - } - flat; - struct - { - INT32 num; - INT32 lastnum; // texture number of the flat - // for flat animation - INT32 basenum; - } - texture; - } - u; - - UINT16 width, height; - - // for flat animation - INT32 animseq; // start pos. in the anim sequence - INT32 numpics; - INT32 speed; - - // for textures - UINT8 *picture; -#ifdef HWRENDER - void *mipmap; - void *mippic; -#endif + UINT8 type; + INT32 texture_id; } levelflat_t; extern size_t numlevelflats; diff --git a/src/p_spec.c b/src/p_spec.c index 7bec07c92730128796558e508718f0449bfe798f..37036d095cb7f7934ebcb4473f22152312e6356c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -62,17 +62,12 @@ sectorportal_t *secportals; */ typedef struct { - SINT8 istexture; ///< ::true for a texture, ::false for a flat - INT32 picnum; ///< The end flat number - INT32 basepic; ///< The start flat number + INT32 picnum; ///< The end texture number + INT32 basepic; ///< The start texture number INT32 numpics; ///< Number of frames in the animation tic_t speed; ///< Number of tics for which each frame is shown } anim_t; -#if defined(_MSC_VER) -#pragma pack(1) -#endif - /** Animated texture definition. * Used for loading an ANIMDEFS lump from a wad. * @@ -87,13 +82,9 @@ typedef struct SINT8 istexture; ///< True for a texture, false for a flat. char endname[9]; ///< Name of the last frame, null-terminated. char startname[9]; ///< Name of the first frame, null-terminated. - INT32 speed ; ///< Number of tics for which each frame is shown. + INT32 speed; ///< Number of tics for which each frame is shown. } ATTRPACK animdef_t; -#if defined(_MSC_VER) -#pragma pack() -#endif - typedef struct { UINT32 count; @@ -138,17 +129,32 @@ static size_t maxanims; static animdef_t *animdefs = NULL; -// Increase the size of animdefs to make room for a new animation definition -static void GrowAnimDefs(void) -{ - maxanims++; - animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); -} - // A prototype; here instead of p_spec.h, so they're "private" void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum); void P_ParseAnimationDefintion(SINT8 istexture); +static boolean P_FindTextureForAnimation(anim_t *anim, animdef_t *animdef) +{ + if (R_CheckTextureNumForName(animdef->startname) == -1) + return false; + + anim->picnum = R_TextureNumForName(animdef->endname); + anim->basepic = R_TextureNumForName(animdef->startname); + + return true; +} + +static boolean P_FindFlatForAnimation(anim_t *anim, animdef_t *animdef) +{ + if (R_CheckFlatNumForName(animdef->startname) == -1) + return false; + + anim->picnum = R_CheckFlatNumForName(animdef->endname); + anim->basepic = R_CheckFlatNumForName(animdef->startname); + + return true; +} + /** Sets up texture and flat animations. * * Converts an ::animdef_t array loaded from a lump into @@ -156,7 +162,6 @@ void P_ParseAnimationDefintion(SINT8 istexture); * * Issues an error if any animation cycles are invalid. * - * \sa P_FindAnimatedFlat, P_SetupLevelFlatAnims * \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs), JTE (had to rewrite it to handle multiple WADs _correctly_) */ void P_InitPicAnims(void) @@ -199,37 +204,39 @@ void P_InitPicAnims(void) lastanim = anims; for (i = 0; animdefs[i].istexture != -1; i++) { + animdef_t *animdef = &animdefs[i]; + + // If this animation is for a texture, look for one first, THEN look for a flat if (animdefs[i].istexture) { - if (R_CheckTextureNumForName(animdefs[i].startname) == -1) - continue; - - lastanim->picnum = R_TextureNumForName(animdefs[i].endname); - lastanim->basepic = R_TextureNumForName(animdefs[i].startname); + if (!P_FindTextureForAnimation(lastanim, animdef)) + { + if (!P_FindFlatForAnimation(lastanim, animdef)) + continue; + } } + // Else, if this animation is for a flat, look for one first, THEN look for a texture else { - if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR) - continue; - - lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname); - lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname); + if (!P_FindFlatForAnimation(lastanim, animdef)) + { + if (!P_FindTextureForAnimation(lastanim, animdef)) + continue; + } } - lastanim->istexture = animdefs[i].istexture; lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; if (lastanim->numpics < 2) { free(anims); I_Error("P_InitPicAnims: bad cycle from %s to %s", - animdefs[i].startname, animdefs[i].endname); + animdef->startname, animdef->endname); } - lastanim->speed = LONG(animdefs[i].speed); + lastanim->speed = animdef->speed; lastanim++; } - lastanim->istexture = -1; R_ClearTextureNumCache(false); // Clear animdefs now that we're done with it. @@ -354,7 +361,8 @@ void P_ParseAnimationDefintion(SINT8 istexture) if (i == maxanims) { // Increase the size to make room for the new animation definition - GrowAnimDefs(); + maxanims++; + animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); strncpy(animdefs[i].startname, animdefsToken, 9); } @@ -440,83 +448,6 @@ void P_ParseAnimationDefintion(SINT8 istexture) } animdefs[i].speed = animSpeed; Z_Free(animdefsToken); - -#ifdef WALLFLATS - // hehe... uhh..... - if (!istexture) - { - GrowAnimDefs(); - M_Memcpy(&animdefs[maxanims-1], &animdefs[i], sizeof(animdef_t)); - animdefs[maxanims-1].istexture = 1; - } -#endif -} - -/** Checks for flats in levelflats that are part of a flat animation sequence - * and sets them up for animation. - * - * \param animnum Index into ::anims to find flats for. - * \sa P_SetupLevelFlatAnims - */ -static inline void P_FindAnimatedFlat(INT32 animnum) -{ - size_t i; - lumpnum_t startflatnum, endflatnum; - levelflat_t *foundflats; - - foundflats = levelflats; - startflatnum = anims[animnum].basepic; - endflatnum = anims[animnum].picnum; - - // note: high word of lumpnum is the wad number - if ((startflatnum>>16) != (endflatnum>>16)) - I_Error("AnimatedFlat start %s not in same wad as end %s\n", - animdefs[animnum].startname, animdefs[animnum].endname); - - // - // now search through the levelflats if this anim flat sequence is used - // - for (i = 0; i < numlevelflats; i++, foundflats++) - { - // is that levelflat from the flat anim sequence ? - if ((anims[animnum].istexture) && (foundflats->type == LEVELFLAT_TEXTURE) - && ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum)) - { - foundflats->u.texture.basenum = startflatnum; - foundflats->animseq = foundflats->u.texture.num - startflatnum; - foundflats->numpics = endflatnum - startflatnum + 1; - foundflats->speed = anims[animnum].speed; - - CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n", - atoi(sizeu1(i)), foundflats->name, foundflats->animseq, - foundflats->numpics,foundflats->speed); - } - else if ((!anims[animnum].istexture) && (foundflats->type == LEVELFLAT_FLAT) - && (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum)) - { - foundflats->u.flat.baselumpnum = startflatnum; - foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum; - foundflats->numpics = endflatnum - startflatnum + 1; - foundflats->speed = anims[animnum].speed; - - CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n", - atoi(sizeu1(i)), foundflats->name, foundflats->animseq, - foundflats->numpics,foundflats->speed); - } - } -} - -/** Sets up all flats used in a level. - * - * \sa P_InitPicAnims, P_FindAnimatedFlat - */ -void P_SetupLevelFlatAnims(void) -{ - INT32 i; - - // the original game flat anim sequences - for (i = 0; anims[i].istexture != -1; i++) - P_FindAnimatedFlat(i); } // @@ -5405,13 +5336,6 @@ void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable) */ void P_UpdateSpecials(void) { - anim_t *anim; - INT32 i; - INT32 pic; - size_t j; - - levelflat_t *foundflats; // for flat animation - // LEVEL TIMER P_CheckTimeLimit(); @@ -5419,37 +5343,18 @@ void P_UpdateSpecials(void) P_CheckPointLimit(); // ANIMATE TEXTURES - for (anim = anims; anim < lastanim; anim++) - { - for (i = 0; i < anim->numpics; i++) - { - pic = anim->basepic + ((leveltime/anim->speed + i) % anim->numpics); - if (anim->istexture) - texturetranslation[anim->basepic+i] = pic; - } - } - - // ANIMATE FLATS - /// \todo do not check the non-animate flat.. link the animated ones? - /// \note its faster than the original anywaysince it animates only - /// flats used in the level, and there's usually very few of them - foundflats = levelflats; - for (j = 0; j < numlevelflats; j++, foundflats++) + for (anim_t *anim = anims; anim < lastanim; anim++) { - if (foundflats->speed) // it is an animated flat + for (INT32 i = 0; i < anim->numpics; i++) { - // update the levelflat texture number - if ((foundflats->type == LEVELFLAT_TEXTURE) && (foundflats->u.texture.basenum != -1)) - foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); - // update the levelflat lump number - else if ((foundflats->type == LEVELFLAT_FLAT) && (foundflats->u.flat.baselumpnum != LUMPERROR)) - foundflats->u.flat.lumpnum = foundflats->u.flat.baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + INT32 pic = anim->basepic + ((leveltime/anim->speed + i) % anim->numpics); + texturetranslation[anim->basepic+i] = pic; } } } // -// Floor over floors (FOFs), 3Dfloors, 3Dblocks, fake floors (ffloors), rovers, or whatever you want to call them +// 3D floors // /** Gets the ID number for a 3Dfloor in its target sector. diff --git a/src/p_spec.h b/src/p_spec.h index 3bbaba58b69858cfc0d8627bfb2971e8628e6b40..b9c3a2ca3c2055481b54cd2d2fce3217df244fe7 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -502,9 +502,6 @@ typedef enum // at game start void P_InitPicAnims(void); -// at map load (sectors) -void P_SetupLevelFlatAnims(void); - // at map load void P_InitSpecials(void); void P_ApplyFlatAlignment(sector_t* sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs, boolean floor, boolean ceiling); diff --git a/src/r_defs.h b/src/r_defs.h index 6e0375e615aed5596e68eb67b113fe61a907e477..d556b540f8a68794986e04da72c58e6d7af8f9a2 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -775,14 +775,26 @@ typedef struct { UINT8 topdelta; // -1 is the last post in a column UINT8 length; // length data bytes follows -} ATTRPACK post_t; +} ATTRPACK doompost_t; #if defined(_MSC_VER) #pragma pack() #endif -// column_t is a list of 0 or more post_t, (UINT8)-1 terminated -typedef post_t column_t; +typedef struct +{ + unsigned topdelta; + unsigned length; + size_t data_offset; +} post_t; + +// column_t is a list of 0 or more post_t +typedef struct +{ + unsigned num_posts; + post_t *posts; + UINT8 *pixels; +} column_t; // // OTHER TYPES @@ -859,8 +871,9 @@ typedef struct INT16 width, height; INT16 leftoffset, topoffset; - INT32 *columnofs; // Column offsets. This is relative to patch->columns - UINT8 *columns; // Software column data + UINT8 *pixels; + column_t *columns; + post_t *posts; void *hardware; // OpenGL patch, allocated whenever necessary void *flats[4]; // The patch as flats @@ -884,26 +897,6 @@ typedef struct // the [0] is &columnofs[width] } ATTRPACK softwarepatch_t; -#ifdef _MSC_VER -#pragma warning(disable : 4200) -#endif - -// a pic is an unmasked block of pixels, stored in horizontal way -typedef struct -{ - INT16 width; - UINT8 zero; // set to 0 allow autodetection of pic_t - // mode instead of patch or raw - UINT8 mode; // see pic_mode_t above - INT16 height; - INT16 reserved1; // set to 0 - UINT8 data[0]; -} ATTRPACK pic_t; - -#ifdef _MSC_VER -#pragma warning(default : 4200) -#endif - #if defined(_MSC_VER) #pragma pack() #endif diff --git a/src/r_draw.h b/src/r_draw.h index 0af911233bfdb6097c8326bf014be84ee7418cad..7eb001ebd360df404e57a5716d96aa73aa013219 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -192,8 +192,6 @@ void R_DrawTranslucentColumn_8(void); void R_DrawDropShadowColumn_8(void); void R_DrawTranslatedColumn_8(void); void R_DrawTranslatedTranslucentColumn_8(void); -void R_Draw2sMultiPatchColumn_8(void); -void R_Draw2sMultiPatchTranslucentColumn_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); diff --git a/src/r_draw8.c b/src/r_draw8.c index fe7d321dfcf1a1a1c0aa6aabc8ba5169c445acdf..87545f41836761421f2cdf8694c07c88f6815612 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -105,199 +105,6 @@ void R_DrawColumn_8(void) } } -void R_Draw2sMultiPatchColumn_8(void) -{ - INT32 count; - register UINT8 *dest; - register fixed_t frac; - fixed_t fracstep; - - count = dc_yh - dc_yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - return; -#endif - - // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - - //dest = ylookup[dc_yl] + columnofs[dc_x]; - dest = &topleft[dc_yl*vid.width + dc_x]; - - count++; - - // Determine scaling, which is the only mapping to be done. - fracstep = dc_iscale; - //frac = dc_texturemid + (dc_yl - centery)*fracstep; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - { - register const UINT8 *source = dc_source; - register const lighttable_t *colormap = dc_colormap; - register INT32 heightmask = dc_texheight-1; - register UINT8 val; - if (dc_texheight & heightmask) // not a power of 2 -- killough - { - heightmask++; - heightmask <<= FRACBITS; - - if (frac < 0) - while ((frac += heightmask) < 0); - else - while (frac >= heightmask) - frac -= heightmask; - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - val = source[frac>>FRACBITS]; - - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; - - dest += vid.width; - - // Avoid overflow. - if (fracstep > 0x7FFFFFFF - frac) - frac += fracstep - heightmask; - else - frac += fracstep; - - while (frac >= heightmask) - frac -= heightmask; - } while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; - dest += vid.width; - frac += fracstep; - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; - dest += vid.width; - frac += fracstep; - } - if (count & 1) - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; - } - } - } -} - -void R_Draw2sMultiPatchTranslucentColumn_8(void) -{ - INT32 count; - register UINT8 *dest; - register fixed_t frac; - fixed_t fracstep; - - count = dc_yh - dc_yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - return; -#endif - - // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - - //dest = ylookup[dc_yl] + columnofs[dc_x]; - dest = &topleft[dc_yl*vid.width + dc_x]; - - count++; - - // Determine scaling, which is the only mapping to be done. - fracstep = dc_iscale; - //frac = dc_texturemid + (dc_yl - centery)*fracstep; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - { - register const UINT8 *source = dc_source; - register const UINT8 *transmap = dc_transmap; - register const lighttable_t *colormap = dc_colormap; - register INT32 heightmask = dc_texheight-1; - register UINT8 val; - if (dc_texheight & heightmask) // not a power of 2 -- killough - { - heightmask++; - heightmask <<= FRACBITS; - - if (frac < 0) - while ((frac += heightmask) < 0); - else - while (frac >= heightmask) - frac -= heightmask; - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - val = source[frac>>FRACBITS]; - - if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - - dest += vid.width; - - // Avoid overflow. - if (fracstep > 0x7FFFFFFF - frac) - frac += fracstep - heightmask; - else - frac += fracstep; - - while (frac >= heightmask) - frac -= heightmask; - } while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - dest += vid.width; - frac += fracstep; - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - dest += vid.width; - frac += fracstep; - } - if (count & 1) - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - } - } - } -} - /** \brief The R_DrawShadeColumn_8 function Experiment to make software go faster. Taken from the Boom source */ diff --git a/src/r_patch.c b/src/r_patch.c index 7c561e9593a58ab8bf75c2ee20793ccd87245ac0..a6a9dc2ebcc0651c26f6faaede8bf7535f607c74 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -21,44 +21,101 @@ // // Creates a patch. -// Assumes a PU_PATCH zone memory tag and no user, but can always be set later // -patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) +patch_t *Patch_Create(INT16 width, INT16 height) { - patch_t *patch = (dest == NULL) ? Z_Calloc(sizeof(patch_t), PU_PATCH, NULL) : (patch_t *)(dest); + patch_t *patch = Z_Calloc(sizeof(patch_t), PU_PATCH, NULL); + patch->width = width; + patch->height = height; + return patch; +} - if (source) - { - INT32 col, colsize; - size_t size = sizeof(INT32) * SHORT(source->width); - size_t offs = (sizeof(INT16) * 4) + size; +patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source) +{ + patch_t *patch = Patch_Create(0, 0); + if (!source) + return patch; + + patch->width = SHORT(source->width); + patch->height = SHORT(source->height); + patch->leftoffset = SHORT(source->leftoffset); + patch->topoffset = SHORT(source->topoffset); + + size_t total_pixels = 0; + size_t total_posts = 0; + + Patch_CalcDataSizes(source, &total_pixels, &total_posts); + + patch->columns = Z_Calloc(sizeof(column_t) * patch->width, PU_PATCH_DATA, NULL); + patch->posts = Z_Calloc(sizeof(post_t) * total_posts, PU_PATCH_DATA, NULL); + patch->pixels = Z_Calloc(sizeof(UINT8) * total_pixels, PU_PATCH_DATA, NULL); - patch->width = SHORT(source->width); - patch->height = SHORT(source->height); - patch->leftoffset = SHORT(source->leftoffset); - patch->topoffset = SHORT(source->topoffset); - patch->columnofs = Z_Calloc(size, PU_PATCH_DATA, NULL); + Patch_MakeColumns(source, patch->width, patch->width, patch->pixels, patch->columns, patch->posts, false); - for (col = 0; col < source->width; col++) + return patch; +} + +void Patch_CalcDataSizes(softwarepatch_t *source, size_t *total_pixels, size_t *total_posts) +{ + for (INT32 i = 0; i < source->width; i++) + { + doompost_t *src_posts = (doompost_t*)((UINT8 *)source + LONG(source->columnofs[i])); + for (doompost_t *post = src_posts; post->topdelta != 0xff ;) { - // This makes the column offsets relative to the column data itself, - // instead of the entire patch data - patch->columnofs[col] = LONG(source->columnofs[col]) - offs; + (*total_posts)++; + (*total_pixels) += post->length; + post = (doompost_t *)((UINT8 *)post + post->length + 4); } + } +} - if (!srcsize) - I_Error("Patch_Create: no source size!"); +void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width, UINT8 *pixels, column_t *columns, post_t *posts, boolean flip) +{ + column_t *column = flip ? columns + (num_columns - 1) : columns; - colsize = (INT32)(srcsize) - (INT32)offs; - if (colsize <= 0) - I_Error("Patch_Create: no column data!"); + for (size_t i = 0; i < num_columns; i++) + { + size_t prevdelta = 0; + size_t data_offset = 0; - patch->columns = Z_Calloc(colsize, PU_PATCH_DATA, NULL); - M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize); - } + column->pixels = pixels; + column->posts = posts; + column->num_posts = 0; - return patch; + if (i >= (unsigned)width) + continue; + + doompost_t *src_posts = (doompost_t*)((UINT8 *)source + LONG(source->columnofs[i])); + + for (doompost_t *post = src_posts; post->topdelta != 0xff ;) + { + size_t topdelta = post->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + posts->topdelta = topdelta; + posts->length = (size_t)post->length; + posts->data_offset = data_offset; + + memcpy(pixels, (UINT8 *)post + 3, post->length); + + data_offset += posts->length; + pixels += posts->length; + + column->num_posts++; + + posts++; + + post = (doompost_t *)((UINT8 *)post + post->length + 4); + } + + if (flip) + column--; + else + column++; + } } // @@ -96,10 +153,12 @@ static void Patch_FreeData(patch_t *patch) } #endif - if (patch->columnofs) - Z_Free(patch->columnofs); + if (patch->pixels) + Z_Free(patch->pixels); if (patch->columns) Z_Free(patch->columns); + if (patch->posts) + Z_Free(patch->posts); } void Patch_Free(patch_t *patch) diff --git a/src/r_patch.h b/src/r_patch.h index cc41639b3a1913706c21b3041044aab84d70ff06..f1a018c035a322a2a57f926e161fe97b66be5c2f 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -18,7 +18,10 @@ #include "doomdef.h" // Patch functions -patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest); +patch_t *Patch_Create(INT16 width, INT16 height); +patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source); +void Patch_CalcDataSizes(softwarepatch_t *source, size_t *total_pixels, size_t *total_posts); +void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width, UINT8 *pixels, column_t *columns, post_t *posts, boolean flip); void Patch_Free(patch_t *patch); #define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum) diff --git a/src/r_picformats.c b/src/r_picformats.c index 0de15b427d3c3968b5d07bff8879469a6cfb984f..7d7f1198d1805b24b715f78a339b07c952dd4e04 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -51,8 +51,6 @@ #endif #endif -static unsigned char imgbuf[1<<26]; - #ifdef PICTURE_PNG_USELOOKUP static colorlookup_t png_colorlookup; #endif @@ -86,22 +84,148 @@ void *Picture_Convert( else if (informat == outformat) I_Error("Picture_Convert: input and output formats were the same!"); + (void)insize; + if (Picture_IsPatchFormat(outformat)) - return Picture_PatchConvert(informat, picture, outformat, insize, outsize, inwidth, inheight, inleftoffset, intopoffset, flags); + return Picture_PatchConvert(informat, picture, outformat, outsize, inwidth, inheight, inleftoffset, intopoffset, flags); else if (Picture_IsFlatFormat(outformat)) - return Picture_FlatConvert(informat, picture, outformat, insize, outsize, inwidth, inheight, inleftoffset, intopoffset, flags); + return Picture_FlatConvert(informat, picture, outformat, outsize, inwidth, intopoffset, flags); else I_Error("Picture_Convert: unsupported input format!"); return NULL; } +static void *ReadPixelFunc_Patch(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags) +{ + (void)inwidth; + (void)inheight; + return Picture_GetPatchPixel((patch_t*)picture, informat, x, y, flags); +} + +static void *ReadPixelFunc_Flat_8bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags) +{ + (void)informat; + (void)flags; + (void)inheight; + return (UINT8 *)picture + ((y * inwidth) + x); +} + +static void *ReadPixelFunc_Flat_16bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags) +{ + (void)informat; + (void)flags; + (void)inheight; + return (UINT16 *)picture + ((y * inwidth) + x); +} + +static void *ReadPixelFunc_Flat_32bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags) +{ + (void)informat; + (void)flags; + (void)inheight; + return (UINT32 *)picture + ((y * inwidth) + x); +} + +static UINT8 GetAlphaFunc_32bpp(void *input, pictureflags_t flags) +{ + (void)flags; + RGBA_t px = *(RGBA_t *)input; + return px.s.alpha; +} + +static UINT8 GetAlphaFunc_16bpp(void *input, pictureflags_t flags) +{ + (void)flags; + UINT16 px = *(UINT16 *)input; + return (px & 0xFF00) >> 8; +} + +static UINT8 GetAlphaFunc_8bpp(void *input, pictureflags_t flags) +{ + UINT8 px = *(UINT8 *)input; + if (px == TRANSPARENTPIXEL && (flags & PICFLAGS_USE_TRANSPARENTPIXEL)) + return 0; + else + return 255; +} + +// input 32bpp output 32bpp +static void *WritePatchPixel_i32o32(void *ptr, void *input) +{ + RGBA_t px = *(RGBA_t *)input; + WRITEUINT32(ptr, px.rgba); + return ptr; +} + +// input 16bpp output 32bpp +static void *WritePatchPixel_i16o32(void *ptr, void *input) +{ + RGBA_t px = pMasterPalette[*((UINT16 *)input) & 0xFF]; + WRITEUINT32(ptr, px.rgba); + return ptr; +} + +// input 8bpp output 32bpp +static void *WritePatchPixel_i8o32(void *ptr, void *input) +{ + RGBA_t px = pMasterPalette[*((UINT8 *)input) & 0xFF]; + WRITEUINT32(ptr, px.rgba); + return ptr; +} + +// input 32bpp output 16bpp +static void *WritePatchPixel_i32o16(void *ptr, void *input) +{ + RGBA_t in = *(RGBA_t *)input; + UINT8 px = NearestColor(in.s.red, in.s.green, in.s.blue); + WRITEUINT16(ptr, (0xFF00 | px)); + return ptr; +} + +// input 16bpp output 16bpp +static void *WritePatchPixel_i16o16(void *ptr, void *input) +{ + WRITEUINT16(ptr, *(UINT16 *)input); + return ptr; +} + +// input 8bpp output 16bpp +static void *WritePatchPixel_i8o16(void *ptr, void *input) +{ + WRITEUINT16(ptr, (0xFF00 | (*(UINT8 *)input))); + return ptr; +} + +// input 32bpp output 8bpp +static void *WritePatchPixel_i32o8(void *ptr, void *input) +{ + RGBA_t in = *(RGBA_t *)input; + UINT8 px = NearestColor(in.s.red, in.s.green, in.s.blue); + WRITEUINT8(ptr, px); + return ptr; +} + +// input 16bpp output 8bpp +static void *WritePatchPixel_i16o8(void *ptr, void *input) +{ + UINT16 px = *(UINT16 *)input; + WRITEUINT8(ptr, (px & 0xFF)); + return ptr; +} + +// input 8bpp output 8bpp +static void *WritePatchPixel_i8o8(void *ptr, void *input) +{ + WRITEUINT8(ptr, *(UINT8 *)input); + return ptr; +} + /** Converts a picture to a patch. * * \param informat Input picture format. * \param picture Input picture data. * \param outformat Output picture format. - * \param insize Input picture size. * \param outsize Output picture size, as a pointer. * \param inwidth Input picture width. * \param inheight Input picture height. @@ -112,34 +236,37 @@ void *Picture_Convert( */ void *Picture_PatchConvert( pictureformat_t informat, void *picture, pictureformat_t outformat, - size_t insize, size_t *outsize, - INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset, + size_t *outsize, + INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset, pictureflags_t flags) { - INT16 x, y; - UINT8 *img; - UINT8 *imgptr = imgbuf; - UINT8 *colpointers, *startofspan; - size_t size = 0; - patch_t *inpatch = NULL; - INT32 inbpp = Picture_FormatBPP(informat); + // Shortcut: If converting a Doom patch into a regular patch, use Patch_Create + if (informat == PICFMT_DOOMPATCH && outformat == PICFMT_PATCH && flags == 0) + { + if (outsize != NULL) + *outsize = sizeof(patch_t); + return Patch_CreateFromDoomPatch(picture); + } - (void)insize; // ignore + INT32 outbpp = Picture_FormatBPP(outformat); + INT32 inbpp = Picture_FormatBPP(informat); + patch_t *inpatch = NULL; if (informat == PICFMT_NONE) I_Error("Picture_PatchConvert: input format was PICFMT_NONE!"); else if (outformat == PICFMT_NONE) I_Error("Picture_PatchConvert: output format was PICFMT_NONE!"); + else if (Picture_IsDoomPatchFormat(outformat)) + I_Error("Picture_PatchConvert: cannot convert to Doom patch!"); else if (informat == outformat) I_Error("Picture_PatchConvert: input and output formats were the same!"); if (inbpp == PICDEPTH_NONE) - I_Error("Picture_PatchConvert: unknown input bits per pixel?!"); - if (Picture_FormatBPP(outformat) == PICDEPTH_NONE) - I_Error("Picture_PatchConvert: unknown output bits per pixel?!"); + I_Error("Picture_PatchConvert: unknown input bits per pixel!"); + if (outbpp == PICDEPTH_NONE) + I_Error("Picture_PatchConvert: unknown output bits per pixel!"); - // If it's a patch, you can just figure out - // the dimensions from the header. + // If it's a patch, we can just figure out the dimensions from the header. if (Picture_IsPatchFormat(informat)) { inpatch = (patch_t *)picture; @@ -160,218 +287,170 @@ void *Picture_PatchConvert( } } - // Write image size and offset - WRITEINT16(imgptr, inwidth); - WRITEINT16(imgptr, inheight); - WRITEINT16(imgptr, inleftoffset); - WRITEINT16(imgptr, intopoffset); + void *(*readPixelFunc)(void *, pictureformat_t, INT32, INT32, INT32, INT32, pictureflags_t) = NULL; + UINT8 (*getAlphaFunc)(void *, pictureflags_t) = NULL; + void *(*writePatchPixel)(void *, void *) = NULL; + + if (Picture_IsPatchFormat(informat)) + readPixelFunc = ReadPixelFunc_Patch; + else if (Picture_IsFlatFormat(informat)) + { + switch (informat) + { + case PICFMT_FLAT32: + readPixelFunc = ReadPixelFunc_Flat_32bpp; + break; + case PICFMT_FLAT16: + readPixelFunc = ReadPixelFunc_Flat_16bpp; + break; + case PICFMT_FLAT: + readPixelFunc = ReadPixelFunc_Flat_8bpp; + break; + default: + I_Error("Picture_PatchConvert: unsupported flat input format!"); + break; + } + } + else + I_Error("Picture_PatchConvert: unsupported input format!"); + + if (inbpp == PICDEPTH_32BPP) + getAlphaFunc = GetAlphaFunc_32bpp; + else if (inbpp == PICDEPTH_16BPP) + getAlphaFunc = GetAlphaFunc_16bpp; + else if (inbpp == PICDEPTH_8BPP) + getAlphaFunc = GetAlphaFunc_8bpp; + + switch (outformat) + { + case PICFMT_PATCH32: + case PICFMT_DOOMPATCH32: + { + if (inbpp == PICDEPTH_32BPP) + writePatchPixel = WritePatchPixel_i32o32; + else if (inbpp == PICDEPTH_16BPP) + writePatchPixel = WritePatchPixel_i16o32; + else // PICFMT_PATCH + writePatchPixel = WritePatchPixel_i8o32; + break; + } + case PICFMT_PATCH16: + case PICFMT_DOOMPATCH16: + if (inbpp == PICDEPTH_32BPP) + writePatchPixel = WritePatchPixel_i32o16; + else if (inbpp == PICDEPTH_16BPP) + writePatchPixel = WritePatchPixel_i16o16; + else // PICFMT_PATCH + writePatchPixel = WritePatchPixel_i8o16; + break; + default: // PICFMT_PATCH + { + if (inbpp == PICDEPTH_32BPP) + writePatchPixel = WritePatchPixel_i32o8; + else if (inbpp == PICDEPTH_16BPP) + writePatchPixel = WritePatchPixel_i16o8; + else // PICFMT_PATCH + writePatchPixel = WritePatchPixel_i8o8; + break; + } + } + + patch_t *out = Z_Calloc(sizeof(patch_t), PU_PATCH, NULL); + + out->width = inwidth; + out->height = inheight; + out->leftoffset = inleftoffset; + out->topoffset = intopoffset; + + size_t max_pixels = out->width * out->height; + unsigned num_posts = 0; + + out->columns = Z_Calloc(sizeof(column_t) * out->width, PU_PATCH_DATA, NULL); + out->pixels = Z_Calloc(max_pixels * (outbpp / 8), PU_PATCH_DATA, NULL); + out->posts = NULL; - // Leave placeholder to column pointers - colpointers = imgptr; - imgptr += inwidth*4; + UINT8 *imgptr = out->pixels; + + unsigned *column_posts = Z_Calloc(sizeof(unsigned) * inwidth, PU_STATIC, NULL); // Write columns - for (x = 0; x < inwidth; x++) + for (INT32 x = 0; x < inwidth; x++) { - int lastStartY = 0; - int spanSize = 0; - startofspan = NULL; + post_t *post; + size_t post_data_offset = 0; + boolean was_opaque = false; + + column_t *column = &out->columns[x]; + column->pixels = imgptr; + column->posts = NULL; + column->num_posts = 0; - // Write column pointer - WRITEINT32(colpointers, imgptr - imgbuf); + column_posts[x] = (unsigned)-1; // Write pixels - for (y = 0; y < inheight; y++) + for (INT32 y = 0; y < inheight; y++) { - void *input = NULL; boolean opaque = false; // Read pixel - if (Picture_IsPatchFormat(informat)) - input = Picture_GetPatchPixel(inpatch, informat, x, y, flags); - else if (Picture_IsFlatFormat(informat)) - { - size_t offs = ((y * inwidth) + x); - switch (informat) - { - case PICFMT_FLAT32: - input = (UINT32 *)picture + offs; - break; - case PICFMT_FLAT16: - input = (UINT16 *)picture + offs; - break; - case PICFMT_FLAT: - input = (UINT8 *)picture + offs; - break; - default: - I_Error("Picture_PatchConvert: unsupported flat input format!"); - break; - } - } - else - I_Error("Picture_PatchConvert: unsupported input format!"); + void *input = readPixelFunc(picture, informat, x, y, inwidth, inheight, flags); // Determine opacity if (input != NULL) - { - UINT8 alpha = 0xFF; - if (inbpp == PICDEPTH_32BPP) - { - RGBA_t px = *(RGBA_t *)input; - alpha = px.s.alpha; - } - else if (inbpp == PICDEPTH_16BPP) - { - UINT16 px = *(UINT16 *)input; - alpha = (px & 0xFF00) >> 8; - } - else if (inbpp == PICDEPTH_8BPP) - { - UINT8 px = *(UINT8 *)input; - if (px == TRANSPARENTPIXEL) - alpha = 0; - } - opaque = (alpha > 1); - } + opaque = getAlphaFunc(input, flags) > 0; // End span if we have a transparent pixel if (!opaque) { - if (startofspan) - WRITEUINT8(imgptr, 0); - startofspan = NULL; + was_opaque = false; continue; } - // Start new column if we need to - if (!startofspan || spanSize == 255) + if (!was_opaque) { - int writeY = y; - - // If we reached the span size limit, finish the previous span - if (startofspan) - WRITEUINT8(imgptr, 0); - - if (y > 254) - { - // Make sure we're aligned to 254 - if (lastStartY < 254) - { - WRITEUINT8(imgptr, 254); - WRITEUINT8(imgptr, 0); - imgptr += 2; - lastStartY = 254; - } - - // Write stopgap empty spans if needed - writeY = y - lastStartY; - - while (writeY > 254) - { - WRITEUINT8(imgptr, 254); - WRITEUINT8(imgptr, 0); - imgptr += 2; - writeY -= 254; - } - } - - startofspan = imgptr; - WRITEUINT8(imgptr, writeY); - imgptr += 2; - spanSize = 0; - - lastStartY = y; + num_posts++; + + out->posts = Z_Realloc(out->posts, sizeof(post_t) * num_posts, PU_PATCH_DATA, NULL); + post = &out->posts[num_posts - 1]; + post->topdelta = (size_t)y; + post->length = 0; + post->data_offset = post_data_offset; + if (column_posts[x] == (unsigned)-1) + column_posts[x] = num_posts - 1; + column->num_posts++; } + was_opaque = true; + // Write the pixel - switch (outformat) - { - case PICFMT_PATCH32: - case PICFMT_DOOMPATCH32: - { - if (inbpp == PICDEPTH_32BPP) - { - RGBA_t out = *(RGBA_t *)input; - WRITEUINT32(imgptr, out.rgba); - } - else if (inbpp == PICDEPTH_16BPP) - { - RGBA_t out = pMasterPalette[*((UINT16 *)input) & 0xFF]; - WRITEUINT32(imgptr, out.rgba); - } - else // PICFMT_PATCH - { - RGBA_t out = pMasterPalette[*((UINT8 *)input) & 0xFF]; - WRITEUINT32(imgptr, out.rgba); - } - break; - } - case PICFMT_PATCH16: - case PICFMT_DOOMPATCH16: - if (inbpp == PICDEPTH_32BPP) - { - RGBA_t in = *(RGBA_t *)input; - UINT8 out = NearestColor(in.s.red, in.s.green, in.s.blue); - WRITEUINT16(imgptr, (0xFF00 | out)); - } - else if (inbpp == PICDEPTH_16BPP) - WRITEUINT16(imgptr, *(UINT16 *)input); - else // PICFMT_PATCH - WRITEUINT16(imgptr, (0xFF00 | (*(UINT8 *)input))); - break; - default: // PICFMT_PATCH - { - if (inbpp == PICDEPTH_32BPP) - { - RGBA_t in = *(RGBA_t *)input; - UINT8 out = NearestColor(in.s.red, in.s.green, in.s.blue); - WRITEUINT8(imgptr, out); - } - else if (inbpp == PICDEPTH_16BPP) - { - UINT16 out = *(UINT16 *)input; - WRITEUINT8(imgptr, (out & 0xFF)); - } - else // PICFMT_PATCH - WRITEUINT8(imgptr, *(UINT8 *)input); - break; - } - } + UINT8 *last_ptr = imgptr; + imgptr = writePatchPixel(last_ptr, input); - spanSize++; - startofspan[1] = spanSize; + post->length++; + post_data_offset += imgptr - last_ptr; } - - if (startofspan) - WRITEUINT8(imgptr, 0); - - WRITEUINT8(imgptr, 0xFF); } - size = imgptr-imgbuf; - img = Z_Malloc(size, PU_STATIC, NULL); - memcpy(img, imgbuf, size); + UINT8 *old_pixels = out->pixels; + size_t total_pixels = imgptr - out->pixels; + if (total_pixels != max_pixels) + out->pixels = Z_Realloc(out->pixels, total_pixels, PU_PATCH_DATA, NULL); - if (Picture_IsInternalPatchFormat(outformat)) + for (INT16 x = 0; x < inwidth; x++) { - patch_t *converted = Patch_Create((softwarepatch_t *)img, size, NULL); + column_t *column = &out->columns[x]; + if (column->num_posts > 0) + column->posts = &out->posts[column_posts[x]]; + if (old_pixels != out->pixels) + column->pixels = out->pixels + (column->pixels - old_pixels); + } -#ifdef HWRENDER - Patch_CreateGL(converted); -#endif + Z_Free(column_posts); - Z_Free(img); + if (outsize != NULL) + *outsize = sizeof(patch_t); - if (outsize != NULL) - *outsize = sizeof(patch_t); - return converted; - } - else - { - if (outsize != NULL) - *outsize = size; - return img; - } + return (void *)out; } /** Converts a picture to a flat. @@ -379,19 +458,16 @@ void *Picture_PatchConvert( * \param informat Input picture format. * \param picture Input picture data. * \param outformat Output picture format. - * \param insize Input picture size. * \param outsize Output picture size, as a pointer. * \param inwidth Input picture width. * \param inheight Input picture height. - * \param inleftoffset Input picture left offset, for patches. - * \param intopoffset Input picture top offset, for patches. * \param flags Input picture flags. * \return A pointer to the converted picture. */ void *Picture_FlatConvert( pictureformat_t informat, void *picture, pictureformat_t outformat, - size_t insize, size_t *outsize, - INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset, + size_t *outsize, + INT32 inwidth, INT32 inheight, pictureflags_t flags) { void *outflat; @@ -401,10 +477,6 @@ void *Picture_FlatConvert( INT32 x, y; size_t size; - (void)insize; // ignore - (void)inleftoffset; // ignore - (void)intopoffset; // ignore - if (informat == PICFMT_NONE) I_Error("Picture_FlatConvert: input format was PICFMT_NONE!"); else if (outformat == PICFMT_NONE) @@ -448,13 +520,22 @@ void *Picture_FlatConvert( for (x = 0; x < inwidth; x++) { void *input = NULL; - size_t offs = ((y * inwidth) + x); + int sx = x; + int sy = y; + + if (flags & PICFLAGS_XFLIP) + sx = inwidth - x - 1; + if (flags & PICFLAGS_YFLIP) + sy = inheight - y - 1; + + size_t in_offs = ((sy * inwidth) + sx); + size_t out_offs = ((y * inwidth) + x); // Read pixel if (Picture_IsPatchFormat(informat)) - input = Picture_GetPatchPixel(inpatch, informat, x, y, flags); + input = Picture_GetPatchPixel(inpatch, informat, sx, sy, 0); else if (Picture_IsFlatFormat(informat)) - input = (UINT8 *)picture + (offs * (inbpp / 8)); + input = (UINT8 *)picture + (in_offs * (inbpp / 8)); else I_Error("Picture_FlatConvert: unsupported input format!"); @@ -469,17 +550,17 @@ void *Picture_FlatConvert( if (inbpp == PICDEPTH_32BPP) { RGBA_t out = *(RGBA_t *)input; - f32[offs] = out.rgba; + f32[out_offs] = out.rgba; } else if (inbpp == PICDEPTH_16BPP) { RGBA_t out = pMasterPalette[*((UINT16 *)input) & 0xFF]; - f32[offs] = out.rgba; + f32[out_offs] = out.rgba; } else // PICFMT_PATCH { RGBA_t out = pMasterPalette[*((UINT8 *)input) & 0xFF]; - f32[offs] = out.rgba; + f32[out_offs] = out.rgba; } break; } @@ -490,12 +571,12 @@ void *Picture_FlatConvert( { RGBA_t in = *(RGBA_t *)input; UINT8 out = NearestColor(in.s.red, in.s.green, in.s.blue); - f16[offs] = (0xFF00 | out); + f16[out_offs] = (0xFF00 | out); } else if (inbpp == PICDEPTH_16BPP) - f16[offs] = *(UINT16 *)input; + f16[out_offs] = *(UINT16 *)input; else // PICFMT_PATCH - f16[offs] = (0xFF00 | *((UINT8 *)input)); + f16[out_offs] = (0xFF00 | *((UINT8 *)input)); break; } case PICFMT_FLAT: @@ -505,15 +586,15 @@ void *Picture_FlatConvert( { RGBA_t in = *(RGBA_t *)input; UINT8 out = NearestColor(in.s.red, in.s.green, in.s.blue); - f8[offs] = out; + f8[out_offs] = out; } else if (inbpp == PICDEPTH_16BPP) { UINT16 out = *(UINT16 *)input; - f8[offs] = (out & 0xFF); + f8[out_offs] = (out & 0xFF); } else // PICFMT_PATCH - f8[offs] = *(UINT8 *)input; + f8[out_offs] = *(UINT8 *)input; break; } default: @@ -538,44 +619,43 @@ void *Picture_GetPatchPixel( INT32 x, INT32 y, pictureflags_t flags) { - fixed_t ofs; - column_t *column; INT32 inbpp = Picture_FormatBPP(informat); softwarepatch_t *doompatch = (softwarepatch_t *)patch; boolean isdoompatch = Picture_IsDoomPatchFormat(informat); - INT16 width; if (patch == NULL) I_Error("Picture_GetPatchPixel: patch == NULL"); - width = (isdoompatch ? SHORT(doompatch->width) : patch->width); + INT16 width = (isdoompatch ? SHORT(doompatch->width) : patch->width); + INT16 height = (isdoompatch ? SHORT(doompatch->height) : patch->height); + + if (x < 0 || x >= width || y < 0 || y >= height) + return NULL; - if (x >= 0 && x < width) + INT32 sx = (flags & PICFLAGS_XFLIP) ? (width-1)-x : x; + INT32 sy = (flags & PICFLAGS_YFLIP) ? (height-1)-y : y; + UINT8 *s8 = NULL; + UINT16 *s16 = NULL; + UINT32 *s32 = NULL; + + if (isdoompatch) { - INT32 colx = (flags & PICFLAGS_XFLIP) ? (width-1)-x : x; - INT32 topdelta, prevdelta = -1; - INT32 colofs = (isdoompatch ? LONG(doompatch->columnofs[colx]) : patch->columnofs[colx]); + INT32 prevdelta = -1; + INT32 colofs = LONG(doompatch->columnofs[sx]); // Column offsets are pointers, so no casting is required. - if (isdoompatch) - column = (column_t *)((UINT8 *)doompatch + colofs); - else - column = (column_t *)((UINT8 *)patch->columns + colofs); + doompost_t *column = (doompost_t *)((UINT8 *)doompatch + colofs); while (column->topdelta != 0xff) { - UINT8 *s8 = NULL; - UINT16 *s16 = NULL; - UINT32 *s32 = NULL; - - topdelta = column->topdelta; + INT32 topdelta = column->topdelta; if (topdelta <= prevdelta) topdelta += prevdelta; prevdelta = topdelta; - ofs = (y - topdelta); + size_t ofs = sy - topdelta; - if (y >= topdelta && ofs < column->length) + if (sy >= topdelta && ofs < column->length) { s8 = (UINT8 *)(column) + 3; switch (inbpp) @@ -592,12 +672,38 @@ void *Picture_GetPatchPixel( } if (inbpp == PICDEPTH_32BPP) - column = (column_t *)((UINT32 *)column + column->length); + column = (doompost_t *)((UINT32 *)column + column->length); else if (inbpp == PICDEPTH_16BPP) - column = (column_t *)((UINT16 *)column + column->length); + column = (doompost_t *)((UINT16 *)column + column->length); else - column = (column_t *)((UINT8 *)column + column->length); - column = (column_t *)((UINT8 *)column + 4); + column = (doompost_t *)((UINT8 *)column + column->length); + column = (doompost_t *)((UINT8 *)column + 4); + } + } + else + { + column_t *column = &patch->columns[sx]; + for (unsigned i = 0; i < column->num_posts; i++) + { + post_t *post = &column->posts[i]; + + size_t ofs = sy - post->topdelta; + + if (sy >= (INT32)post->topdelta && ofs < post->length) + { + s8 = column->pixels + post->data_offset; + switch (inbpp) + { + case PICDEPTH_32BPP: + s32 = (UINT32 *)s8; + return &s32[ofs]; + case PICDEPTH_16BPP: + s16 = (UINT16 *)s8; + return &s16[ofs]; + default: // PICDEPTH_8BPP + return &s8[ofs]; + } + } } } @@ -738,75 +844,50 @@ boolean Picture_CheckIfDoomPatch(softwarepatch_t *patch, size_t size) /** Converts a texture to a flat. * - * \param trickytex The texture number. + * \param texnum The texture number. * \return The converted flat. */ -void *Picture_TextureToFlat(size_t trickytex) +void *Picture_TextureToFlat(size_t texnum) { texture_t *texture; - size_t tex; UINT8 *converted; size_t flatsize; - fixed_t col, ofs; - column_t *column; UINT8 *desttop, *dest, *deststop; UINT8 *source; - if (trickytex >= (unsigned)numtextures) + if (texnum >= (unsigned)numtextures) I_Error("Picture_TextureToFlat: invalid texture number!"); // Check the texture cache // If the texture's not there, it'll be generated right now - tex = trickytex; - texture = textures[tex]; - R_CheckTextureCache(tex); + texture = textures[texnum]; + R_CheckTextureCache(texnum); // Allocate the flat - flatsize = (texture->width * texture->height); + flatsize = texture->width * texture->height; converted = Z_Malloc(flatsize, PU_STATIC, NULL); memset(converted, TRANSPARENTPIXEL, flatsize); // Now we're gonna write to it desttop = converted; deststop = desttop + flatsize; - for (col = 0; col < texture->width; col++, desttop++) + + for (size_t col = 0; col < (size_t)texture->width; col++, desttop++) { - // no post_t info - if (!texture->holes) + column_t *column = (column_t *)R_GetColumn(texnum, col); + for (unsigned i = 0; i < column->num_posts; i++) { - column = (column_t *)(R_GetColumn(tex, col)); - source = (UINT8 *)(column); - dest = desttop; - for (ofs = 0; dest < deststop && ofs < texture->height; ofs++) + post_t *post = &column->posts[i]; + dest = desttop + (post->topdelta * texture->width); + source = column->pixels + post->data_offset; + for (size_t ofs = 0; dest < deststop && ofs < post->length; ofs++) { if (source[ofs] != TRANSPARENTPIXEL) *dest = source[ofs]; dest += texture->width; } } - else - { - INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)R_GetColumn(tex, col) - 3); - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - - dest = desttop + (topdelta * texture->width); - source = (UINT8 *)column + 3; - for (ofs = 0; dest < deststop && ofs < column->length; ofs++) - { - if (source[ofs] != TRANSPARENTPIXEL) - *dest = source[ofs]; - dest += texture->width; - } - column = (column_t *)((UINT8 *)column + column->length + 4); - } - } } return converted; @@ -820,7 +901,7 @@ void *Picture_TextureToFlat(size_t trickytex) */ boolean Picture_IsLumpPNG(const UINT8 *d, size_t s) { - if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ + if (s < 67) // https://web.archive.org/web/20230524232139/http://garethrees.org/2007/11/14/pngcrush/ return false; // Check for PNG file signature using memcmp // As it may be faster on CPUs with slow unaligned memory access @@ -877,7 +958,6 @@ static int PNG_ChunkReader(png_structp png_ptr, png_unknown_chunkp chonk) static void PNG_error(png_structp PNG, png_const_charp pngtext) { CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext); - //I_Error("libpng error at %p: %s", PNG, pngtext); } static void PNG_warn(png_structp PNG, png_const_charp pngtext) @@ -944,7 +1024,7 @@ static png_bytep *PNG_Read( png_set_read_fn(png_ptr, &png_io, PNG_IOReader); memset(&chunk, 0x00, sizeof(png_chunk_t)); - chunkname = grAb_chunk; // I want to read a grAb chunk + chunkname = grAb_chunk; user_chunk_ptr = png_get_user_chunk_ptr(png_ptr); png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, PNG_ChunkReader); @@ -1293,7 +1373,7 @@ void *Picture_PNGConvert( } // Now, convert it! - converted = Picture_PatchConvert(informat, flat, outformat, insize, outsize, (INT16)width, (INT16)height, *leftoffset, *topoffset, flags); + converted = Picture_PatchConvert(informat, flat, outformat, outsize, (INT32)width, (INT32)height, *leftoffset, *topoffset, flags); Z_Free(flat); return converted; } @@ -1329,13 +1409,17 @@ boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *to png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn); if (!png_ptr) - I_Error("Picture_PNGDimensions: Couldn't initialize libpng!"); + { + CONS_Alert(CONS_ERROR, "Picture_PNGDimensions: Couldn't initialize libpng!\n"); + return false; + } png_info_ptr = png_create_info_struct(png_ptr); if (!png_info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); - I_Error("Picture_PNGDimensions: libpng couldn't allocate memory!"); + CONS_Alert(CONS_ERROR, "Picture_PNGDimensions: libpng couldn't allocate memory!\n"); + return false; } #ifdef USE_FAR_KEYWORD @@ -1345,7 +1429,8 @@ boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *to #endif { png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); - I_Error("Picture_PNGDimensions: libpng load error!"); + CONS_Alert(CONS_ERROR, "Picture_PNGDimensions: libpng load error!\n"); + return false; } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); @@ -1357,7 +1442,7 @@ boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *to png_set_read_fn(png_ptr, &png_io, PNG_IOReader); memset(&chunk, 0x00, sizeof(png_chunk_t)); - chunkname = grAb_chunk; // I want to read a grAb chunk + chunkname = grAb_chunk; user_chunk_ptr = png_get_user_chunk_ptr(png_ptr); png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, PNG_ChunkReader); diff --git a/src/r_picformats.h b/src/r_picformats.h index 4050a1b71dc01e8a60cbb14cbe017716c61038c3..3ee9805d867f30cf8eec923285b24d0172038f18 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -42,8 +42,9 @@ typedef enum typedef enum { - PICFLAGS_XFLIP = 1, - PICFLAGS_YFLIP = 1<<1 + PICFLAGS_XFLIP = 1, + PICFLAGS_YFLIP = 1<<1, + PICFLAGS_USE_TRANSPARENTPIXEL = 1<<2 } pictureflags_t; enum @@ -62,20 +63,20 @@ void *Picture_Convert( void *Picture_PatchConvert( pictureformat_t informat, void *picture, pictureformat_t outformat, - size_t insize, size_t *outsize, - INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset, + size_t *outsize, + INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset, pictureflags_t flags); void *Picture_FlatConvert( pictureformat_t informat, void *picture, pictureformat_t outformat, - size_t insize, size_t *outsize, - INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset, + size_t *outsize, + INT32 inwidth, INT32 inheight, pictureflags_t flags); void *Picture_GetPatchPixel( patch_t *patch, pictureformat_t informat, INT32 x, INT32 y, pictureflags_t flags); -void *Picture_TextureToFlat(size_t trickytex); +void *Picture_TextureToFlat(size_t texnum); INT32 Picture_FormatBPP(pictureformat_t format); boolean Picture_IsPatchFormat(pictureformat_t format); @@ -103,10 +104,10 @@ typedef struct boolean available; } spriteinfo_t; -// Portable Network Graphics -#define PNG_HEADER_SIZE (8) +// PNG support +#define PNG_HEADER_SIZE 8 + boolean Picture_IsLumpPNG(const UINT8 *d, size_t s); -#define Picture_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic #ifndef NO_PNG_LUMPS void *Picture_PNGConvert( diff --git a/src/r_plane.c b/src/r_plane.c index 11aa6c941ae916cfcd924d0ea55c20709f1f3081..4f9ce9ec84bdf7443a16b811504a30df674d78f7 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -624,37 +624,31 @@ void R_DrawPlanes(void) // static void R_DrawSkyPlane(visplane_t *pl) { - INT32 x; - INT32 angle; + INT32 texture = texturetranslation[skytexture]; // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) // (that is, unless we'll need to switch drawers in future for some reason) colfunc = colfuncs[BASEDRAWFUNC]; - // use correct aspect ratio scale dc_iscale = skyscale; - // Sky is always drawn full bright, - // i.e. colormaps[0] is used. - // Because of this hack, sky is not affected - // by sector colormaps (INVUL inverse mapping is not implemented in SRB2 so is irrelevant). dc_colormap = colormaps; dc_texturemid = skytexturemid; - dc_texheight = textureheight[skytexture] - >>FRACBITS; - for (x = pl->minx; x <= pl->maxx; x++) + dc_texheight = textureheight[texture]>>FRACBITS; + + R_CheckTextureCache(texture); + + for (INT32 x = pl->minx; x <= pl->maxx; x++) { dc_yl = pl->top[x]; dc_yh = pl->bottom[x]; if (dc_yl <= dc_yh) { - angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; + INT32 angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; dc_iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); dc_x = x; - dc_source = - R_GetColumn(texturetranslation[skytexture], - -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 + dc_source = R_GetColumn(texture, -angle)->pixels; // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 colfunc(); } } @@ -1004,30 +998,21 @@ void R_DrawSinglePlane(visplane_t *pl) { levelflat_t *levelflat = &levelflats[pl->picnum]; - /* :james: */ - switch (levelflat->type) + // Get the texture + ds_source = (UINT8 *)R_GetFlat(levelflat); + if (ds_source == NULL) + return; + + texture_t *texture = textures[R_GetTextureNumForFlat(levelflat)]; + ds_flatwidth = texture->width; + ds_flatheight = texture->height; + + if (R_CheckSolidColorFlat()) + ds_solidcolor = true; + else if (R_CheckPowersOfTwo()) { - case LEVELFLAT_NONE: - return; - case LEVELFLAT_FLAT: - ds_source = (UINT8 *)R_GetFlat(levelflat->u.flat.lumpnum); - R_SetFlatVars(W_LumpLength(levelflat->u.flat.lumpnum)); - if (R_CheckSolidColorFlat()) - ds_solidcolor = true; - else - ds_powersoftwo = true; - break; - default: - ds_source = (UINT8 *)R_GetLevelFlat(levelflat); - if (!ds_source) - return; - else if (R_CheckSolidColorFlat()) - ds_solidcolor = true; - else if (R_CheckPowersOfTwo()) - { - R_SetFlatVars(ds_flatwidth * ds_flatheight); - ds_powersoftwo = true; - } + R_SetFlatVars(ds_flatwidth * ds_flatheight); + ds_powersoftwo = true; } mapfunc = R_MapPlane; diff --git a/src/r_segs.c b/src/r_segs.c index 7877f1353e5b24739d86a62bb940dbe729d85afc..267c1d47d63ff32a56d6e6b0330783397dacfee3 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -96,49 +96,6 @@ void R_ClearSegTables(void) // R_RenderMaskedSegRange // ========================================================================== -// If we have a multi-patch texture on a 2sided wall (rare) then we draw -// it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this -// way we don't have to store extra post_t info with each column for -// multi-patch textures. They are not normally needed as multi-patch -// textures don't have holes in it. At least not for now. - -static void R_Render2sidedMultiPatchColumn(column_t *column) -{ - INT32 topscreen, bottomscreen; - - topscreen = sprtopscreen; // + spryscale*column->topdelta; topdelta is 0 for the wall - bottomscreen = topscreen + spryscale * lengthcol; - - dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; - - if (windowtop != INT32_MAX && windowbottom != INT32_MAX) - { - dc_yl = ((windowtop + FRACUNIT)>>FRACBITS); - dc_yh = (windowbottom - 1)>>FRACBITS; - } - - if (dc_yh >= mfloorclip[dc_x]) - dc_yh = mfloorclip[dc_x] - 1; - if (dc_yl <= mceilingclip[dc_x]) - dc_yl = mceilingclip[dc_x] + 1; - - if (dc_yl >= vid.height || dc_yh < 0) - return; - - if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) - { - dc_source = (UINT8 *)column + 3; - - if (colfunc == colfuncs[BASEDRAWFUNC]) - (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) - (colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])(); - else - colfunc(); - } -} - transnum_t R_GetLinedefTransTable(fixed_t alpha) { return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); @@ -152,12 +109,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) fixed_t height, realbot; lightlist_t *light; r_lightlist_t *rlight; - void (*colfunc_2s)(column_t *); + void (*colfunc_2s)(column_t *, unsigned); line_t *ldef; sector_t *front, *back; INT32 times, repeats; INT64 overflow_test; INT32 range; + unsigned lengthcol; // Calculate light table. // Use different light tables @@ -214,26 +172,15 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) rw_scalestep = scalestep; spryscale = scale1 + (x1 - ds->x1)*rw_scalestep; - // Texture must be cached before setting colfunc_2s, - // otherwise texture[texnum]->holes may be false when it shouldn't be + // Texture must be cached R_CheckTextureCache(texnum); - // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures - // are not stored per-column with post info in SRB2 - if (textures[texnum]->holes) - { - if (textures[texnum]->flip & 2) // vertically flipped? - { - colfunc_2s = R_DrawFlippedMaskedColumn; - lengthcol = textures[texnum]->height; - } - else - colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture - } + + if (textures[texnum]->flip & 2) // vertically flipped? + colfunc_2s = R_DrawFlippedMaskedColumn; else - { - colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) - lengthcol = textures[texnum]->height; - } + colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + + lengthcol = textures[texnum]->height; // Setup lighting based on the presence/lack-of 3D floors. dc_numlights = 0; @@ -405,7 +352,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) windowbottom = realbot; // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3); + col = R_GetColumn(texnum, maskedtexturecol[dc_x] >> FRACBITS); for (i = 0; i < dc_numlights; i++) { @@ -444,7 +391,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (windowbottom >= realbot) { windowbottom = realbot; - colfunc_2s(col); + colfunc_2s(col, lengthcol); for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; @@ -453,13 +400,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) continue; } - colfunc_2s(col); + colfunc_2s(col, lengthcol); windowtop = windowbottom + 1; dc_colormap = rlight->rcolormap; } windowbottom = realbot; if (windowtop < windowbottom) - colfunc_2s(col); + colfunc_2s(col, lengthcol); spryscale += rw_scalestep; continue; @@ -480,8 +427,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) dc_iscale = FixedMul(ds->invscale[dc_x], wall_scaley); // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3); - colfunc_2s(col); + col = R_GetColumn(texnum, maskedtexturecol[dc_x] >> FRACBITS); + colfunc_2s(col, lengthcol); spryscale += rw_scalestep; } @@ -490,10 +437,10 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } // Loop through R_DrawMaskedColumn calls -static void R_DrawRepeatMaskedColumn(column_t *col) +static void R_DrawRepeatMaskedColumn(column_t *col, unsigned lengthcol) { while (sprtopscreen < sprbotscreen) { - R_DrawMaskedColumn(col); + R_DrawMaskedColumn(col, lengthcol); if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow sprtopscreen = INT32_MAX; else @@ -501,10 +448,10 @@ static void R_DrawRepeatMaskedColumn(column_t *col) } } -static void R_DrawRepeatFlippedMaskedColumn(column_t *col) +static void R_DrawRepeatFlippedMaskedColumn(column_t *col, unsigned lengthcol) { do { - R_DrawFlippedMaskedColumn(col); + R_DrawFlippedMaskedColumn(col, lengthcol); sprtopscreen += dc_texheight*spryscale; } while (sprtopscreen < sprbotscreen); } @@ -554,8 +501,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) boolean do_texture_skew; boolean dont_peg_bottom; fixed_t wall_scalex, wall_scaley; + unsigned lengthcol; - void (*colfunc_2s) (column_t *); + void (*colfunc_2s) (column_t *, unsigned); // Calculate light table. // Use different light tables @@ -788,26 +736,15 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_texturemid += offsetvalue; - // Texture must be cached before setting colfunc_2s, - // otherwise texture[texnum]->holes may be false when it shouldn't be + // Texture must be cached R_CheckTextureCache(texnum); - //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures - // are not stored per-column with post info anymore in Doom Legacy - if (textures[texnum]->holes) - { - if (textures[texnum]->flip & 2) // vertically flipped? - { - colfunc_2s = R_DrawRepeatFlippedMaskedColumn; - lengthcol = textures[texnum]->height; - } - else - colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture - } + + if (textures[texnum]->flip & 2) // vertically flipped? + colfunc_2s = R_DrawRepeatFlippedMaskedColumn; else - { - colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) - lengthcol = textures[texnum]->height; - } + colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture + + lengthcol = textures[texnum]->height; // Set heights according to plane, or slope, whichever { @@ -873,7 +810,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_iscale = FixedMul(0xffffffffu / (unsigned)spryscale, wall_scaley); // Get data for the column - col = (column_t *)((UINT8 *)R_GetColumn(texnum, (thicksidecol[dc_x] >> FRACBITS)) - 3); + col = R_GetColumn(texnum, (thicksidecol[dc_x] >> FRACBITS)); // SoM: New code does not rely on R_DrawColumnShadowed_8 which // will (hopefully) put less strain on the stack. @@ -965,7 +902,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { windowbottom = sprbotscreen; // draw the texture - colfunc_2s (col); + colfunc_2s (col, lengthcol); for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; @@ -976,7 +913,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) continue; } // draw the texture - colfunc_2s (col); + colfunc_2s (col, lengthcol); if (solid) windowtop = bheight; else @@ -987,7 +924,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) windowbottom = sprbotscreen; // draw the texture, if there is any space left if (windowtop < windowbottom) - colfunc_2s (col); + colfunc_2s (col, lengthcol); spryscale += rw_scalestep; continue; @@ -1007,7 +944,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); // draw the texture - colfunc_2s (col); + colfunc_2s (col, lengthcol); spryscale += rw_scalestep; } colfunc = colfuncs[BASEDRAWFUNC]; @@ -1078,6 +1015,13 @@ static void R_RenderSegLoop (void) INT32 bottom; INT32 i; + if (midtexture) + R_CheckTextureCache(midtexture); + if (toptexture) + R_CheckTextureCache(toptexture); + if (bottomtexture) + R_CheckTextureCache(bottomtexture); + for (; rw_x < rw_stopx; rw_x++) { // mark floor / ceiling areas @@ -1309,7 +1253,7 @@ static void R_RenderSegLoop (void) dc_yh = yh; dc_texturemid = rw_midtexturemid; dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_midtexturescaley); - dc_source = R_GetColumn(midtexture, offset >> FRACBITS); + dc_source = R_GetColumn(midtexture, offset >> FRACBITS)->pixels; dc_texheight = textureheight[midtexture]>>FRACBITS; //profile stuff --------------------------------------------------------- @@ -1378,7 +1322,7 @@ static void R_RenderSegLoop (void) dc_yh = mid; dc_texturemid = rw_toptexturemid; dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_toptexturescaley); - dc_source = R_GetColumn(toptexture, offset >> FRACBITS); + dc_source = R_GetColumn(toptexture, offset >> FRACBITS)->pixels; dc_texheight = textureheight[toptexture]>>FRACBITS; colfunc(); ceilingclip[rw_x] = (INT16)mid; @@ -1426,7 +1370,7 @@ static void R_RenderSegLoop (void) dc_yh = yh; dc_texturemid = rw_bottomtexturemid; dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_bottomtexturescaley); - dc_source = R_GetColumn(bottomtexture, offset >> FRACBITS); + dc_source = R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels; dc_texheight = textureheight[bottomtexture]>>FRACBITS; colfunc(); floorclip[rw_x] = (INT16)mid; diff --git a/src/r_textures.c b/src/r_textures.c index 8b47f455e8bc7e2e3a9cb766fb38b357b96d4091..27a9336319bdbb71a1d0d1c4747c5a0db73fb2b2 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -48,7 +48,7 @@ INT32 numtextures = 0; // total number of textures found, // size of following tables texture_t **textures = NULL; -UINT32 **texturecolumnofs; // column offset lookup table for each texture +column_t **texturecolumns; // columns for each texture UINT8 **texturecache; // graphics data for each generated full-size texture INT32 *texturewidth; @@ -61,6 +61,7 @@ static struct { char name[9]; UINT32 hash; INT32 id; + UINT8 type; } *tidcache = NULL; static INT32 tidcachelen = 0; @@ -78,24 +79,20 @@ static INT32 tidcachelen = 0; // R_DrawColumnInCache // Clip and draw a column from a patch into a cached post. // -static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static void R_DrawColumnInCache(column_t *column, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight, UINT8 *opaque_pixels) { INT32 count, position; UINT8 *source; - INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; (void)patchheight; // This parameter is unused - while (patch->topdelta != 0xff) + for (unsigned i = 0; i < column->num_posts; i++) { - topdelta = patch->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (UINT8 *)patch + 3; - count = patch->length; - position = originy + topdelta; + post_t *post = &column->posts[i]; + source = column->pixels + post->data_offset; + count = post->length; + position = originy + post->topdelta; if (position < 0) { @@ -108,9 +105,10 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, texpatch_t count = cacheheight - position; if (count > 0) + { M_Memcpy(cache + position, source, count); - - patch = (column_t *)((UINT8 *)patch + patch->length + 4); + memset(opaque_pixels + position, true, count); + } } } @@ -118,22 +116,20 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, texpatch_t // R_DrawFlippedColumnInCache // Similar to R_DrawColumnInCache; it draws the column inverted, however. // -static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static void R_DrawFlippedColumnInCache(column_t *column, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight, UINT8 *opaque_pixels) { INT32 count, position; UINT8 *source, *dest; - INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; + INT32 topdelta; + UINT8 *is_opaque; - while (patch->topdelta != 0xff) + for (unsigned i = 0; i < column->num_posts; i++) { - topdelta = patch->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topdelta = patchheight-patch->length-topdelta; - source = (UINT8 *)patch + 2 + patch->length; // patch + 3 + (patch->length-1) - count = patch->length; + post_t *post = &column->posts[i]; + topdelta = patchheight - post->length - post->topdelta; + source = column->pixels + post->data_offset + (post->length - 1); + count = post->length; position = originy + topdelta; if (position < 0) @@ -147,38 +143,38 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, tex count = cacheheight - position; dest = cache + position; + is_opaque = opaque_pixels + position; + if (count > 0) { for (; dest < cache + position + count; --source) + { *dest++ = *source; + *is_opaque = true; + } } - - patch = (column_t *)((UINT8 *)patch + patch->length + 4); } } // // R_DrawBlendColumnInCache -// Draws a translucent column into the cache, applying a half-cooked equation to get a proper translucency value (Needs code in R_GenerateTexture()). +// Draws a translucent column into the cache. // -static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static void R_DrawBlendColumnInCache(column_t *column, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight, UINT8 *opaque_pixels) { INT32 count, position; UINT8 *source, *dest; - INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; + UINT8 *is_opaque; (void)patchheight; // This parameter is unused - while (patch->topdelta != 0xff) + for (unsigned i = 0; i < column->num_posts; i++) { - topdelta = patch->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (UINT8 *)patch + 3; - count = patch->length; - position = originy + topdelta; + post_t *post = &column->posts[i]; + source = column->pixels + post->data_offset; + count = post->length; + position = originy + post->topdelta; if (position < 0) { @@ -191,14 +187,16 @@ static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpa count = cacheheight - position; dest = cache + position; + is_opaque = opaque_pixels + position; + if (count > 0) { for (; dest < cache + position + count; source++, dest++) - if (*source != 0xFF) - *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); + { + *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); + *is_opaque = true; + } } - - patch = (column_t *)((UINT8 *)patch + patch->length + 4); } } @@ -206,22 +204,20 @@ static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpa // R_DrawBlendFlippedColumnInCache // Similar to the one above except that the column is inverted. // -static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static void R_DrawBlendFlippedColumnInCache(column_t *column, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight, UINT8 *opaque_pixels) { INT32 count, position; UINT8 *source, *dest; - INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; + INT32 topdelta; + UINT8 *is_opaque; - while (patch->topdelta != 0xff) + for (unsigned i = 0; i < column->num_posts; i++) { - topdelta = patch->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topdelta = patchheight-patch->length-topdelta; - source = (UINT8 *)patch + 2 + patch->length; // patch + 3 + (patch->length-1) - count = patch->length; + post_t *post = &column->posts[i]; + topdelta = patchheight - post->length - post->topdelta; + source = column->pixels + post->data_offset + (post->length - 1); + count = post->length; position = originy + topdelta; if (position < 0) @@ -235,14 +231,16 @@ static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache count = cacheheight - position; dest = cache + position; + is_opaque = opaque_pixels + position; + if (count > 0) { for (; dest < cache + position + count; --source, dest++) - if (*source != 0xFF) - *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); + { + *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); + *is_opaque = true; + } } - - patch = (column_t *)((UINT8 *)patch + patch->length + 4); } } @@ -252,7 +250,7 @@ static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache // Allocate space for full size texture, either single patch or 'composite' // Build the full textures from patches. // The texture caching system is a little more hungry of memory, but has -// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed. +// been simplified for the sake of highcolor, dynamic lighting, & speed. // // This is not optimised, but it's supposed to be executed only once // per level, when enough memory is available. @@ -261,24 +259,25 @@ UINT8 *R_GenerateTexture(size_t texnum) { UINT8 *block; UINT8 *blocktex; + UINT8 *temp_block; texture_t *texture; texpatch_t *patch; - softwarepatch_t *realpatch; - UINT8 *pdata; int x, x1, x2, i, width, height; size_t blocksize; - column_t *patchcol; - UINT8 *colofs; - - UINT16 wadnum; - lumpnum_t lumpnum; - size_t lumplength; + unsigned *column_posts; + UINT8 *opaque_pixels; + column_t *columns, *temp_columns; + post_t *posts, *temp_posts = NULL; + size_t total_posts = 0; + size_t total_pixels = 0; I_Assert(texnum <= (size_t)numtextures); texture = textures[texnum]; I_Assert(texture != NULL); - // allocate texture column offset lookup + // Just create a composite one + if (texture->type == TEXTURETYPE_FLAT) + goto multipatch; // single-patch textures can have holes in them and may be used on // 2sided lines so they need to be kept in 'packed' format @@ -286,72 +285,78 @@ UINT8 *R_GenerateTexture(size_t texnum) // so check if there's holes and if not strip the posts. if (texture->patchcount == 1) { - boolean holey = false; - patch = texture->patches; + patch = &texture->patches[0]; - wadnum = patch->wad; - lumpnum = patch->lump; - lumplength = W_LumpLengthPwad(wadnum, lumpnum); - pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - realpatch = (softwarepatch_t *)pdata; + UINT16 wadnum = patch->wad; + UINT16 lumpnum = patch->lump; + UINT8 *pdata; + softwarepatch_t *realpatch; + boolean holey = false; #ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) - goto multipatch; -#endif -#ifdef WALLFLATS - if (texture->type == TEXTURETYPE_FLAT) + UINT8 header[PNG_HEADER_SIZE]; + + W_ReadLumpHeaderPwad(wadnum, lumpnum, header, PNG_HEADER_SIZE, 0); + + // Not worth converting + if (Picture_IsLumpPNG(header, W_LumpLengthPwad(wadnum, lumpnum))) goto multipatch; #endif + pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + realpatch = (softwarepatch_t *)pdata; + // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) holey = true; - colofs = (UINT8 *)realpatch->columnofs; - for (x = 0; x < texture->width && !holey; x++) + else { - column_t *col = (column_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); - INT32 topdelta, prevdelta = -1, y = 0; - while (col->topdelta != 0xff) + UINT8 *colofs = (UINT8 *)realpatch->columnofs; + for (x = 0; x < texture->width; x++) { - topdelta = col->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - if (topdelta > y) - break; - y = topdelta + col->length + 1; - col = (column_t *)((UINT8 *)col + col->length + 4); + doompost_t *col = (doompost_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); + INT32 topdelta, prevdelta = -1, y = 0; + while (col->topdelta != 0xff) + { + topdelta = col->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + if (topdelta > y) + break; + y = topdelta + col->length + 1; + col = (doompost_t *)((UINT8 *)col + col->length + 4); + } + if (y < texture->height) + holey = true; // this texture is HOLEy! D: } - if (y < texture->height) - holey = true; // this texture is HOLEy! D: } // If the patch uses transparency, we have to save it this way. if (holey) { - texture->holes = true; texture->flip = patch->flip; - blocksize = lumplength; - block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function - &texturecache[texnum]); - M_Memcpy(block, realpatch, blocksize); + + Patch_CalcDataSizes(realpatch, &total_pixels, &total_posts); + + blocksize = (sizeof(column_t) * texture->width) + (sizeof(post_t) * total_posts) + (sizeof(UINT8) * total_pixels); texturememory += blocksize; - // use the patch's column lookup - colofs = (block + 8); - texturecolumnofs[texnum] = (UINT32 *)colofs; + block = Z_Calloc(blocksize, PU_STATIC, &texturecache[texnum]); blocktex = block; - if (patch->flip & 1) // flip the patch horizontally - { - UINT8 *realcolofs = (UINT8 *)realpatch->columnofs; - for (x = 0; x < texture->width; x++) - *(UINT32 *)&colofs[x<<2] = realcolofs[( texture->width-1-x )<<2]; // swap with the offset of the other side of the texture - } + + columns = (column_t *)(block + (sizeof(UINT8) * total_pixels)); + posts = (post_t *)(block + (sizeof(UINT8) * total_pixels) + (sizeof(column_t) * texture->width)); + + texturecolumns[texnum] = columns; + + // Handles flipping as well. // we can't as easily flip the patch vertically sadly though, // we have wait until the texture itself is drawn to do that - for (x = 0; x < texture->width; x++) - *(UINT32 *)&colofs[x<<2] = LONG(LONG(*(UINT32 *)&colofs[x<<2]) + 3); + Patch_MakeColumns(realpatch, texture->width, texture->width, blocktex, columns, posts, patch->flip & 1); + + Z_Free(pdata); + goto done; } @@ -360,69 +365,73 @@ UINT8 *R_GenerateTexture(size_t texnum) // multi-patch textures (or 'composite') multipatch: - texture->holes = false; texture->flip = 0; - blocksize = (texture->width * 4) + (texture->width * texture->height); - texturememory += blocksize; - block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]); - memset(block, TRANSPARENTPIXEL, blocksize+1); // Transparency hack + // To make things easier, I just allocate WxH always + total_pixels = texture->width * texture->height; - // columns lookup table - colofs = block; - texturecolumnofs[texnum] = (UINT32 *)colofs; + opaque_pixels = Z_Calloc(total_pixels * sizeof(UINT8), PU_STATIC, NULL); + temp_columns = Z_Calloc(sizeof(column_t) * texture->width, PU_STATIC, NULL); + temp_block = Z_Calloc(total_pixels, PU_STATIC, NULL); - // texture data after the lookup table - blocktex = block + (texture->width*4); + for (x = 0; x < texture->width; x++) + { + column_t *column = &temp_columns[x]; + column->num_posts = 0; + column->posts = NULL; + column->pixels = temp_block + (texture->height * x); + } // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { - boolean dealloc = true; - static void (*ColumnDrawerPointer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer. + static void (*columnDrawer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32, UINT8 *); if (patch->style != AST_COPY) - ColumnDrawerPointer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache; + columnDrawer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache; else - ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; + columnDrawer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; - wadnum = patch->wad; - lumpnum = patch->lump; - pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - lumplength = W_LumpLengthPwad(wadnum, lumpnum); - realpatch = (softwarepatch_t *)pdata; - dealloc = true; + UINT16 wadnum = patch->wad; + lumpnum_t lumpnum = patch->lump; + UINT8 *pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + patch_t *realpatch = NULL; + boolean free_patch = true; #ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) - realpatch = (softwarepatch_t *)Picture_PNGConvert((UINT8 *)realpatch, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); + size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); + if (Picture_IsLumpPNG(pdata, lumplength)) + realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); else #endif -#ifdef WALLFLATS if (texture->type == TEXTURETYPE_FLAT) - realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); + realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, PICFLAGS_USE_TRANSPARENTPIXEL); else -#endif { - (void)lumplength; - dealloc = false; + // If this patch has already been loaded, we just use it from the cache. + realpatch = W_GetCachedPatchNumPwad(wadnum, lumpnum); + free_patch = false; + + // Otherwise, we load it here. + if (realpatch == NULL) + realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH); } x1 = patch->originx; - width = SHORT(realpatch->width); - height = SHORT(realpatch->height); + width = realpatch->width; + height = realpatch->height; x2 = x1 + width; if (x1 > texture->width || x2 < 0) { - if (dealloc) - Z_Free(realpatch); + if (free_patch) + Patch_Free(realpatch); continue; // patch not located within texture's x bounds, ignore } if (patch->originy > texture->height || (patch->originy + height) < 0) { - if (dealloc) - Z_Free(realpatch); + if (free_patch) + Patch_Free(realpatch); continue; // patch not located within texture's y bounds, ignore } @@ -441,18 +450,88 @@ UINT8 *R_GenerateTexture(size_t texnum) for (; x < x2; x++) { + INT32 colx; + if (patch->flip & 1) - patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[(x1+width-1)-x])); + colx = (x1+width-1)-x; else - patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); + colx = x-x1; + + column_t *patchcol = &realpatch->columns[colx]; - // generate column ofset lookup - *(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4)); - ColumnDrawerPointer(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch, texture->height, height); + if (patchcol->num_posts > 0) + columnDrawer(patchcol, temp_columns[x].pixels, patch, texture->height, height, &opaque_pixels[x * texture->height]); } - if (dealloc) - Z_Free(realpatch); + if (free_patch) + Patch_Free(realpatch); + } + + // Now write the columns + column_posts = Z_Calloc(sizeof(unsigned) * texture->width, PU_STATIC, NULL); + + for (x = 0; x < texture->width; x++) + { + post_t *post; + boolean was_opaque = false; + + column_t *column = &temp_columns[x]; + + column_posts[x] = (unsigned)-1; + + for (INT32 y = 0; y < texture->height; y++) + { + // End span if we have a transparent pixel + if (!opaque_pixels[(x * texture->height) + y]) + { + was_opaque = false; + continue; + } + + if (!was_opaque) + { + total_posts++; + + temp_posts = Z_Realloc(temp_posts, sizeof(post_t) * total_posts, PU_CACHE, NULL); + post = &temp_posts[total_posts - 1]; + post->topdelta = (size_t)y; + post->length = 0; + post->data_offset = (size_t)y; + if (column_posts[x] == (unsigned)-1) + column_posts[x] = total_posts - 1; + column->num_posts++; + } + + was_opaque = true; + + post->length++; + } + } + + blocksize = (sizeof(column_t) * texture->width) + (sizeof(post_t) * total_posts) + (sizeof(UINT8) * total_pixels); + texturememory += blocksize; + + block = Z_Calloc(blocksize, PU_STATIC, &texturecache[texnum]); + blocktex = block; + + memcpy(blocktex, temp_block, total_pixels); + + Z_Free(temp_block); + + columns = (column_t *)(block + (sizeof(UINT8) * total_pixels)); + posts = (post_t *)(block + (sizeof(UINT8) * total_pixels) + (sizeof(column_t) * texture->width)); + + memcpy(columns, temp_columns, sizeof(column_t) * texture->width); + memcpy(posts, temp_posts, sizeof(post_t) * total_posts); + + texturecolumns[texnum] = columns; + + for (x = 0; x < texture->width; x++) + { + column_t *column = &columns[x]; + if (column->num_posts > 0) + column->posts = &posts[column_posts[x]]; + column->pixels = blocktex + (texture->height * x); } done: @@ -461,28 +540,42 @@ done: return blocktex; } -// -// R_GenerateTextureAsFlat -// -// Generates a flat picture for a texture. -// -UINT8 *R_GenerateTextureAsFlat(size_t texnum) +UINT8 *R_GetFlatForTexture(size_t texnum) { + if (texnum >= (unsigned)numtextures) + return NULL; + texture_t *texture = textures[texnum]; - UINT8 *converted = NULL; - size_t size = (texture->width * texture->height); + if (texture->flat != NULL) + return texture->flat; - // The flat picture for this texture was not generated yet. - if (!texture->flat) + // Special case: Textures that are flats don't need to be converted FROM a texture INTO a flat. + if (texture->type == TEXTURETYPE_FLAT) { - // Well, let's do it now, then. - texture->flat = Z_Malloc(size, PU_STATIC, NULL); + texpatch_t *patch = &texture->patches[0]; + UINT16 wadnum = patch->wad; + lumpnum_t lumpnum = patch->lump; + UINT8 *pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); + +#ifndef NO_PNG_LUMPS + if (Picture_IsLumpPNG(pdata, lumplength)) + texture->flat = Picture_PNGConvert(pdata, PICFMT_FLAT, NULL, NULL, NULL, NULL, lumplength, NULL, 0); + else +#endif + { + texture->flat = Z_Malloc(lumplength, PU_STATIC, NULL); + memcpy(texture->flat, pdata, lumplength); + } + + Z_SetUser(texture->flat, &texture->flat); - // Picture_TextureToFlat handles everything for us. - converted = (UINT8 *)Picture_TextureToFlat(texnum); - M_Memcpy(texture->flat, converted, size); - Z_Free(converted); + Z_Free(pdata); } + else + texture->flat = (UINT8 *)Picture_TextureToFlat(texnum); + + flatmemory += texture->width * texture->height; return texture->flat; } @@ -513,110 +606,28 @@ void R_CheckTextureCache(INT32 tex) R_GenerateTexture(tex); } -// -// R_GetColumn -// -UINT8 *R_GetColumn(fixed_t tex, INT32 col) +column_t *R_GetColumn(fixed_t tex, INT32 col) { - UINT8 *data; INT32 width = texturewidth[tex]; - if (width & (width - 1)) col = (UINT32)col % width; else col &= (width - 1); - data = texturecache[tex]; - if (!data) - data = R_GenerateTexture(tex); - - return data + LONG(texturecolumnofs[tex][col]); + return &texturecolumns[tex][col]; } -void *R_GetFlat(lumpnum_t flatlumpnum) +INT32 R_GetTextureNumForFlat(levelflat_t *levelflat) { - return W_CacheLumpNum(flatlumpnum, PU_CACHE); + return texturetranslation[levelflat->texture_id]; } -// -// R_GetLevelFlat -// -// If needed, convert a texture or patch to a flat. -// -void *R_GetLevelFlat(levelflat_t *levelflat) +void *R_GetFlat(levelflat_t *levelflat) { - boolean isleveltexture = (levelflat->type == LEVELFLAT_TEXTURE); - texture_t *texture = (isleveltexture ? textures[levelflat->u.texture.num] : NULL); - boolean texturechanged = (isleveltexture ? (levelflat->u.texture.num != levelflat->u.texture.lastnum) : false); - UINT8 *flatdata = NULL; - - // Check if the texture changed. - if (isleveltexture && (!texturechanged)) - { - if (texture->flat) - { - flatdata = texture->flat; - ds_flatwidth = texture->width; - ds_flatheight = texture->height; - texturechanged = false; - } - else - texturechanged = true; - } - - // If the texture changed, or the flat wasn't generated, convert. - if (levelflat->picture == NULL || texturechanged) - { - // Level texture - if (isleveltexture) - { - levelflat->picture = R_GenerateTextureAsFlat(levelflat->u.texture.num); - ds_flatwidth = levelflat->width = texture->width; - ds_flatheight = levelflat->height = texture->height; - } - else - { -#ifndef NO_PNG_LUMPS - if (levelflat->type == LEVELFLAT_PNG) - { - INT32 pngwidth, pngheight; - - levelflat->picture = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0); - levelflat->width = (UINT16)pngwidth; - levelflat->height = (UINT16)pngheight; - - ds_flatwidth = levelflat->width; - ds_flatheight = levelflat->height; - } - else -#endif - if (levelflat->type == LEVELFLAT_PATCH) - { - UINT8 *converted; - size_t size; - softwarepatch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE); - - levelflat->width = ds_flatwidth = SHORT(patch->width); - levelflat->height = ds_flatheight = SHORT(patch->height); - - levelflat->picture = Z_Malloc(levelflat->width * levelflat->height, PU_LEVEL, NULL); - converted = Picture_FlatConvert(PICFMT_DOOMPATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, SHORT(patch->topoffset), SHORT(patch->leftoffset), 0); - M_Memcpy(levelflat->picture, converted, size); - Z_Free(converted); - } - } - } - else - { - ds_flatwidth = levelflat->width; - ds_flatheight = levelflat->height; - } - - levelflat->u.texture.lastnum = levelflat->u.texture.num; + if (levelflat->type == LEVELFLAT_NONE) + return NULL; - if (flatdata == NULL) - flatdata = levelflat->picture; - return flatdata; + return R_GetFlatForTexture(R_GetTextureNumForFlat(levelflat)); } // @@ -624,12 +635,12 @@ void *R_GetLevelFlat(levelflat_t *levelflat) // boolean R_CheckPowersOfTwo(void) { - boolean wpow2 = !(ds_flatwidth & (ds_flatwidth - 1)); - boolean hpow2 = !(ds_flatheight & (ds_flatheight - 1)); - if (ds_flatwidth > 2048 || ds_flatheight > 2048) return false; + boolean wpow2 = !(ds_flatwidth & (ds_flatwidth - 1)); + boolean hpow2 = !(ds_flatheight & (ds_flatheight - 1)); + return ds_flatwidth == ds_flatheight && wpow2 && hpow2; } @@ -722,98 +733,114 @@ void R_FlushTextureCache(void) if (numtextures) for (i = 0; i < numtextures; i++) + { + Z_Free(textures[i]->flat); Z_Free(texturecache[i]); + } } // Need these prototypes for later; defining them here instead of r_textures.h so they're "private" int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum); void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); -#ifdef WALLFLATS +static void R_AddSinglePatchTexture(INT32 i, UINT16 wadnum, UINT16 lumpnum, INT16 width, INT16 height, unsigned type) +{ + texture_t *texture = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); + + // Set texture properties. + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + texture->hash = quickncasehash(texture->name, 8); + + texture->width = width; + texture->height = height; + + texture->type = type; + texture->patchcount = 1; + texture->flip = 0; + + // Allocate information for the texture's patches. + texpatch_t *patch = &texture->patches[0]; + + patch->originx = patch->originy = 0; + patch->wad = wadnum; + patch->lump = lumpnum; + patch->flip = 0; + + texturewidth[i] = texture->width; + textureheight[i] = texture->height << FRACBITS; + + textures[i] = texture; +} + static INT32 Rloadflats (INT32 i, INT32 w) { - UINT16 j; - UINT16 texstart, texend; - texture_t *texture; - texpatch_t *patch; - UINT8 header[PNG_HEADER_SIZE]; + UINT16 j, numlumps = 0; + UINT16 texstart = 0, texend = 0; + UINT32 *list = NULL; - // Yes + // Get every lump inside the Flats/ folder if (W_FileHasFolders(wadfiles[w])) { - texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); + W_GetFolderLumpsPwad("Flats/", (UINT16)w, &list, NULL, &numlumps); } else { + // Else, get the lumps between F_START/F_END markers texstart = W_CheckNumForMarkerStartPwad("F_START", (UINT16)w, 0); texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); + if (texstart == INT16_MAX || texend == INT16_MAX) + return i; + + numlumps = texend - texstart; } - if (!( texstart == INT16_MAX || texend == INT16_MAX )) + // Now add every entry as a texture + for (j = 0; j < numlumps; j++) { - // Work through each lump between the markers in the WAD. - for (j = 0; j < (texend - texstart); j++) - { - UINT16 wadnum = (UINT16)w; - lumpnum_t lumpnum = texstart + j; - size_t lumplength; - size_t flatsize; + UINT16 wadnum = list ? WADFILENUM(list[j]) : (UINT16)w; + UINT16 lumpnum = list ? LUMPNUM(list[j]) : (texstart + j); - if (W_FileHasFolders(wadfiles[w])) - { - if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder - continue; // If it is then SKIP IT - } + size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); + size_t flatsize = R_GetFlatSize(lumplength); - W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0); - lumplength = W_LumpLengthPwad(wadnum, lumpnum); - flatsize = R_GetFlatSize(lumplength); + INT16 width = flatsize, height = flatsize; - //CONS_Printf("\n\"%s\" is a flat, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),flatsize,flatsize); - texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); +#ifndef NO_PNG_LUMPS + UINT8 header[PNG_HEADER_SIZE]; - // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); - texture->hash = quickncasehash(texture->name, 8); + W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0); -#ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG(header, lumplength)) + if (Picture_IsLumpPNG(header, lumplength)) + { + INT32 texw, texh; + UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + if (Picture_PNGDimensions((UINT8 *)flatlump, &texw, &texh, NULL, NULL, lumplength)) { - UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - INT32 width, height; - Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, NULL, NULL, lumplength); - texture->width = (INT16)width; - texture->height = (INT16)height; - Z_Free(flatlump); + width = (INT16)width; + height = (INT16)height; } else + { + width = 1; + height = 1; + } + Z_Free(flatlump); + } #endif - texture->width = texture->height = flatsize; - - texture->type = TEXTURETYPE_FLAT; - texture->patchcount = 1; - texture->holes = false; - texture->flip = 0; - // Allocate information for the texture's patches. - patch = &texture->patches[0]; + // printf("\"%s\" (wad: %u, lump: %u) is a flat, dimensions %d x %d\n",W_CheckNameForNumPwad(wadnum,lumpnum),wadnum,lumpnum,width,height); - patch->originx = patch->originy = 0; - patch->wad = (UINT16)w; - patch->lump = texstart + j; - patch->flip = 0; + R_AddSinglePatchTexture(i, wadnum, lumpnum, width, height, TEXTURETYPE_FLAT); - texturewidth[i] = texture->width; - textureheight[i] = texture->height << FRACBITS; - i++; - } + i++; } + if (list) + Z_Free(list); + return i; } -#endif/*WALLFLATS*/ #define TX_START "TX_START" #define TX_END "TX_END" @@ -821,17 +848,16 @@ Rloadflats (INT32 i, INT32 w) static INT32 Rloadtextures (INT32 i, INT32 w) { - UINT16 j; - UINT16 texstart, texend, texturesLumpPos; - texture_t *texture; - texpatch_t *patch; - softwarepatch_t patchlump; + UINT16 j, numlumps = 0; + UINT16 texstart = 0, texend = 0; + UINT16 texturesLumpPos; + UINT32 *list = NULL; - // Get the lump numbers for the markers in the WAD, if they exist. + // Get every lump inside the Textures/ folder if (W_FileHasFolders(wadfiles[w])) { - texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); + W_GetFolderLumpsPwad("Textures/", (UINT16)w, &list, NULL, &numlumps); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); while (texturesLumpPos != INT16_MAX) { @@ -839,80 +865,45 @@ Rloadtextures (INT32 i, INT32 w) texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); } } + // Else, get the lumps between TX_START/TX_END markers else { - texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0); - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); if (texturesLumpPos != INT16_MAX) R_ParseTEXTURESLump(w, texturesLumpPos, &i); - } - - if (!( texstart == INT16_MAX || texend == INT16_MAX )) - { - // Work through each lump between the markers in the WAD. - for (j = 0; j < (texend - texstart); j++) - { - UINT16 wadnum = (UINT16)w; - lumpnum_t lumpnum = texstart + j; -#ifndef NO_PNG_LUMPS - size_t lumplength; -#endif - - if (W_FileHasFolders(wadfiles[w])) - { - if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder - continue; // If it is then SKIP IT - } - W_ReadLumpHeaderPwad(wadnum, lumpnum, &patchlump, PNG_HEADER_SIZE, 0); -#ifndef NO_PNG_LUMPS - lumplength = W_LumpLengthPwad(wadnum, lumpnum); -#endif + texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0); + texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, texstart); + if (texstart == INT16_MAX || texend == INT16_MAX) + return i; - //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); - texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); + numlumps = texend - texstart; + } - // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); - texture->hash = quickncasehash(texture->name, 8); + // Now add every entry as a texture + for (j = 0; j < numlumps; j++) + { + UINT16 wadnum = list ? WADFILENUM(list[j]) : (UINT16)w; + UINT16 lumpnum = list ? LUMPNUM(list[j]) : (texstart + j); -#ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength)) - { - UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - INT32 width, height; - Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength); - texture->width = (INT16)width; - texture->height = (INT16)height; - Z_Free(png); - } - else -#endif - { - texture->width = SHORT(patchlump.width); - texture->height = SHORT(patchlump.height); - } + INT16 width = 0, height = 0; - texture->type = TEXTURETYPE_SINGLEPATCH; - texture->patchcount = 1; - texture->holes = false; - texture->flip = 0; + if (!W_ReadPatchHeaderPwad(wadnum, lumpnum, &width, &height, NULL, NULL)) + { + width = 1; + height = 1; + } - // Allocate information for the texture's patches. - patch = &texture->patches[0]; + // printf("\"%s\" (wad: %u, lump: %u) is a single patch, dimensions %d x %d\n",W_CheckNameForNumPwad(wadnum,lumpnum),wadnum,lumpnum,width,height); - patch->originx = patch->originy = 0; - patch->wad = (UINT16)w; - patch->lump = texstart + j; - patch->flip = 0; + R_AddSinglePatchTexture(i, wadnum, lumpnum, width, height, TEXTURETYPE_SINGLEPATCH); - texturewidth[i] = texture->width; - textureheight[i] = texture->height << FRACBITS; - i++; - } + i++; } + if (list) + Z_Free(list); + return i; } @@ -923,37 +914,17 @@ count_range const char * folder, UINT16 wadnum) { - UINT16 j; - UINT16 texstart, texend; INT32 count = 0; - // Count flats if (W_FileHasFolders(wadfiles[wadnum])) - { - texstart = W_CheckNumForFolderStartPK3(folder, wadnum, 0); - texend = W_CheckNumForFolderEndPK3(folder, wadnum, texstart); - } + count += W_CountFolderLumpsPwad(folder, wadnum); else { - texstart = W_CheckNumForMarkerStartPwad(marker_start, wadnum, 0); - texend = W_CheckNumForNamePwad(marker_end, wadnum, texstart); - } + UINT16 texstart = W_CheckNumForMarkerStartPwad(marker_start, wadnum, 0); + UINT16 texend = W_CheckNumForNamePwad(marker_end, wadnum, texstart); - if (texstart != INT16_MAX && texend != INT16_MAX) - { - // PK3s have subfolders, so we can't just make a simple sum - if (W_FileHasFolders(wadfiles[wadnum])) - { - for (j = texstart; j < texend; j++) - { - if (!W_IsLumpFolder(wadnum, j)) // Check if lump is a folder; if not, then count it - count++; - } - } - else // Add all the textures between markers - { + if (texstart != INT16_MAX && texend != INT16_MAX) count += (texend - texstart); - } } return count; @@ -972,9 +943,7 @@ static INT32 R_CountTextures(UINT16 wadnum) // This system will allocate memory for all duplicate/patched textures even if it never uses them, // but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures. -#ifdef WALLFLATS count += count_range("F_START", "F_END", "flats/", wadnum); -#endif // Count the textures from TEXTURES lumps texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", wadnum, 0); @@ -1016,7 +985,7 @@ static void R_AllocateTextures(INT32 add) recallocuser(&textures, oldsize, newsize); // Allocate texture column offset table. - recallocuser(&texturecolumnofs, oldsize, newsize); + recallocuser(&texturecolumns, oldsize, newsize); // Allocate texture referencing cache. recallocuser(&texturecache, oldsize, newsize); // Allocate texture width table. @@ -1044,9 +1013,7 @@ static void R_AllocateTextures(INT32 add) static INT32 R_DefineTextures(INT32 i, UINT16 w) { -#ifdef WALLFLATS i = Rloadflats(i, w); -#endif return Rloadtextures(i, w); } @@ -1563,55 +1530,6 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) Z_Free((void *)texturesText); } -// Search for flat name. -lumpnum_t R_GetFlatNumForName(const char *name) -{ - INT32 i; - lumpnum_t lump; - lumpnum_t start; - lumpnum_t end; - - // Scan wad files backwards so patched flats take preference. - for (i = numwadfiles - 1; i >= 0; i--) - { - switch (wadfiles[i]->type) - { - case RET_WAD: - if ((start = W_CheckNumForMarkerStartPwad("F_START", (UINT16)i, 0)) == INT16_MAX) - { - if ((start = W_CheckNumForMarkerStartPwad("FF_START", (UINT16)i, 0)) == INT16_MAX) - continue; - else if ((end = W_CheckNumForNamePwad("FF_END", (UINT16)i, start)) == INT16_MAX) - continue; - } - else - if ((end = W_CheckNumForNamePwad("F_END", (UINT16)i, start)) == INT16_MAX) - continue; - break; - case RET_PK3: - case RET_FOLDER: - if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX) - continue; - if ((end = W_CheckNumForFolderEndPK3("Flats/", i, start)) == INT16_MAX) - continue; - break; - default: - continue; - } - - // Now find lump with specified name in that range. - lump = W_CheckNumForNamePwad(name, (UINT16)i, start); - if (lump < end) - { - lump += (i<<16); // found it, in our constraints - break; - } - lump = LUMPERROR; - } - - return lump; -} - void R_ClearTextureNumCache(boolean btell) { if (tidcache) @@ -1622,6 +1540,20 @@ void R_ClearTextureNumCache(boolean btell) tidcachelen = 0; } +static void AddTextureToCache(const char *name, UINT32 hash, INT32 id, UINT8 type) +{ + tidcachelen++; + Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache); + strncpy(tidcache[tidcachelen-1].name, name, 8); + tidcache[tidcachelen-1].name[8] = '\0'; +#ifndef ZDEBUG + CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name); +#endif + tidcache[tidcachelen-1].hash = hash; + tidcache[tidcachelen-1].id = id; + tidcache[tidcachelen-1].type = type; +} + // // R_CheckTextureNumForName // @@ -1643,19 +1575,10 @@ INT32 R_CheckTextureNumForName(const char *name) return tidcache[i].id; // Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier - //for (i = 0; i < numtextures; i++) <- old - for (i = (numtextures - 1); i >= 0; i--) // <- new + for (i = numtextures - 1; i >= 0; i--) if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8)) { - tidcachelen++; - Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache); - strncpy(tidcache[tidcachelen-1].name, name, 8); - tidcache[tidcachelen-1].name[8] = '\0'; -#ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name); -#endif - tidcache[tidcachelen-1].hash = hash; - tidcache[tidcachelen-1].id = i; + AddTextureToCache(name, hash, i, textures[i]->type); return i; } @@ -1712,3 +1635,29 @@ INT32 R_TextureNumForName(const char *name) } return i; } + +// Like R_CheckTextureNumForName, but only looks in the flat namespace specifically. +INT32 R_CheckFlatNumForName(const char *name) +{ + INT32 i; + UINT32 hash; + + // "NoTexture" marker. + if (name[0] == '-') + return 0; + + hash = quickncasehash(name, 8); + + for (i = 0; i < tidcachelen; i++) + if (tidcache[i].type == TEXTURETYPE_FLAT && tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8)) + return tidcache[i].id; + + for (i = numtextures - 1; i >= 0; i--) + if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8) && textures[i]->type == TEXTURETYPE_FLAT) + { + AddTextureToCache(name, hash, i, TEXTURETYPE_FLAT); + return i; + } + + return -1; +} diff --git a/src/r_textures.h b/src/r_textures.h index 394b4f8243a7fa7a0de120f2ff893bc1dc9f0702..eb68ec09f21d4fe8d847b048ac12ba9bd3a1817d 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -42,9 +42,7 @@ enum TEXTURETYPE_UNKNOWN, TEXTURETYPE_SINGLEPATCH, TEXTURETYPE_COMPOSITE, -#ifdef WALLFLATS - TEXTURETYPE_FLAT, -#endif + TEXTURETYPE_FLAT }; // A texture_t describes a rectangular texture, @@ -55,9 +53,8 @@ typedef struct // Keep name for switch changing, etc. char name[8]; UINT32 hash; - UINT8 type; // TEXTURETYPE_ + UINT8 type; // TEXTURETYPE_* INT16 width, height; - boolean holes; UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both void *flat; // The texture, as a flat. @@ -72,7 +69,7 @@ extern texture_t **textures; extern INT32 *texturewidth; extern fixed_t *textureheight; // needed for texture pegging -extern UINT32 **texturecolumnofs; // column offset lookup table for each texture +extern column_t **texturecolumns; // columns for each texture extern UINT8 **texturecache; // graphics data for each generated full-size texture // Load TEXTURES definitions, create lookup tables @@ -82,15 +79,16 @@ void R_FlushTextureCache(void); // Texture generation UINT8 *R_GenerateTexture(size_t texnum); -UINT8 *R_GenerateTextureAsFlat(size_t texnum); +UINT8 *R_GetFlatForTexture(size_t texnum); INT32 R_GetTextureNum(INT32 texnum); void R_CheckTextureCache(INT32 tex); void R_ClearTextureNumCache(boolean btell); // Retrieve texture data. -void *R_GetLevelFlat(levelflat_t *levelflat); -UINT8 *R_GetColumn(fixed_t tex, INT32 col); -void *R_GetFlat(lumpnum_t flatnum); +column_t *R_GetColumn(fixed_t tex, INT32 col); +void *R_GetFlat(levelflat_t *levelflat); + +INT32 R_GetTextureNumForFlat(levelflat_t *levelflat); boolean R_CheckPowersOfTwo(void); boolean R_CheckSolidColorFlat(void); @@ -102,7 +100,7 @@ void R_SetFlatVars(size_t length); // Returns the texture number for the texture name. INT32 R_TextureNumForName(const char *name); INT32 R_CheckTextureNumForName(const char *name); -lumpnum_t R_GetFlatNumForName(const char *name); +INT32 R_CheckFlatNumForName(const char *name); // Returns the texture name for the texture number (in case you ever needed it) const char *R_CheckTextureNameForNum(INT32 num); diff --git a/src/r_things.c b/src/r_things.c index 07420e34ad284e9dea9998e443baa37613e071a8..d6ef72b9d29980134757df4547ffd03837379957 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -257,7 +257,6 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 UINT8 frame; UINT8 rotation; lumpinfo_t *lumpinfo; - softwarepatch_t patch; UINT16 numadded = 0; memset(sprtemp,0xFF, sizeof (sprtemp)); @@ -285,11 +284,8 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 { if (memcmp(lumpinfo[l].name,sprname,4)==0) { - INT32 width, height; + INT16 width, height; INT16 topoffset, leftoffset; -#ifndef NO_PNG_LUMPS - boolean isPNG = false; -#endif frame = R_Char2Frame(lumpinfo[l].name[4]); rotation = R_Char2Rotation(lumpinfo[l].name[5]); @@ -304,33 +300,12 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 if (W_LumpLengthPwad(wadnum,l)<=8) continue; + // Get the patch's dimensions only + if (!W_ReadPatchHeaderPwad(wadnum, l, &width, &height, &topoffset, &leftoffset)) + continue; + // store sprite info in lookup tables //FIXME : numspritelumps do not duplicate sprite replacements - -#ifndef NO_PNG_LUMPS - { - softwarepatch_t *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC); - size_t len = W_LumpLengthPwad(wadnum, l); - - if (Picture_IsLumpPNG((UINT8 *)png, len)) - { - Picture_PNGDimensions((UINT8 *)png, &width, &height, &topoffset, &leftoffset, len); - isPNG = true; - } - - Z_Free(png); - } - - if (!isPNG) -#endif - { - W_ReadLumpHeaderPwad(wadnum, l, &patch, sizeof(INT16) * 4, 0); - width = (INT32)(SHORT(patch.width)); - height = (INT32)(SHORT(patch.height)); - topoffset = (INT16)(SHORT(patch.topoffset)); - leftoffset = (INT16)(SHORT(patch.leftoffset)); - } - spritecachedinfo[numspritelumps].width = width<<FRACBITS; spritecachedinfo[numspritelumps].offset = leftoffset<<FRACBITS; spritecachedinfo[numspritelumps].topoffset = topoffset<<FRACBITS; @@ -635,25 +610,18 @@ INT16 *mceilingclip; fixed_t spryscale = 0, sprtopscreen = 0, sprbotscreen = 0; fixed_t windowtop = 0, windowbottom = 0; -void R_DrawMaskedColumn(column_t *column) +void R_DrawMaskedColumn(column_t *column, unsigned lengthcol) { - INT32 topscreen; - INT32 bottomscreen; - fixed_t basetexturemid; - INT32 topdelta, prevdelta = 0; + fixed_t basetexturemid = dc_texturemid; - basetexturemid = dc_texturemid; + (void)lengthcol; - for (; column->topdelta != 0xff ;) + for (unsigned i = 0; i < column->num_posts; i++) { - // calculate unclipped screen coordinates - // for post - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topscreen = sprtopscreen + spryscale*topdelta; - bottomscreen = topscreen + spryscale*column->length; + post_t *post = &column->posts[i]; + + INT32 topscreen = sprtopscreen + spryscale*post->topdelta; + INT32 bottomscreen = topscreen + spryscale*post->length; dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; @@ -677,48 +645,36 @@ void R_DrawMaskedColumn(column_t *column) if (dc_yl <= dc_yh && dc_yh > 0) { - dc_source = (UINT8 *)column + 3; - dc_texturemid = basetexturemid - (topdelta<<FRACBITS); + dc_source = column->pixels + post->data_offset; + dc_texturemid = basetexturemid - (post->topdelta<<FRACBITS); - // Drawn by R_DrawColumn. - // This stuff is a likely cause of the splitscreen water crash bug. - // FIXTHIS: Figure out what "something more proper" is and do it. - // quick fix... something more proper should be done!!! - if (ylookup[dc_yl]) - colfunc(); -#ifdef PARANOIA - else - I_Error("R_DrawMaskedColumn: Invalid ylookup for dc_yl %d", dc_yl); -#endif + colfunc(); } - column = (column_t *)((UINT8 *)column + column->length + 4); } dc_texturemid = basetexturemid; } -INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height +static UINT8 *flippedcol = NULL; +static size_t flippedcolsize = 0; -void R_DrawFlippedMaskedColumn(column_t *column) +void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) { INT32 topscreen; INT32 bottomscreen; fixed_t basetexturemid = dc_texturemid; - INT32 topdelta, prevdelta = -1; UINT8 *d,*s; - for (; column->topdelta != 0xff ;) + for (unsigned i = 0; i < column->num_posts; i++) { - // calculate unclipped screen coordinates - // for post - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topdelta = lengthcol-column->length-topdelta; + post_t *post = &column->posts[i]; + if (!post->length) + continue; + + INT32 topdelta = lengthcol-post->length-post->topdelta; topscreen = sprtopscreen + spryscale*topdelta; - bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*column->length - : sprbotscreen + spryscale*column->length; + bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*post->length + : sprbotscreen + spryscale*post->length; dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; @@ -742,21 +698,19 @@ void R_DrawFlippedMaskedColumn(column_t *column) if (dc_yl <= dc_yh && dc_yh > 0) { - dc_source = ZZ_Alloc(column->length); - for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s) + if (post->length > flippedcolsize) + { + flippedcolsize = post->length; + flippedcol = Z_Realloc(flippedcol, flippedcolsize, PU_STATIC, NULL); + } + + for (s = column->pixels+post->data_offset+post->length, d = flippedcol; d < flippedcol+post->length; --s) *d++ = *s; + dc_source = flippedcol; dc_texturemid = basetexturemid - (topdelta<<FRACBITS); - // Still drawn by R_DrawColumn. - if (ylookup[dc_yl]) - colfunc(); -#ifdef PARANOIA - else - I_Error("R_DrawMaskedColumn: Invalid ylookup for dc_yl %d", dc_yl); -#endif - Z_Free(dc_source); + colfunc(); } - column = (column_t *)((UINT8 *)column + column->length + 4); } dc_texturemid = basetexturemid; @@ -816,14 +770,14 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans static void R_DrawVisSprite(vissprite_t *vis) { column_t *column; - void (*localcolfunc)(column_t *); - INT32 texturecolumn; + void (*localcolfunc)(column_t *, unsigned); INT32 pwidth; fixed_t frac; patch_t *patch = vis->patch; fixed_t this_scale = vis->thingscale; INT32 x1, x2; INT64 overflow_test; + unsigned lengthcol; if (!patch) return; @@ -942,7 +896,7 @@ static void R_DrawVisSprite(vissprite_t *vis) for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += scalestep) { angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF; - texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / horzscale; + INT32 texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / horzscale; if (texturecolumn < 0 || texturecolumn >= pwidth) continue; @@ -953,9 +907,9 @@ static void R_DrawVisSprite(vissprite_t *vis) sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); dc_iscale = (0xffffffffu / (unsigned)spryscale); - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); + column = &patch->columns[texturecolumn]; - localcolfunc (column); + localcolfunc (column, lengthcol); } } else if (vis->cut & SC_SHEAR) @@ -967,17 +921,9 @@ static void R_DrawVisSprite(vissprite_t *vis) // Vertically sheared sprite for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, dc_texturemid -= vis->shear.tan) { -#ifdef RANGECHECK - texturecolumn = frac>>FRACBITS; - if (texturecolumn < 0 || texturecolumn >= pwidth) - I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); -#else - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); -#endif - + column = &patch->columns[frac>>FRACBITS]; sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - localcolfunc (column); + localcolfunc (column, lengthcol); } } else @@ -989,15 +935,8 @@ static void R_DrawVisSprite(vissprite_t *vis) // Non-paper drawing loop for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan) { -#ifdef RANGECHECK - texturecolumn = frac>>FRACBITS; - if (texturecolumn < 0 || texturecolumn >= pwidth) - I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); -#else - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); -#endif - localcolfunc (column); + column = &patch->columns[frac>>FRACBITS]; + localcolfunc (column, lengthcol); } } @@ -1011,21 +950,12 @@ static void R_DrawVisSprite(vissprite_t *vis) // Special precipitation drawer Tails 08-18-2002 static void R_DrawPrecipitationVisSprite(vissprite_t *vis) { - column_t *column; -#ifdef RANGECHECK - INT32 texturecolumn; -#endif - fixed_t frac; - patch_t *patch; - INT64 overflow_test; - - //Fab : R_InitSprites now sets a wad lump number - patch = vis->patch; + patch_t *patch = vis->patch; if (!patch) return; // Check for overflow - overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS); + INT64 overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS); if (overflow_test < 0) overflow_test = -overflow_test; if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow @@ -1041,31 +971,19 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) dc_texturemid = vis->texturemid; dc_texheight = 0; - frac = vis->startfrac; spryscale = vis->scale; sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); windowtop = windowbottom = sprbotscreen = INT32_MAX; if (vis->x1 < 0) vis->x1 = 0; - if (vis->x2 >= vid.width) vis->x2 = vid.width-1; - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) - { -#ifdef RANGECHECK - texturecolumn = frac>>FRACBITS; - - if (texturecolumn < 0 || texturecolumn >= patch->width) - I_Error("R_DrawPrecipitationSpriteRange: bad texturecolumn"); + fixed_t frac = vis->startfrac; - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); -#else - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); -#endif - R_DrawMaskedColumn(column); - } + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) + R_DrawMaskedColumn(&patch->columns[frac>>FRACBITS], patch->height); colfunc = colfuncs[BASEDRAWFUNC]; } diff --git a/src/r_things.h b/src/r_things.h index bd0a350093453a7798e3d254c6ddb7b3c16cce35..043b454b049cefa907c16f12c13751236db4b456 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -45,10 +45,9 @@ extern fixed_t sprtopscreen; extern fixed_t sprbotscreen; extern fixed_t windowtop; extern fixed_t windowbottom; -extern INT32 lengthcol; -void R_DrawMaskedColumn(column_t *column); -void R_DrawFlippedMaskedColumn(column_t *column); +void R_DrawMaskedColumn(column_t *column, unsigned lengthcol); +void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol); // ---------------- // SPRITE RENDERING diff --git a/src/screen.c b/src/screen.c index ca59b251dce1f6f1371af433b010a18b4304e621..76f546402ef38e0a4882221945ff602de73aadf9 100644 --- a/src/screen.c +++ b/src/screen.c @@ -116,8 +116,6 @@ void SCR_SetDrawFuncs(void) colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8; colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8; colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8; colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8; spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8; diff --git a/src/screen.h b/src/screen.h index e4c1006c35b79a7f9948f818c0a3b03edf84c558..64d92b9d3ef99cf3c4e066ddc5cc9e57edd94afd 100644 --- a/src/screen.h +++ b/src/screen.h @@ -126,8 +126,6 @@ enum COLDRAWFUNC_SHADE, COLDRAWFUNC_SHADOWED, COLDRAWFUNC_TRANSTRANS, - COLDRAWFUNC_TWOSMULTIPATCH, - COLDRAWFUNC_TWOSMULTIPATCHTRANS, COLDRAWFUNC_FOG, COLDRAWFUNC_MAX diff --git a/src/v_video.c b/src/v_video.c index 9e1bac2e5ec417d585957d8fc788ceb58ec054c1..cb7db487e921b88e50fd0b6d97a6d3f631841c90 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -506,7 +506,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; INT32 dup; - const column_t *column; + column_t *column; UINT8 *desttop, *dest, *deststart, *destend; const UINT8 *source, *deststop; fixed_t pwidth; // patch width @@ -686,12 +686,12 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (!(scrn & V_SCALEPATCHMASK)) { // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) - if (x == 0 && patch->width == BASEVIDWIDTH && y == 0 && patch->height == BASEVIDHEIGHT) + if (!v_translevel && x == 0 && patch->width == BASEVIDWIDTH && y == 0 && patch->height == BASEVIDHEIGHT) { - column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[0])); - if (!column->topdelta) + column = &patch->columns[0]; + if (column->num_posts && !column->posts[0].topdelta) { - source = (const UINT8 *)(column) + 3; + source = column->pixels; V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, source[0]); } } @@ -741,7 +741,6 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop++) { - INT32 topdelta, prevdelta = -1; if (scrn & V_FLIP) // offx is measured from right edge instead of left { if (x+pwidth-offx < 0) // don't draw off the left of the screen (WRAP PREVENTION) @@ -756,27 +755,24 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (x+offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) break; } - column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); - while (column->topdelta != 0xff) + column = &patch->columns[col>>FRACBITS]; + + for (unsigned i = 0; i < column->num_posts; i++) { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; + post_t *post = &column->posts[i]; + source = column->pixels + post->data_offset; dest = desttop; if (scrn & V_FLIP) dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<<FRACBITS,vdup))*vid.width; + dest += FixedInt(FixedMul(post->topdelta<<FRACBITS,vdup))*vid.width; - for (ofs = 0; dest < deststop && (ofs>>FRACBITS) < column->length; ofs += rowfrac) + for (ofs = 0; dest < deststop && (size_t)(ofs>>FRACBITS) < post->length; ofs += rowfrac) { if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } - column = (const column_t *)((const UINT8 *)column + column->length + 4); } } } @@ -791,7 +787,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; INT32 dup; - const column_t *column; + column_t *column; UINT8 *desttop, *dest; const UINT8 *source, *deststop; @@ -1020,20 +1016,18 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN for (col = sx; (col>>FRACBITS) < patch->width && (col - sx) < w; col += colfrac, ++x, desttop++) { - INT32 topdelta, prevdelta = -1; if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION) continue; if (x >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) break; - column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); - while (column->topdelta != 0xff) + column = &patch->columns[col>>FRACBITS]; + + for (unsigned i = 0; i < column->num_posts; i++) { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; + post_t *post = &column->posts[i]; + INT32 topdelta = post->topdelta; + source = column->pixels + post->data_offset; dest = desttop; if ((topdelta<<FRACBITS)-sy > 0) { @@ -1043,13 +1037,12 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN else ofs = sy-(topdelta<<FRACBITS); - for (; dest < deststop && (ofs>>FRACBITS) < column->length && ((ofs - sy) + (topdelta<<FRACBITS)) < h; ofs += rowfrac) + for (; dest < deststop && (size_t)(ofs>>FRACBITS) < post->length && ((ofs - sy) + (topdelta<<FRACBITS)) < h; ofs += rowfrac) { if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } - column = (const column_t *)((const UINT8 *)column + column->length + 4); } } } @@ -1101,61 +1094,6 @@ void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const } } -static void V_BlitScaledPic(INT32 px1, INT32 py1, INT32 scrn, pic_t *pic); -// Draw a linear pic, scaled, TOTALLY CRAP CODE!!! OPTIMISE AND ASM!! -// -void V_DrawScaledPic(INT32 rx1, INT32 ry1, INT32 scrn, INT32 lumpnum) -{ -#ifdef HWRENDER - if (rendermode != render_soft) - { - HWR_DrawPic(rx1, ry1, lumpnum); - return; - } -#endif - - V_BlitScaledPic(rx1, ry1, scrn, W_CacheLumpNum(lumpnum, PU_CACHE)); -} - -static void V_BlitScaledPic(INT32 rx1, INT32 ry1, INT32 scrn, pic_t * pic) -{ - INT32 dupx, dupy; - INT32 x, y; - UINT8 *src, *dest; - INT32 width, height; - - width = SHORT(pic->width); - height = SHORT(pic->height); - scrn &= V_PARAMMASK; - - if (pic->mode != 0) - { - CONS_Debug(DBG_RENDER, "pic mode %d not supported in Software\n", pic->mode); - return; - } - - dest = screens[scrn] + max(0, ry1 * vid.width) + max(0, rx1); - // y cliping to the screen - if (ry1 + height * vid.dup >= vid.width) - height = (vid.width - ry1) / vid.dup - 1; - // WARNING no x clipping (not needed for the moment) - - for (y = max(0, -ry1 / vid.dup); y < height; y++) - { - for (dupy = vid.dup; dupy; dupy--) - { - src = pic->data + y * width; - for (x = 0; x < width; x++) - { - for (dupx = vid.dup; dupx; dupx--) - *dest++ = *src; - src++; - } - dest += vid.width - vid.dup * width; - } - } -} - // // Fills a box of pixels with a single color, NOTE: scaled to screen size // diff --git a/src/v_video.h b/src/v_video.h index 80936f3ee9f6f6585b0a3d4208a43dda266e8635..5a3df5a4499588df56e4a6d152f1445f82a60926 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -178,9 +178,6 @@ void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 ski // Draw a linear block of pixels into the view buffer. void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const UINT8 *src); -// draw a pic_t, SCALED -void V_DrawScaledPic (INT32 px1, INT32 py1, INT32 scrn, INT32 lumpnum); - // fill a box with a single color void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c); void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c); diff --git a/src/w_wad.c b/src/w_wad.c index ff1af6ee1a553dec87b96a625c4735086173ecdc..3a50646930e984762ffb720f2c2022edac075e33 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1351,6 +1351,74 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump) return i; } +void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps) +{ + size_t name_length = strlen(name); + lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo; + + UINT16 capacity = list_capacity ? *list_capacity : 0; + UINT16 count = *numlumps; + + for (UINT16 i = 0; i < wadfiles[wad]->numlumps; i++, lump_p++) + { + if (strnicmp(name, lump_p->fullname, name_length) == 0) + { + if (strlen(lump_p->fullname) > name_length + && lump_p->longname[0] != '\0') + { + if (!capacity || count >= capacity) + { + capacity = capacity ? (capacity * 2) : 16; + *list = Z_Realloc(*list, capacity * sizeof(UINT32), PU_STATIC, NULL); + } + + (*list)[count] = (wad << 16) + i; + count++; + } + } + } + + if (list_capacity) + (*list_capacity) = capacity; + (*numlumps) = count; +} + +void W_GetFolderLumps(const char *name, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps) +{ + for (UINT16 i = 0; i < numwadfiles; i++) + W_GetFolderLumpsPwad(name, i, list, list_capacity, numlumps); +} + +UINT32 W_CountFolderLumpsPwad(const char *name, UINT16 wad) +{ + size_t name_length = strlen(name); + lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo; + + UINT32 count = 0; + + for (UINT16 i = 0; i < wadfiles[wad]->numlumps; i++, lump_p++) + { + if (strnicmp(name, lump_p->fullname, name_length) == 0) + { + if (strlen(lump_p->fullname) > name_length + && lump_p->longname[0] != '\0') + count++; + } + } + + return count; +} + +UINT32 W_CountFolderLumps(const char *name) +{ + UINT32 count = 0; + + for (UINT16 i = 0; i < numwadfiles; i++) + count += W_CountFolderLumpsPwad(name, i); + + return count; +} + // In a PK3 type of resource file, it looks for an entry with the specified full name. // Returns lump position in PK3's lumpinfo, or INT16_MAX if not found. UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump) @@ -1700,6 +1768,10 @@ void zerr(int ret) } #endif +#ifdef NO_PNG_LUMPS +#define Picture_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename) +#endif + /** Reads bytes from the head of a lump. * Note: If the lump is compressed, the whole thing has to be read anyway. * @@ -1780,10 +1852,6 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si bytesread = fread(dest, 1, size, handle); if (wadfiles[wad]->type == RET_FOLDER) fclose(handle); -#ifdef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)dest, bytesread)) - Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename); -#endif return bytesread; case CM_LZF: // Is it LZF compressed? Used by ZWADs. { @@ -1819,10 +1887,6 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si M_Memcpy(dest, decData + offset, size); Z_Free(rawData); Z_Free(decData); -#ifdef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)dest, size)) - Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename); -#endif return size; #else //I_Error("ZWAD files not supported on this platform."); @@ -1882,10 +1946,6 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si Z_Free(rawData); Z_Free(decData); -#ifdef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)dest, size)) - Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename); -#endif return size; } #endif @@ -2004,8 +2064,7 @@ boolean W_IsLumpCached(lumpnum_t lumpnum, void *ptr) // If a patch is already cached return true, otherwise // return false. // -// no outside code uses the PWAD form, for now -static boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) +boolean W_IsPatchCachedPwad(UINT16 wad, UINT16 lump, void *ptr) { void *lcache; @@ -2027,7 +2086,7 @@ static boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) boolean W_IsPatchCached(lumpnum_t lumpnum, void *ptr) { - return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); + return W_IsPatchCachedPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); } // ========================================================================== @@ -2042,18 +2101,10 @@ void *W_CacheLumpName(const char *name, INT32 tag) // CACHING OF GRAPHIC PATCH RESOURCES // ========================================================================== -// Graphic 'patches' are loaded, and if necessary, converted into the format -// the most useful for the current rendermode. For software renderer, the -// graphic patches are kept as is. For the hardware renderer, graphic patches -// are 'unpacked', and are kept into the cache in that unpacked format, and -// the heap memory cache then acts as a 'level 2' cache just after the -// graphics card memory. - // // Cache a patch into heap memory, convert the patch format as necessary // - -void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) +static void *W_GetPatchPwad(UINT16 wad, UINT16 lump, INT32 tag) { lumpcache_t *lumpcache = NULL; @@ -2071,15 +2122,25 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0); ptr = lumpdata; -#ifndef NO_PNG_LUMPS if (Picture_IsLumpPNG((UINT8 *)lumpdata, len)) - ptr = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, len, &len, 0); + { +#ifndef NO_PNG_LUMPS + ptr = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, len, &len, 0); + Z_ChangeTag(ptr, tag); + Z_SetUser(ptr, &lumpcache[lump]); + Z_Free(lumpdata); + return lumpcache[lump]; +#else + Picture_ThrowPNGError(W_CheckNameForNumPwad(wad, lump), wadfiles[wad]->filename); + return NULL; #endif + } - dest = Z_Calloc(sizeof(patch_t), tag, &lumpcache[lump]); - Patch_Create(ptr, len, dest); - + dest = Patch_CreateFromDoomPatch(ptr); Z_Free(ptr); + + Z_ChangeTag(dest, tag); + Z_SetUser(dest, &lumpcache[lump]); } else Z_ChangeTag(lumpcache[lump], tag); @@ -2087,30 +2148,19 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) return lumpcache[lump]; } -void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag) -{ - return W_CacheSoftwarePatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); -} - void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { - patch_t *patch; - if (!TestValidLump(wad, lump)) return NULL; - patch = W_CacheSoftwarePatchNumPwad(wad, lump, tag); + patch_t *patch = W_GetPatchPwad(wad, lump, tag); #ifdef HWRENDER - // Software-only compile cache the data without conversion - if (rendermode == render_soft || rendermode == render_none) + if (rendermode == render_opengl) + Patch_CreateGL(patch); #endif - return (void *)patch; -#ifdef HWRENDER - Patch_CreateGL(patch); return (void *)patch; -#endif } void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) @@ -2118,6 +2168,71 @@ void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) return W_CachePatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); } +void *W_GetCachedPatchNumPwad(UINT16 wad, UINT16 lump) +{ + if (!TestValidLump(wad, lump)) + return NULL; + + return wadfiles[wad]->patchcache[lump]; +} + +boolean W_ReadPatchHeaderPwad(UINT16 wadnum, UINT16 lumpnum, INT16 *width, INT16 *height, INT16 *topoffset, INT16 *leftoffset) +{ + UINT8 header[PNG_HEADER_SIZE]; + + if (!TestValidLump(wadnum, lumpnum)) + return false; + + W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0); + + size_t len = W_LumpLengthPwad(wadnum, lumpnum); + + if (Picture_IsLumpPNG(header, len)) + { +#ifndef NO_PNG_LUMPS + UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + + INT32 pwidth = 0, pheight = 0; + + if (!Picture_PNGDimensions(png, &pwidth, &pheight, topoffset, leftoffset, len)) + { + Z_Free(png); + return false; + } + + *width = (INT16)pwidth; + *height = (INT16)pheight; + + Z_Free(png); + + return true; +#else + Picture_ThrowPNGError(W_CheckNameForNumPwad(wadnum, lumpnum), wadfiles[wadnum]->filename); + + return false; +#endif + } + + softwarepatch_t patch; + + if (!W_ReadLumpHeaderPwad(wadnum, lumpnum, &patch, sizeof(INT16) * 4, 0)) + return false; + + *width = SHORT(patch.width); + *height = SHORT(patch.height); + if (topoffset) + *topoffset = SHORT(patch.topoffset); + if (leftoffset) + *leftoffset = SHORT(patch.leftoffset); + + return true; +} + +boolean W_ReadPatchHeader(lumpnum_t lumpnum, INT16 *width, INT16 *height, INT16 *topoffset, INT16 *leftoffset) +{ + return W_ReadPatchHeaderPwad(WADFILENUM(lumpnum), LUMPNUM(lumpnum), width, height, topoffset, leftoffset); +} + void W_UnlockCachedPatch(void *patch) { if (!patch) diff --git a/src/w_wad.h b/src/w_wad.h index ffb9095ba21c9e1d79049adadaa893953b097260..e043e4d62c82f061ce505c4ce6b6a2298d48a4ec 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -181,6 +181,11 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump); +void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps); +void W_GetFolderLumps(const char *name, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps); +UINT32 W_CountFolderLumpsPwad(const char *name, UINT16 wad); +UINT32 W_CountFolderLumps(const char *name); + lumpnum_t W_CheckNumForMap(const char *name); lumpnum_t W_CheckNumForName(const char *name); lumpnum_t W_CheckNumForLongName(const char *name); @@ -210,20 +215,18 @@ void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag); boolean W_IsLumpCached(lumpnum_t lump, void *ptr); boolean W_IsPatchCached(lumpnum_t lump, void *ptr); +boolean W_IsPatchCachedPwad(UINT16 wad, UINT16 lump, void *ptr); void *W_CacheLumpName(const char *name, INT32 tag); void *W_CachePatchName(const char *name, INT32 tag); void *W_CachePatchLongName(const char *name, INT32 tag); -// Returns either a Software patch, or an OpenGL patch. -// Performs any necessary conversions from PNG images. void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); +void *W_GetCachedPatchNumPwad(UINT16 wad, UINT16 lump); -// Returns a Software patch. -// Performs any necessary conversions from PNG images. -void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); -void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag); +boolean W_ReadPatchHeaderPwad(UINT16 wadnum, UINT16 lumpnum, INT16 *width, INT16 *height, INT16 *topoffset, INT16 *leftoffset); +boolean W_ReadPatchHeader(lumpnum_t lumpnum, INT16 *width, INT16 *height, INT16 *topoffset, INT16 *leftoffset); void W_UnlockCachedPatch(void *patch);