diff --git a/src/p_setup.c b/src/p_setup.c index fab5429b8..e36c20a0a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4452,7 +4452,7 @@ boolean P_AddWadFile(const char *wadfilename) // Reload it all anyway, just in case they // added some textures but didn't insert a // TEXTURES/etc. list. - R_LoadTextures(); // numtexture changes + R_LoadTexturesPwad(wadnum); // numtexture changes // Reload ANIMDEFS P_InitPicAnims(); diff --git a/src/r_textures.c b/src/r_textures.c index 4ec110556..76e78f00e 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -926,27 +926,53 @@ Rloadtextures (INT32 i, INT32 w) return i; } -// -// R_LoadTextures -// Initializes the texture list with the textures from the world map. -// -void R_LoadTextures(void) +static INT32 +count_range +( const char * marker_start, + const char * marker_end, + const char * folder, + UINT16 wadnum) { - INT32 i, w; UINT16 j; - UINT16 texstart, texend, texturesLumpPos; + UINT16 texstart, texend; + INT32 count = 0; - // Free previous memory before numtextures change. - if (numtextures) + // Count flats + if (wadfiles[wadnum]->type == RET_PK3) { - for (i = 0; i < numtextures; i++) - { - Z_Free(textures[i]); - Z_Free(texturecache[i]); - } - Z_Free(texturetranslation); - Z_Free(textures); + texstart = W_CheckNumForFolderStartPK3(folder, wadnum, 0); + texend = W_CheckNumForFolderEndPK3(folder, wadnum, texstart); } + else + { + texstart = W_CheckNumForMarkerStartPwad(marker_start, wadnum, 0); + 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 (wadfiles[wadnum]->type == RET_PK3) + { + 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); + } + } + + return count; +} + +static INT32 R_CountTextures(UINT16 wadnum) +{ + UINT16 texturesLumpPos; + INT32 count = 0; // Load patches and textures. @@ -955,106 +981,76 @@ void R_LoadTextures(void) // the markers. // 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. - for (w = 0, numtextures = 0; w < numwadfiles; w++) - { + #ifdef WALLFLATS - // Count flats - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); - } - else - { - texstart = W_CheckNumForMarkerStartPwad("F_START", (UINT16)w, 0); - texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); - } + count += count_range("F_START", "F_END", "flats/", wadnum); +#endif - if (!( texstart == INT16_MAX || texend == INT16_MAX )) - { - // PK3s have subfolders, so we can't just make a simple sum - if (wadfiles[w]->type == RET_PK3) - { - for (j = texstart; j < texend; j++) - { - if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it - numtextures++; - } - } - else // Add all the textures between F_START and F_END - { - numtextures += (UINT32)(texend - texstart); - } - } -#endif/*WALLFLATS*/ + // Count the textures from TEXTURES lumps + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", wadnum, 0); - // Count the textures from TEXTURES lumps - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); - while (texturesLumpPos != INT16_MAX) - { - numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); - } - - // Count single-patch textures - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); - } - else - { - texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0); - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); - } - - if (texstart == INT16_MAX || texend == INT16_MAX) - continue; - - // PK3s have subfolders, so we can't just make a simple sum - if (wadfiles[w]->type == RET_PK3) - { - for (j = texstart; j < texend; j++) - { - if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it - numtextures++; - } - } - else // Add all the textures between TX_START and TX_END - { - numtextures += (UINT32)(texend - texstart); - } + while (texturesLumpPos != INT16_MAX) + { + count += R_CountTexturesInTEXTURESLump(wadnum, texturesLumpPos); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", wadnum, texturesLumpPos + 1); } - // If no textures found by this point, bomb out - if (!numtextures) - I_Error("No textures detected in any WADs!\n"); + // Count single-patch textures + count += count_range(TX_START, TX_END, "textures/", wadnum); + + return count; +} + +static void +recallocuser +( void * user, + size_t old, + size_t new) +{ + char *p = Z_Realloc(*(void**)user, + new, PU_STATIC, user); + + if (new > old) + memset(&p[old], 0, (new - old)); +} + +static void R_AllocateTextures(INT32 add) +{ + const INT32 newtextures = (numtextures + add); + const size_t newsize = newtextures * sizeof (void*); + const size_t oldsize = numtextures * sizeof (void*); + + INT32 i; // Allocate memory and initialize to 0 for all the textures we are initialising. - // There are actually 5 buffers allocated in one for convenience. - textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL); + recallocuser(&textures, oldsize, newsize); // Allocate texture column offset table. - texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *))); + recallocuser(&texturecolumnofs, oldsize, newsize); // Allocate texture referencing cache. - texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); + recallocuser(&texturecache, oldsize, newsize); // Allocate texture width table. - texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); + recallocuser(&texturewidth, oldsize, newsize); // Allocate texture height table. - textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); + recallocuser(&textureheight, oldsize, newsize); // Create translation table for global animation. - texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); + Z_Realloc(texturetranslation, (newtextures + 1) * sizeof(*texturetranslation), PU_STATIC, &texturetranslation); - for (i = 0; i < numtextures; i++) + for (i = numtextures; i < newtextures; ++i) texturetranslation[i] = i; +} - for (i = 0, w = 0; w < numwadfiles; w++) - { +static INT32 R_DefineTextures(INT32 i, UINT16 w) +{ #ifdef WALLFLATS - i = Rloadflats(i, w); + i = Rloadflats(i, w); #endif - i = Rloadtextures(i, w); - } + return Rloadtextures(i, w); +} + +static void R_FinishLoadingTextures(INT32 add) +{ + numtextures += add; #ifdef HWRENDER if (rendermode == render_opengl) @@ -1062,6 +1058,43 @@ void R_LoadTextures(void) #endif } +// +// R_LoadTextures +// Initializes the texture list with the textures from the world map. +// +void R_LoadTextures(void) +{ + INT32 i, w; + INT32 newtextures = 0; + + for (w = 0; w < numwadfiles; w++) + { + newtextures += R_CountTextures((UINT16)w); + } + + // If no textures found by this point, bomb out + if (!newtextures) + I_Error("No textures detected in any WADs!\n"); + + R_AllocateTextures(newtextures); + + for (i = 0, w = 0; w < numwadfiles; w++) + { + i = R_DefineTextures(i, w); + } + + R_FinishLoadingTextures(newtextures); +} + +void R_LoadTexturesPwad(UINT16 wadnum) +{ + INT32 newtextures = R_CountTextures(wadnum); + + R_AllocateTextures(newtextures); + R_DefineTextures(numtextures, wadnum); + R_FinishLoadingTextures(newtextures); +} + static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) { char *texturesToken; diff --git a/src/r_textures.h b/src/r_textures.h index 6e0cc168a..bd737c231 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -76,6 +76,7 @@ extern UINT8 **texturecache; // graphics data for each generated full-size textu // Load TEXTURES definitions, create lookup tables void R_LoadTextures(void); +void R_LoadTexturesPwad(UINT16 wadnum); void R_FlushTextureCache(void); // Texture generation