From be3592684379ef553b2c4ae2e0e233e85e98b5c9 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Fri, 27 Jun 2025 16:32:25 +0200 Subject: [PATCH] Add W_CheckNumForMarkers, clean up lump validation Fixes many cases of invalid startlumps, so validation is now actually done only when PARANOIA is defined The W_CheckNumFor* functions allow startlump == numlumps, to make iteration less frustrating --- src/p_setup.c | 43 +++---- src/r_skins.c | 4 +- src/r_textures.c | 298 +++++++++++++++++++++-------------------------- src/r_things.cpp | 43 ++----- src/w_wad.c | 217 +++++++++++++++------------------- src/w_wad.h | 4 +- 6 files changed, 253 insertions(+), 356 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 08f5564b4..c650b7954 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -9027,11 +9027,14 @@ boolean P_RunSOC(const char *socfilename) // Auxiliary function for PK3 loading - looks for sound replacements. // NOTE: it does not really add any new sound entry or anything. -static void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 end, size_t *sreplaces) +static void P_LoadSoundsRange(UINT16 wadnum, size_t *sreplaces) { sfxenum_t j; - UINT16 i; - for (i = first; i < end; i++) + UINT16 i, end; + if (!W_CheckNumForMarkers((const char *[]){"Sounds/"}, 1, wadnum, &i, &end)) + return; + + for (; i < end; i++) { // Let's check whether it's replacing an existing sound or it's a brand new one. const char *name = W_CheckNameForNumPwad(wadnum, i); @@ -9055,10 +9058,13 @@ static void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 end, size_t *s // Auxiliary function for PK3 loading - looks for music and music replacements. // NOTE: does nothing but print debug messages. The code is handled somewhere else. -static void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 end, size_t *digmreplaces, size_t *mreplaces) +static void P_LoadMusicsRange(UINT16 wadnum, size_t *digmreplaces, size_t *mreplaces) { - UINT16 i; - for (i = first; i < end; i++) + UINT16 i, end; + if (!W_CheckNumForMarkers((const char *[]){"Music/"}, 1, wadnum, &i, &end)) + return; + + for (; i < end; i++) { const char *name = W_CheckNameForNumPwad(wadnum, i); if (name[0] == 'O' && name[1] == '_') @@ -9236,12 +9242,6 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, wadcompat_t compat) size_t sreplaces = 0, mreplaces = 0, digmreplaces = 0; UINT16 numlumps, wadnum; - // Vars to help us with the position start and amount of each resource type. - // Useful for PK3s since they use folders. - // WADs use markers for some resources, but others such as sounds are checked lump-by-lump anyway. - UINT16 sfxPos, sfxEnd; - UINT16 musPos, musEnd; - // Init file. if ((numlumps = W_InitFile(wadfilename, false, false, compat)) == LUMPERROR) { @@ -9261,23 +9261,8 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, wadcompat_t compat) } partadd_stage = 0; - switch(wadfiles[wadnum]->type) - { - case RET_PK3: - sfxPos = W_CheckNumForFolderStartPK3("Sounds/", wadnum, 0); - sfxEnd = W_CheckNumForFolderEndPK3("Sounds/", wadnum, sfxPos); - musPos = W_CheckNumForFolderStartPK3("Music/", wadnum, 0); - musEnd = W_CheckNumForFolderEndPK3("Music/", wadnum, musPos); - break; - - default: - sfxPos = musPos = 0; - sfxEnd = musEnd = numlumps; - break; - } - - P_LoadSoundsRange(wadnum, sfxPos, sfxEnd, &sreplaces); - P_LoadMusicsRange(wadnum, musPos, musEnd, &digmreplaces, &mreplaces); + P_LoadSoundsRange(wadnum, &sreplaces); + P_LoadMusicsRange(wadnum, &digmreplaces, &mreplaces); if (!devparm && sreplaces) CONS_Printf(M_GetText("%s sounds replaced\n"), sizeu1(sreplaces)); diff --git a/src/r_skins.c b/src/r_skins.c index cb6031ab1..ff05f1655 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -648,7 +648,7 @@ void R_AddSkins(UINT16 wadnum) // search for all skin markers in pwad // - while ((lump = W_CheckNumForNamePrefixPwad("S_SKIN", 6, wadnum, lastlump)) != LUMPERROR) + while (lastlump != LUMPERROR && (lump = W_CheckNumForNamePrefixPwad("S_SKIN", 6, wadnum, lastlump)) != LUMPERROR) { // advance by default lastlump = lump + 1; @@ -820,7 +820,7 @@ void R_PatchSkins(UINT16 wadnum) // search for all skin patch markers in pwad // - while ((lump = W_CheckNumForNamePrefixPwad("P_SKIN", 6, wadnum, lastlump)) != LUMPERROR) + while (lastlump != LUMPERROR && (lump = W_CheckNumForNamePrefixPwad("P_SKIN", 6, wadnum, lastlump)) != LUMPERROR) { INT32 skinnum = 0; diff --git a/src/r_textures.c b/src/r_textures.c index 1c9f13759..1d1020f5a 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -1117,6 +1117,11 @@ void R_FlushTextureCache(void) int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum); void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); +static const char *flatmarkers[] = { + "Flats/", + "F_START", "F_END", +}; + static INT32 Rloadflats (INT32 i, INT32 w) { @@ -1126,81 +1131,74 @@ Rloadflats (INT32 i, INT32 w) texpatch_t *patch; UINT8 header[PNG_HEADER_SIZE]; - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); - } - else - { - texstart = W_CheckNumForLongNamePwad("F_START", (UINT16)w, 0); - if (texstart != LUMPERROR) texstart++; - texend = W_CheckNumForLongNamePwad("F_END", (UINT16)w, texstart); - } + if (!W_CheckNumForMarkers(flatmarkers, sizeof(flatmarkers)/sizeof(*flatmarkers), (UINT16)w, &texstart, &texend)) + return i; - if (!( texstart == LUMPERROR || texend == LUMPERROR )) + // Work through each lump between the markers in the WAD. + for (j = 0; j < (texend - texstart); 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; + + if (wadfiles[w]->type == RET_PK3) { - UINT16 wadnum = (UINT16)w; - lumpnum_t lumpnum = texstart + j; + if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder + continue; // If it is then SKIP IT + } - if (wadfiles[w]->type == RET_PK3) - { - 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_FlatDimensionsFromLumpSize(lumplength); - size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); - size_t flatsize = R_FlatDimensionsFromLumpSize(lumplength); + //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); - //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); - - // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); - texture->hash = quickncasehash(texture->name, 8); + // Set texture properties. + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + texture->hash = quickncasehash(texture->name, 8); #ifndef NO_PNG_LUMPS - W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0); + W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0); - if (Picture_IsLumpPNG(header, 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); - } - else -#endif - texture->width = texture->height = flatsize; - - texture->type = TEXTURETYPE_FLAT; - texture->patchcount = 1; - texture->holes = false; - texture->flip = 0; - texture->terrainID = K_GetTerrainIDForTextureName(texture->name); - - // Allocate information for the texture's patches. - patch = &texture->patches[0]; - - patch->originx = patch->originy = 0; - patch->wad = (UINT16)w; - patch->lump = texstart + j; - patch->flip = 0; - - texturewidth[i] = texture->width; - textureheight[i] = texture->height << FRACBITS; - i++; + if (Picture_IsLumpPNG(header, 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); } + else +#endif + texture->width = texture->height = flatsize; + + texture->type = TEXTURETYPE_FLAT; + texture->patchcount = 1; + texture->holes = false; + texture->flip = 0; + texture->terrainID = K_GetTerrainIDForTextureName(texture->name); + + // Allocate information for the texture's patches. + patch = &texture->patches[0]; + + patch->originx = patch->originy = 0; + patch->wad = (UINT16)w; + patch->lump = texstart + j; + patch->flip = 0; + + texturewidth[i] = texture->width; + textureheight[i] = texture->height << FRACBITS; + i++; } return i; } +static const char *texturemarkers[] = { + "Textures/", + "TX_START", "TX_END", +}; + static INT32 Rloadtextures (INT32 i, INT32 w) { @@ -1211,136 +1209,108 @@ Rloadtextures (INT32 i, INT32 w) softwarepatch_t patchlump; // Get the lump numbers for the markers in the WAD, if they exist. + if (!W_CheckNumForMarkers(texturemarkers, sizeof(texturemarkers)/sizeof(*texturemarkers), (UINT16)w, &texstart, &texend)) + return i; + if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); - texturesLumpPos = W_CheckNumForLongNamePwad("TEXTURES", (UINT16)w, 0); - while (texturesLumpPos != LUMPERROR) - { + for (texturesLumpPos = 0; (texturesLumpPos = W_CheckNumForLongNamePwad("TEXTURES", (UINT16)w, texturesLumpPos)) != LUMPERROR; texturesLumpPos++) R_ParseTEXTURESLump(w, texturesLumpPos, &i); - texturesLumpPos = W_CheckNumForLongNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); - } - } else { - texstart = W_CheckNumForLongNamePwad("TX_START", (UINT16)w, 0); - if (texstart != LUMPERROR) texstart++; - texend = W_CheckNumForLongNamePwad("TX_END", (UINT16)w, 0); texturesLumpPos = W_CheckNumForLongNamePwad("TEXTURES", (UINT16)w, 0); if (texturesLumpPos != LUMPERROR) R_ParseTEXTURESLump(w, texturesLumpPos, &i); } - if (!( texstart == LUMPERROR || texend == LUMPERROR )) + // Work through each lump between the markers in the WAD. + for (j = 0; j < (texend - texstart); 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; +#ifndef NO_PNG_LUMPS + size_t lumplength; +#endif + + if (wadfiles[w]->type == RET_PK3) { - UINT16 wadnum = (UINT16)w; - lumpnum_t lumpnum = texstart + j; -#ifndef NO_PNG_LUMPS - size_t lumplength; -#endif - - if (wadfiles[w]->type == RET_PK3) - { - 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 - - //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); - - // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); - texture->hash = quickncasehash(texture->name, 8); - -#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); - } - - texture->type = TEXTURETYPE_SINGLEPATCH; - texture->patchcount = 1; - texture->holes = false; - texture->flip = 0; - texture->terrainID = K_GetTerrainIDForTextureName(texture->name); - - // Allocate information for the texture's patches. - patch = &texture->patches[0]; - - patch->originx = patch->originy = 0; - patch->wad = (UINT16)w; - patch->lump = texstart + j; - patch->flip = 0; - - texturewidth[i] = texture->width; - textureheight[i] = texture->height << FRACBITS; - i++; + 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 + + //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); + + // Set texture properties. + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + texture->hash = quickncasehash(texture->name, 8); + +#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); + } + + texture->type = TEXTURETYPE_SINGLEPATCH; + texture->patchcount = 1; + texture->holes = false; + texture->flip = 0; + texture->terrainID = K_GetTerrainIDForTextureName(texture->name); + + // Allocate information for the texture's patches. + patch = &texture->patches[0]; + + patch->originx = patch->originy = 0; + patch->wad = (UINT16)w; + patch->lump = texstart + j; + patch->flip = 0; + + texturewidth[i] = texture->width; + textureheight[i] = texture->height << FRACBITS; + i++; } return i; } -static INT32 -count_range -( const char * marker_start, - const char * marker_end, - const char * folder, - UINT16 wadnum) +static INT32 count_range(const char *markers[], size_t nummarkers, UINT16 wadnum) { UINT16 j; UINT16 texstart, texend; INT32 count = 0; // Count flats + if (!W_CheckNumForMarkers(markers, nummarkers, wadnum, &texstart, &texend)) + return count; + + // PK3s have subfolders, so we can't just make a simple sum if (wadfiles[wadnum]->type == RET_PK3) { - texstart = W_CheckNumForFolderStartPK3(folder, wadnum, 0); - texend = W_CheckNumForFolderEndPK3(folder, wadnum, texstart); - } - else - { - texstart = W_CheckNumForLongNamePwad(marker_start, wadnum, 0); - if (texstart != LUMPERROR) texstart++; - texend = W_CheckNumForLongNamePwad(marker_end, wadnum, texstart); - } - - if (texstart != LUMPERROR && texend != LUMPERROR) - { - // PK3s have subfolders, so we can't just make a simple sum - if (wadfiles[wadnum]->type == RET_PK3) + for (j = texstart; j < texend; j++) { - 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 - { - count += (texend - texstart); + if (!W_IsLumpFolder(wadnum, j)) // Check if lump is a folder; if not, then count it + count++; } } + else // Add all the textures between markers + { + count += (texend - texstart); + } return count; } @@ -1358,14 +1328,14 @@ 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. - count += count_range("F_START", "F_END", "flats/", wadnum); + count += count_range(flatmarkers, sizeof(flatmarkers)/sizeof(*flatmarkers), wadnum); // Count the textures from TEXTURES lumps for (texturesLumpPos = 0; (texturesLumpPos = W_CheckNumForLongNamePwad("TEXTURES", wadnum, texturesLumpPos)) != LUMPERROR; texturesLumpPos++) count += R_CountTexturesInTEXTURESLump(wadnum, texturesLumpPos); // Count single-patch textures - count += count_range("TX_START", "TX_END", "textures/", wadnum); + count += count_range(texturemarkers, sizeof(texturemarkers)/sizeof(*texturemarkers), wadnum); return count; } diff --git a/src/r_things.cpp b/src/r_things.cpp index d9b73aa3a..9475a6f4a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -489,6 +489,12 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 return true; } +static const char *spritemarkers[] = { + "Sprites/", + "S_START", "S_END", + "SS_START", "SS_END", // deutex compatib. +}; + // // Search for sprites replacements in a wad whose names are in namelist // @@ -498,47 +504,12 @@ void R_AddSpriteDefs(UINT16 wadnum) UINT16 start, end; char wadname[MAX_WADPATH]; - // Find the sprites section in this resource file. - switch (wadfiles[wadnum]->type) - { - case RET_WAD: - start = W_CheckNumForLongNamePwad("S_START", wadnum, 0); - if (start == LUMPERROR) - start = W_CheckNumForLongNamePwad("SS_START", wadnum, 0); //deutex compatib. - if (start != LUMPERROR) start++; - - end = W_CheckNumForLongNamePwad("S_END", wadnum, start); - if (end == LUMPERROR) - end = W_CheckNumForLongNamePwad("SS_END", wadnum, start); //deutex compatib. - break; - case RET_PK3: - start = W_CheckNumForFolderStartPK3("Sprites/", wadnum, 0); - end = W_CheckNumForFolderEndPK3("Sprites/", wadnum, start); - break; - default: - return; - } - - if (start == LUMPERROR) - { - // ignore skin wads (we don't want skin sprites interfering with vanilla sprites) - // G: DON'T ignore skin wads. this check did nothing because it incorrectly checked for UINT16_MAX instead of INT16_MAX - // plus, this didn't exist in kart, so it might break old WADs... - /* - if (W_CheckNumForLongNamePwad("S_SKIN", wadnum, 0) != LUMPERROR) - return; - */ - - start = 0; //let say S_START is lump 0 - } - - if (end == LUMPERROR || start >= end) + if (!W_CheckNumForMarkers(spritemarkers, sizeof(spritemarkers)/sizeof(*spritemarkers), wadnum, &start, &end)) { CONS_Debug(DBG_SETUP, "no sprites in pwad %d\n", wadnum); return; } - // // scan through lumps, for each sprite, find all the sprite frames // diff --git a/src/w_wad.c b/src/w_wad.c index 2eff63e77..b599c271d 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -332,23 +332,15 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile) { LUA_LoadLump(wadnum, posStart, true); } - else + else if (W_CheckNumForMarkers((const char *[]){"Lua/"}, 1, wadnum, &posStart, &posEnd)) { - posStart = W_CheckNumForFolderStartPK3("Lua/", wadnum, 0); - if (posStart != LUMPERROR) - { - posEnd = W_CheckNumForFolderEndPK3("Lua/", wadnum, posStart); - for (; posStart < posEnd; posStart++) - LUA_LoadLump(wadnum, posStart, true); - } + for (; posStart < posEnd; posStart++) + LUA_LoadLump(wadnum, posStart, true); } - posStart = W_CheckNumForFolderStartPK3("SOC/", wadnum, 0); - if (posStart != LUMPERROR) + if (W_CheckNumForMarkers((const char *[]){"SOC/"}, 1, wadnum, &posStart, &posEnd)) { - posEnd = W_CheckNumForFolderEndPK3("SOC/", wadnum, posStart); - - for(; posStart < posEnd; posStart++) + for (; posStart < posEnd; posStart++) { CONS_Printf(M_GetText("Loading SOC from %s|%s\n"), wadfiles[wadnum]->filename, W_CheckFullNameForNumPwad(wadnum, posStart)); DEH_LoadDehackedLumpPwad(wadnum, posStart, mainfile); @@ -1099,22 +1091,25 @@ INT32 W_InitMultipleFiles(char **filenames, boolean addons) return overallrc; } -// check for a valid lump number -// lump cannot be asserted because some callers pass LUMPERROR, -// and most W_ functions previously always passed 0 for lump... -static boolean TestValidLump(UINT16 wad, UINT16 lump) -{ - I_Assert(wad < numwadfiles); - return lump < wadfiles[wad]->numlumps; -} +#ifdef PARANOIA +#define TESTVALID(wad, lump) \ + if (wad >= numwadfiles || lump >= wadfiles[wad]->numlumps) \ + I_Error("Invalid lump number %04x:%04x", wad, lump); + +// allows one past the end of the lump array to make iteration less hellish +#define TESTVALIDEND(wad, lump) \ + if (wad >= numwadfiles || lump > wadfiles[wad]->numlumps) \ + I_Error("Invalid lump number %04x:%04x", wad, lump); +#else +#define TESTVALID(wad, lump) +#define TESTVALIDEND(wad, lump) +#endif // NOTE: this actually returns the longname, but since nothing relies on // the 8-char truncation, i thought i'd save some effort :^) const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump) { - if (!TestValidLump(wad, lump)) - return NULL; - + TESTVALID(wad, lump) return strbuf_get(lumpnamebuf, wadfiles[wad]->lumpinfo[lump].longname); } @@ -1125,9 +1120,7 @@ const char *W_CheckNameForNum(lumpnum_t lumpnum) const char *W_CheckFullNameForNumPwad(UINT16 wad, UINT16 lump) { - if (!TestValidLump(wad, lump)) - return NULL; - + TESTVALID(wad, lump) return strbuf_get(lumpnamebuf, wadfiles[wad]->lumpinfo[lump].fullname); } @@ -1146,21 +1139,17 @@ UINT16 W_FindNextEmptyInPwad(UINT16 wad, UINT16 startlump) { UINT16 i; - if (!TestValidLump(wad, startlump)) - return LUMPERROR; + TESTVALIDEND(wad, startlump) // // scan forward // start at 'startlump', useful parameter when there are multiple // resources with the same name // - if (startlump < wadfiles[wad]->numlumps) - { - lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; - for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) - if (!lump_p->size) - return i; - } + lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + if (!lump_p->size) + return i; // not found. return LUMPERROR; @@ -1202,8 +1191,7 @@ UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump) UINT32 hash; char *up = uname; - if (!TestValidLump(wad, startlump)) - return LUMPERROR; + TESTVALIDEND(wad, startlump) while (*name) *up++ = toupper(*name++); @@ -1219,8 +1207,7 @@ UINT16 W_CheckNumForNamePrefixPwad(const char *name, size_t namelen, UINT16 wad, UINT16 i; lumpinfo_t *lump_p; - if (!TestValidLump(wad, startlump)) - return LUMPERROR; + TESTVALIDEND(wad, startlump) // scan forward, start at lump_p = wadfiles[wad]->lumpinfo + startlump; @@ -1238,8 +1225,7 @@ UINT16 W_CheckNumForNameMultiPrefixPwad(const lumpprefixes_t *prefixes, size_t n size_t j; lumpinfo_t *lump_p; - if (!TestValidLump(wad, startlump)) - return LUMPERROR; + TESTVALIDEND(wad, startlump) // scan forward, start at lump_p = wadfiles[wad]->lumpinfo + startlump; @@ -1251,39 +1237,50 @@ UINT16 W_CheckNumForNameMultiPrefixPwad(const lumpprefixes_t *prefixes, size_t n return LUMPERROR; // not found } -// Look for the first lump from a folder. -UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump) +// finds the range [start:end) of lumps within the given PK3 folder or (optionally) WAD marker names +// if wadnum is a WAD but no markers are specified, yields 0 and wad->numlumps +// returns true and sets ostart/oend if lumps were found +// [0] = PK3 folder [1], [2] = WAD start/end markers [3], [4] = secondary WAD start/end markers etc... +boolean W_CheckNumForMarkers(const char *markers[], size_t nummarkers, UINT16 wad, UINT16 *ostart, UINT16 *oend) { - size_t name_length; - INT32 i; - lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; - name_length = strlen(name); - for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + INT32 start, end; + if (wadfiles[wad]->type == RET_PK3) { - if (strnicmp(name, strbuf_get(lumpnamebuf, lump_p->fullname), name_length) == 0) + size_t name_length = strlen(markers[0]); + for (start = 0; start < wadfiles[wad]->numlumps; start++) + if (!strncasecmp(markers[0], W_CheckFullNameForNumPwad(wad, start), name_length)) + break; + if (start == wadfiles[wad]->numlumps) + return false; + for (end = start + 1; end < wadfiles[wad]->numlumps; end++) + if (strncasecmp(markers[0], W_CheckFullNameForNumPwad(wad, end), name_length)) + break; + } + else if (nummarkers == 1) + { + start = 0; + end = wadfiles[wad]->numlumps; + } + else + { + size_t i; + for (i = 1; i < nummarkers; i += 2) { - /* SLADE is special and puts a single directory entry. Skip that. */ - if (strlen(strbuf_get(lumpnamebuf, lump_p->fullname)) == name_length) - i++; + start = W_CheckNumForLongNamePwad(markers[i], wad, 0); + if (start == LUMPERROR || ++start == wadfiles[wad]->numlumps) + continue; + end = W_CheckNumForLongNamePwad(markers[i+1], wad, start); + if (end == LUMPERROR) + continue; break; } + if (i == nummarkers) + return false; } - return i; -} -// In a PK3 type of resource file, it looks for the next lumpinfo entry that doesn't share the specified pathfile. -// Useful for finding folder ends. -// Returns the position of the lumpinfo entry. -UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump) -{ - INT32 i; - lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; - for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) - { - if (strnicmp(name, strbuf_get(lumpnamebuf, lump_p->fullname), strlen(name))) - break; - } - return i; + *ostart = (UINT16)start; + *oend = (UINT16)end; + return true; } // In a PK3 type of resource file, it looks for an entry with the specified full name. @@ -1292,6 +1289,7 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump) { INT32 i; lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) { if (!strnicmp(name, strbuf_get(lumpnamebuf, lump_p->fullname), strlen(name))) @@ -1315,8 +1313,7 @@ lumpnum_t W_CheckNumForLongName(const char *name) char uname[MAXLUMPNAME+1]; char *up = uname; - if (name == NULL) - return LUMPERROR; + I_Assert(name != NULL); if (!*name) // some doofus gave us an empty string? return LUMPERROR; @@ -1388,19 +1385,7 @@ lumpnum_t W_CheckNumForMap(const char *name) for (i = numwadfiles - 1; i >= 0; i--) { UINT16 start, end; - switch (wadfiles[i]->type) - { - case RET_PK3: - start = W_CheckNumForFolderStartPK3("Maps/", i, 0); - end = W_CheckNumForFolderEndPK3("Maps/", i, start); - break; - default: - start = 0; - end = wadfiles[i]->numlumps; - break; - } - - if (start == LUMPERROR || end == LUMPERROR) + if (!W_CheckNumForMarkers((const char *[]){"Maps/"}, 1, i, &start, &end)) continue; retry: @@ -1454,31 +1439,22 @@ lumpnum_t W_GetNumForLongName(const char *name) lumpnum_t W_CheckNumForNameInFolder(const char *lump, const char *folder) { INT32 i; - lumpnum_t fsid, feid; + UINT16 fsid, feid; lumpnum_t check = LUMPERROR; // scan wad files backwards so patch lump files take precedence for (i = numwadfiles - 1; i >= 0; i--) { - if (wadfiles[i]->type == RET_PK3) + if (wadfiles[i]->type != RET_PK3) + continue; + + if (!W_CheckNumForMarkers(&folder, 1, i, &fsid, &feid)) + continue; + + check = W_CheckNumForLongNamePwad(lump, (UINT16)i, fsid); + if (check < feid) { - fsid = W_CheckNumForFolderStartPK3(folder, (UINT16)i, 0); - if (fsid == LUMPERROR) - { - continue; // Start doesn't exist? - } - - feid = W_CheckNumForFolderEndPK3(folder, (UINT16)i, fsid); - if (feid == LUMPERROR) - { - continue; // End doesn't exist? - } - - check = W_CheckNumForLongNamePwad(lump, (UINT16)i, fsid); - if (check < feid) - { - return (i<<16) + check; // found it, in our constraints - } + return (i<<16) + check; // found it, in our constraints } } @@ -1502,8 +1478,7 @@ UINT8 W_LumpExists(const char *name) size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump) { - if (!TestValidLump(wad, lump)) - return 0; + TESTVALID(wad, lump) return wadfiles[wad]->lumpinfo[lump].size; } @@ -1617,8 +1592,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si lumpinfo_t *l; FILE *handle; - if (!TestValidLump(wad,lump)) - return 0; + TESTVALID(wad, lump) lumpsize = wadfiles[wad]->lumpinfo[lump].size; // empty resource (usually markers like S_START, F_END ..) @@ -1782,8 +1756,7 @@ void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { lumpcache_t *lumpcache; - if (!TestValidLump(wad,lump)) - return NULL; + TESTVALID(wad, lump) lumpcache = wadfiles[wad]->lumpcache; if (!lumpcache[lump]) @@ -1815,8 +1788,7 @@ void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag) wad = WADFILENUM(lumpnum); lump = LUMPNUM(lumpnum); - if (!TestValidLump(wad,lump)) - return NULL; + TESTVALID(wad, lump) ptr = Z_Malloc(W_LumpLengthPwad(wad, lump), tag, NULL); W_ReadLumpHeaderPwad(wad, lump, ptr, 0, 0); // read the lump in full @@ -1835,8 +1807,7 @@ static inline boolean W_IsLumpCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) { void *lcache; - if (!TestValidLump(wad, lump)) - return false; + TESTVALID(wad, lump) lcache = wadfiles[wad]->lumpcache[lump]; @@ -1867,8 +1838,7 @@ static inline boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) { void *lcache; - if (!TestValidLump(wad, lump)) - return false; + TESTVALID(wad, lump) lcache = wadfiles[wad]->patchcache[lump]; @@ -1929,8 +1899,7 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { lumpcache_t *lumpcache = NULL; - if (!TestValidLump(wad, lump)) - return NULL; + TESTVALID(wad, lump) lumpcache = wadfiles[wad]->patchcache; @@ -1960,8 +1929,7 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { patch_t *patch; - if (!TestValidLump(wad, lump)) - return NULL; + TESTVALID(wad, lump) patch = W_CacheSoftwarePatchNumPwad(wad, lump, tag); @@ -2405,17 +2373,20 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum) { // Count number of lumps until the end of resource OR up until next 0-length lump. lumpnum_t lumppos = lumpnum + 1; - lumpnum_t lastlump = wadfiles[WADFILENUM(lumpnum)]->numlumps; + UINT16 wad = WADFILENUM(lumpnum); + UINT16 lastlump = wadfiles[wad]->numlumps; + // or the end of directory, for PK3 files if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3) { const char *fullname = W_CheckFullNameForNum(lumpnum); const char *dirend = strrchr(fullname, '/'); - char *dirname = malloc(dirend - fullname + 2); - strlcpy(dirname, fullname, dirend - fullname + 2); - lastlump = W_CheckNumForFolderEndPK3(dirname, WADFILENUM(lumpnum), lumpnum); - free(dirname); + size_t dirlen = dirend - fullname + 1; + for (lastlump = LUMPNUM(lumppos); lastlump < wadfiles[wad]->numlumps; lastlump++) + if (strnicmp(fullname, W_CheckFullNameForNumPwad(wad, lastlump), dirlen)) + break; } + for (i = LUMPNUM(lumppos); i < lastlump; i++, lumppos++, numlumps++) { if (W_LumpLength(lumppos) > 0) diff --git a/src/w_wad.h b/src/w_wad.h index f73d7d4cb..32436ba2f 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -127,9 +127,9 @@ UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump) UINT16 W_CheckNumForNamePrefixPwad(const char *name, size_t namelen, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForNameMultiPrefixPwad(const lumpprefixes_t *prefixes, size_t numprefixes, UINT16 wad, UINT16 startlump); +boolean W_CheckNumForMarkers(const char *markers[], size_t nummarkers, UINT16 wad, UINT16 *ostart, UINT16 *oend); + 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); lumpnum_t W_CheckNumForMap(const char *name); lumpnum_t W_CheckNumForLongName(const char *name);