From 6d7dd8adacdbf65ad27ee3ea897228550f39b24c Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 9 Mar 2024 15:36:22 -0800 Subject: [PATCH] Disallow textures >2048 in size, print a console warning --- src/r_textures.c | 52 ++++++++++++++++++++++++++++------------- src/r_textures.h | 3 +++ src/r_textures_dups.cpp | 34 +++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/r_textures.c b/src/r_textures.c index ea1033c84..e3df88b82 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -1259,6 +1259,7 @@ Rloadtextures (INT32 i, INT32 w) #ifndef NO_PNG_LUMPS size_t lumplength; #endif + INT32 width, height; if (wadfiles[w]->type == RET_PK3) { @@ -1271,6 +1272,35 @@ Rloadtextures (INT32 i, INT32 w) lumplength = W_LumpLengthPwad(wadnum, lumpnum); #endif +#ifndef NO_PNG_LUMPS + if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength)) + { + UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength); + width = (INT16)width; + height = (INT16)height; + Z_Free(png); + } + else +#endif + { + width = SHORT(patchlump.width); + height = SHORT(patchlump.height); + } + + if (width > 2048 || height > 2048) + { + // This is INTENTIONAL. Even if software can handle it, very old GL hardware will not. + // For the sake of a compatibility baseline, we will not allow anything larger than this. + char header[1024]; + sprintf(header, + "Texture patch size cannot be greater than %dx%d!\n" + "List of affected textures:\n", + sizeLimit, sizeLimit); + R_InsertTextureWarning(header, va("\x82" "WARNING: %s", wadfiles[wadnum]->lumpinfo[lumpnum].fullname)); + continue; + } + //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); @@ -1278,22 +1308,8 @@ Rloadtextures (INT32 i, INT32 w) 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->width = width; + texture->height = height; texture->type = TEXTURETYPE_SINGLEPATCH; texture->patchcount = 1; @@ -1516,6 +1532,8 @@ void R_LoadTextures(void) #ifdef DEVELOP R_CheckTextureDuplicates(0, maintextures); #endif + + R_PrintTextureWarnings(); } void R_LoadTexturesPwad(UINT16 wadnum) @@ -1525,6 +1543,8 @@ void R_LoadTexturesPwad(UINT16 wadnum) R_AllocateTextures(newtextures); newtextures = R_DefineTextures(numtextures, wadnum); R_FinishLoadingTextures(newtextures); + + R_PrintTextureWarnings(); } static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) diff --git a/src/r_textures.h b/src/r_textures.h index 5a2dffd79..98a78ba0d 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -114,6 +114,9 @@ lumpnum_t R_GetFlatNumForName(const char *name); void R_CheckTextureDuplicates(INT32 start, INT32 end); void R_PrintTextureDuplicates(void); +void R_InsertTextureWarning(const char *header, const char *warning); +void R_PrintTextureWarnings(void); + extern INT32 numtextures; extern INT32 g_texturenum_dbgline; diff --git a/src/r_textures_dups.cpp b/src/r_textures_dups.cpp index ba167df80..1de9cb1c1 100644 --- a/src/r_textures_dups.cpp +++ b/src/r_textures_dups.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ namespace { std::unordered_map> g_dups; +std::map> g_warnings; std::thread g_dups_thread; std::string key8char(const char cstr[8]) @@ -146,15 +148,37 @@ void R_PrintTextureDuplicates(void) g_dups_thread.join(); } - if (g_dups.empty()) - { - return; - } - for (auto [key, v] : g_dups) { std::for_each(v.cbegin(), v.cend(), print_dup); } g_dups = {}; + + R_PrintTextureWarnings(); +} + +void R_InsertTextureWarning(const char *header, const char *warning) +{ + g_warnings[header].push_back(warning); +} + +void R_PrintTextureWarnings(void) +{ + if (g_dups_thread.joinable()) + { + return; + } + + for (auto [header, v] : g_warnings) + { + CONS_Alert(CONS_WARNING, "\n%s", header.c_str()); + + for (const std::string& warning : v) + { + CONS_Printf("%s\n", warning.c_str()); + } + } + + g_warnings = {}; }