Disallow textures >2048 in size, print a console warning

This commit is contained in:
James R 2024-03-09 15:36:22 -08:00
parent 2ee595419c
commit 6d7dd8adac
3 changed files with 68 additions and 21 deletions

View file

@ -1259,6 +1259,7 @@ Rloadtextures (INT32 i, INT32 w)
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
size_t lumplength; size_t lumplength;
#endif #endif
INT32 width, height;
if (wadfiles[w]->type == RET_PK3) if (wadfiles[w]->type == RET_PK3)
{ {
@ -1271,6 +1272,35 @@ Rloadtextures (INT32 i, INT32 w)
lumplength = W_LumpLengthPwad(wadnum, lumpnum); lumplength = W_LumpLengthPwad(wadnum, lumpnum);
#endif #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); //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); 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)); M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
texture->hash = quickncasehash(texture->name, 8); texture->hash = quickncasehash(texture->name, 8);
#ifndef NO_PNG_LUMPS texture->width = width;
if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength)) texture->height = height;
{
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->type = TEXTURETYPE_SINGLEPATCH;
texture->patchcount = 1; texture->patchcount = 1;
@ -1516,6 +1532,8 @@ void R_LoadTextures(void)
#ifdef DEVELOP #ifdef DEVELOP
R_CheckTextureDuplicates(0, maintextures); R_CheckTextureDuplicates(0, maintextures);
#endif #endif
R_PrintTextureWarnings();
} }
void R_LoadTexturesPwad(UINT16 wadnum) void R_LoadTexturesPwad(UINT16 wadnum)
@ -1525,6 +1543,8 @@ void R_LoadTexturesPwad(UINT16 wadnum)
R_AllocateTextures(newtextures); R_AllocateTextures(newtextures);
newtextures = R_DefineTextures(numtextures, wadnum); newtextures = R_DefineTextures(numtextures, wadnum);
R_FinishLoadingTextures(newtextures); R_FinishLoadingTextures(newtextures);
R_PrintTextureWarnings();
} }
static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)

View file

@ -114,6 +114,9 @@ lumpnum_t R_GetFlatNumForName(const char *name);
void R_CheckTextureDuplicates(INT32 start, INT32 end); void R_CheckTextureDuplicates(INT32 start, INT32 end);
void R_PrintTextureDuplicates(void); void R_PrintTextureDuplicates(void);
void R_InsertTextureWarning(const char *header, const char *warning);
void R_PrintTextureWarnings(void);
extern INT32 numtextures; extern INT32 numtextures;
extern INT32 g_texturenum_dbgline; extern INT32 g_texturenum_dbgline;

View file

@ -11,6 +11,7 @@
#include <cctype> #include <cctype>
#include <cstdint> #include <cstdint>
#include <filesystem> #include <filesystem>
#include <map>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <thread> #include <thread>
@ -28,6 +29,7 @@ namespace
{ {
std::unordered_map<std::string, std::vector<const texture_t*>> g_dups; std::unordered_map<std::string, std::vector<const texture_t*>> g_dups;
std::map<std::string, std::vector<std::string>> g_warnings;
std::thread g_dups_thread; std::thread g_dups_thread;
std::string key8char(const char cstr[8]) std::string key8char(const char cstr[8])
@ -146,15 +148,37 @@ void R_PrintTextureDuplicates(void)
g_dups_thread.join(); g_dups_thread.join();
} }
if (g_dups.empty())
{
return;
}
for (auto [key, v] : g_dups) for (auto [key, v] : g_dups)
{ {
std::for_each(v.cbegin(), v.cend(), print_dup); std::for_each(v.cbegin(), v.cend(), print_dup);
} }
g_dups = {}; 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 = {};
} }