// AJM: Added this file in #include "csg.h" #include "cmdlib.h" #ifdef SYSTEM_WIN32 #pragma warning(disable:4996) #endif #ifdef HLCSG_AUTOWAD #define MAX_AUTOWAD_TEXNAME 32 // 32 char limit in array size in brush_texture_t struct int g_numUsedTextures = 0; typedef struct autowad_texname_s // non-dupicate list of textures used in map { char name[MAX_AUTOWAD_TEXNAME]; autowad_texname_s* next; } autowad_texname_t; autowad_texname_t* g_autowad_texname; // ===================================================================================== // Extract File stuff (ExtractFile | ExtractFilePath | ExtractFileBase) // // With VS 2005 - and the 64 bit build, i had to pull 3 classes over from // cmdlib.cpp even with the proper includes to get rid of the lnk2001 error // // amckern - amckern@yahoo.com // ===================================================================================== #define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') void ExtractFileBase(const char* const path, char* dest) { hlassert (path != dest); const char* src; src = path + strlen(path) - 1; // // back up until a \ or the start // while (src != path && !PATHSEPARATOR(*(src - 1))) src--; while (*src && *src != '.') { *dest++ = *src++; } *dest = 0; } void ExtractFilePath(const char* const path, char* dest) { hlassert (path != dest); const char* src; src = path + strlen(path) - 1; // // back up until a \ or the start // while (src != path && !PATHSEPARATOR(*(src - 1))) src--; memcpy(dest, path, src - path); dest[src - path] = 0; } void ExtractFile(const char* const path, char* dest) { hlassert (path != dest); const char* src; src = path + strlen(path) - 1; while (src != path && !PATHSEPARATOR(*(src - 1))) src--; while (*src) { *dest++ = *src++; } *dest = 0; } // ===================================================================================== // autowad_PushName // adds passed texname as an entry to autowad_wadnames list, without duplicates // ===================================================================================== void autowad_PushName(const char* const texname) { autowad_texname_t* tex; if (!g_autowad_texname) { // first texture, make an entry tex = (autowad_texname_t*)malloc(sizeof(autowad_texname_t)); tex->next = NULL; strcpy_s(tex->name, texname); g_autowad_texname = tex; g_numUsedTextures++; #ifdef _DEBUG Log("[dbg] Used texture: %i[%s]\n", g_numUsedTextures, texname); #endif return; } // otherwise, see if texname isnt already in the list for (tex = g_autowad_texname; ;tex = tex->next) { if (!strcmp(tex->name, texname)) return; // dont bother adding it again if (!tex->next) break; // end of list } // unique texname g_numUsedTextures++; autowad_texname_t* last; last = tex; tex = (autowad_texname_t*)malloc(sizeof(autowad_texname_t)); strcpy_s(tex->name, texname); tex->next = NULL; last->next = tex; #ifdef _DEBUG Log("[dbg] Used texture: %i[%s]\n", g_numUsedTextures, texname); #endif } // ===================================================================================== // autowad_PurgeName // ===================================================================================== void autowad_PurgeName(const char* const texname) { autowad_texname_t* prev; autowad_texname_t* current; if (!g_autowad_texname) return; current = g_autowad_texname; prev = NULL; for (; ;) { if (!strcmp(current->name, texname)) { if (!prev) // start of the list { g_autowad_texname = current->next; } else // middle of list { prev->next = current->next; } free(current); return; } if (!current->next) { //Log(" AUTOWAD: Purge Tex: texname '%s' does not exist\n", texname); return; // end of list } // move along prev = current; current = current->next; } } // ===================================================================================== // autowad_PopName // removes a name from the autowad list, puts it in memory and retuns pointer (which // shoudl be destructed by the calling function later) // ===================================================================================== char* autowad_PopName() { // todo: code return NULL; } // ===================================================================================== // autowad_cleanup // frees memory used by autowad procedure // ===================================================================================== void autowad_cleanup() { if (g_autowad_texname != NULL) { autowad_texname_t* current; autowad_texname_t* next; for (current = g_autowad_texname; ; current = next) { if (!current) break; //Log("[aw] removing tex %s\n", current->name); next = current->next; free(current); } } } // ===================================================================================== // autowad_IsUsedTexture // is this texture in the autowad list? // ===================================================================================== bool autowad_IsUsedTexture(const char* const texname) { autowad_texname_t* current; if (!g_autowad_texname) return false; for (current = g_autowad_texname; ; current = current->next) { //Log("atw: IUT: Comparing: '%s' with '%s'\n", current->name, texname); if (!strcmp(current->name, texname)) return true; if (!current->next) return false; // reached end of list } return false; } // ===================================================================================== // GetUsedTextures // ===================================================================================== void GetUsedTextures() { int i; side_t* bs; for (i = 0; i < g_numbrushsides; i++) { bs = &g_brushsides[i]; autowad_PushName(bs->td.name); } } // ===================================================================================== // autowad_UpdateUsedWads // ===================================================================================== // yes, these should be in a header/common lib, but i cant be bothered #define MAXWADNAME 16 typedef struct { char identification[4]; // should be WAD2/WAD3 int numlumps; int infotableofs; } wadinfo_t; typedef struct { int filepos; int disksize; int size; // uncompressed char type; char compression; char pad1, pad2; char name[MAXWADNAME]; // must be null terminated int iTexFile; // index of the wad this texture is located in } lumpinfo_t; static void CleanupName(const char* const in, char* out) { int i; for (i = 0; i < MAXWADNAME; i++) { if (!in[i]) { break; } out[i] = toupper(in[i]); } for (; i < MAXWADNAME; i++) { out[i] = 0; } } void autowad_UpdateUsedWads() { // see which wadfiles are needed // code for this wad loop somewhat copied from below wadinfo_t thiswad; lumpinfo_t* thislump = NULL; wadpath_t* currentwad; char* pszWadFile; FILE* texfile; const char* pszWadroot = getenv("WADROOT"); int i, j; int nTexLumps = 0; #ifdef _DEBUG Log("[dbg] Starting wad dependency check\n"); #endif // open each wadpath and sort though its contents for (i = 0; i < g_iNumWadPaths; i++) { currentwad = g_pWadPaths[i]; pszWadFile = currentwad->path; currentwad->usedbymap = false; // guilty until proven innocent #ifdef _DEBUG Log(" Parsing wad: '%s'\n", pszWadFile); #endif texfile = fopen(pszWadFile, "rb"); #ifdef SYSTEM_WIN32 if (!texfile) { // cant find it, maybe this wad file has a hard code drive if (pszWadFile[1] == ':') { pszWadFile += 2; // skip past the drive texfile = fopen(pszWadFile, "rb"); } } #endif char szTmp[_MAX_PATH]; if (!texfile && pszWadroot) { char szFile[_MAX_PATH]; char szSubdir[_MAX_PATH]; ExtractFile(pszWadFile, szFile); ExtractFilePath(pszWadFile, szTmp); ExtractFile(szTmp, szSubdir); // szSubdir will have a trailing separator safe_snprintf(szTmp, _MAX_PATH, "%s" SYSTEM_SLASH_STR "%s%s", pszWadroot, szSubdir, szFile); texfile = fopen(szTmp, "rb"); #ifdef SYSTEM_POSIX if (!texfile) { // cant find it, Convert to lower case and try again strlwr(szTmp); texfile = fopen(szTmp, "rb"); } #endif } if (!texfile) // still cant find it, skip this one { if(pszWadroot) { Warning("Wad file '%s' not found, also tried '%s'",pszWadFile,szTmp); } else { Warning("Wad file '%s' not found",pszWadFile); } continue; } // look and see if we're supposed to include the textures from this WAD in the bsp. { WadInclude_i it; bool including = false; for (it = g_WadInclude.begin(); it != g_WadInclude.end(); it++) { if (stristr(pszWadFile, it->c_str())) { #ifdef _DEBUG Log(" - including wad\n"); #endif including = true; currentwad->usedbymap = true; break; } } if (including) { //fclose(texfile); //continue; } } // read in this wadfiles information SafeRead(texfile, &thiswad, sizeof(thiswad)); // make sure its a valid format if (strncmp(thiswad.identification, "WAD2", 4) && strncmp(thiswad.identification, "WAD3", 4)) { fclose(texfile); continue; } thiswad.numlumps = LittleLong(thiswad.numlumps); thiswad.infotableofs = LittleLong(thiswad.infotableofs); // read in lump if (fseek(texfile, thiswad.infotableofs, SEEK_SET)) { fclose(texfile); continue; // had trouble reading, skip this wad } // memalloc for this lump thislump = (lumpinfo_t*)realloc(thislump, (nTexLumps + thiswad.numlumps) * sizeof(lumpinfo_t)); // BUGBUG: is this destructed? // for each texlump for (j = 0; j < thiswad.numlumps; j++, nTexLumps++) { SafeRead(texfile, &thislump[nTexLumps], (sizeof(lumpinfo_t) - sizeof(int)) ); // iTexFile is NOT read from file CleanupName(thislump[nTexLumps].name, thislump[nTexLumps].name); if (autowad_IsUsedTexture(thislump[nTexLumps].name)) { currentwad->usedbymap = true; currentwad->usedtextures++; #ifdef _DEBUG Log(" - Used wadfile: [%s]\n", thislump[nTexLumps].name); #endif autowad_PurgeName(thislump[nTexLumps].name); } } fclose(texfile); } #ifdef _DEBUG Log("[dbg] End wad dependency check\n\n"); #endif return; } #endif // HLCSG_AUTOWAD