1 // AJM: Added this file in
2 #include "csg.h"
3 #include "cmdlib.h"
4 
5 #ifdef HLCSG_AUTOWAD
6 
7 #define MAX_AUTOWAD_TEXNAME 32  // 32 char limit in array size in brush_texture_t struct
8 
9 int g_numUsedTextures = 0;
10 
11 typedef struct autowad_texname_s         // non-dupicate list of textures used in map
12 {
13     char        name[MAX_AUTOWAD_TEXNAME];
14     autowad_texname_s*  next;
15 } autowad_texname_t;
16 
17 autowad_texname_t* g_autowad_texname;
18 
19 // =====================================================================================
20 //  Extract File stuff (ExtractFile | ExtractFilePath | ExtractFileBase)
21 //
22 // With VS 2005 - and the 64 bit build, i had to pull 3 classes over from
23 // cmdlib.cpp even with the proper includes to get rid of the lnk2001 error
24 //
25 // amckern - amckern@yahoo.com
26 // =====================================================================================
27 
28 #define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/')
29 
ExtractFileBase(const char * const path,char * dest)30 void            ExtractFileBase(const char* const path, char* dest)
31 {
32     hlassert (path != dest);
33 
34     const char*           src;
35 
36     src = path + strlen(path) - 1;
37 
38     //
39     // back up until a \ or the start
40     //
41     while (src != path && !PATHSEPARATOR(*(src - 1)))
42         src--;
43 
44     while (*src && *src != '.')
45     {
46         *dest++ = *src++;
47     }
48     *dest = 0;
49 }
50 
ExtractFilePath(const char * const path,char * dest)51 void            ExtractFilePath(const char* const path, char* dest)
52 {
53     hlassert (path != dest);
54 
55     const char*           src;
56 
57     src = path + strlen(path) - 1;
58 
59     //
60     // back up until a \ or the start
61     //
62     while (src != path && !PATHSEPARATOR(*(src - 1)))
63         src--;
64 
65     memcpy(dest, path, src - path);
66     dest[src - path] = 0;
67 }
68 
ExtractFile(const char * const path,char * dest)69 void            ExtractFile(const char* const path, char* dest)
70 {
71     hlassert (path != dest);
72 
73     const char*           src;
74 
75     src = path + strlen(path) - 1;
76 
77     while (src != path && !PATHSEPARATOR(*(src - 1)))
78         src--;
79 
80     while (*src)
81     {
82         *dest++ = *src++;
83     }
84     *dest = 0;
85 }
86 
87 // =====================================================================================
88 //  autowad_PushName
89 //      adds passed texname as an entry to autowad_wadnames list, without duplicates
90 // =====================================================================================
autowad_PushName(const char * const texname)91 void        autowad_PushName(const char* const texname)
92 {
93     autowad_texname_t*  tex;
94 
95     if (!g_autowad_texname)
96     {
97         // first texture, make an entry
98         tex = (autowad_texname_t*)malloc(sizeof(autowad_texname_t));
99         tex->next = NULL;
100         strcpy_s(tex->name, texname);
101 
102         g_autowad_texname = tex;
103         g_numUsedTextures++;
104 
105 #ifdef _DEBUG
106         Log("[dbg] Used texture: %i[%s]\n", g_numUsedTextures, texname);
107 #endif
108         return;
109     }
110 
111     // otherwise, see if texname isnt already in the list
112     for (tex = g_autowad_texname; ;tex = tex->next)
113     {
114         if (!strcmp(tex->name, texname))
115             return; // dont bother adding it again
116 
117         if (!tex->next)
118             break;  // end of list
119     }
120 
121     // unique texname
122     g_numUsedTextures++;
123     autowad_texname_t*  last;
124     last = tex;
125     tex = (autowad_texname_t*)malloc(sizeof(autowad_texname_t));
126     strcpy_s(tex->name, texname);
127     tex->next = NULL;
128     last->next = tex;
129 
130 #ifdef _DEBUG
131     Log("[dbg] Used texture: %i[%s]\n", g_numUsedTextures, texname);
132 #endif
133 }
134 
135 // =====================================================================================
136 //  autowad_PurgeName
137 // =====================================================================================
autowad_PurgeName(const char * const texname)138 void        autowad_PurgeName(const char* const texname)
139 {
140     autowad_texname_t*  prev;
141     autowad_texname_t*  current;
142 
143     if (!g_autowad_texname)
144         return;
145 
146     current = g_autowad_texname;
147     prev = NULL;
148     for (; ;)
149     {
150         if (!strcmp(current->name, texname))
151         {
152             if (!prev)      // start of the list
153             {
154                 g_autowad_texname = current->next;
155             }
156             else            // middle of list
157             {
158                 prev->next = current->next;
159             }
160 
161             free(current);
162             return;
163         }
164 
165         if (!current->next)
166         {
167             //Log(" AUTOWAD: Purge Tex: texname '%s' does not exist\n", texname);
168             return; // end of list
169         }
170 
171         // move along
172         prev = current;
173         current = current->next;
174     }
175 }
176 
177 // =====================================================================================
178 //  autowad_PopName
179 //      removes a name from the autowad list, puts it in memory and retuns pointer (which
180 //      shoudl be destructed by the calling function later)
181 // =====================================================================================
autowad_PopName()182 char*      autowad_PopName()
183 {
184     // todo: code
185     return NULL;
186 }
187 
188 // =====================================================================================
189 //  autowad_cleanup
190 //      frees memory used by autowad procedure
191 // =====================================================================================
autowad_cleanup()192 void        autowad_cleanup()
193 {
194     if (g_autowad_texname != NULL)
195     {
196         autowad_texname_t*  current;
197         autowad_texname_t*  next;
198 
199         for (current = g_autowad_texname; ; current = next)
200         {
201             if (!current)
202                 break;
203 
204             //Log("[aw] removing tex %s\n", current->name);
205             next = current->next;
206             free(current);
207         }
208     }
209 }
210 
211 // =====================================================================================
212 //  autowad_IsUsedTexture
213 //      is this texture in the autowad list?
214 // =====================================================================================
autowad_IsUsedTexture(const char * const texname)215 bool        autowad_IsUsedTexture(const char* const texname)
216 {
217     autowad_texname_t*  current;
218 
219     if (!g_autowad_texname)
220         return false;
221 
222     for (current = g_autowad_texname; ; current = current->next)
223     {
224         //Log("atw: IUT: Comparing: '%s' with '%s'\n", current->name, texname);
225         if (!strcmp(current->name, texname))
226             return true;
227 
228         if (!current->next)
229             return false; // reached end of list
230     }
231 
232     return false;
233 }
234 
235 // =====================================================================================
236 //  GetUsedTextures
237 // =====================================================================================
GetUsedTextures()238 void        GetUsedTextures()
239 {
240     int             i;
241     side_t*         bs;
242 
243     for (i = 0; i < g_numbrushsides; i++)
244     {
245         bs = &g_brushsides[i];
246         autowad_PushName(bs->td.name);
247     }
248 }
249 
250 // =====================================================================================
251 //  autowad_UpdateUsedWads
252 // =====================================================================================
253 
254 // yes, these should be in a header/common lib, but i cant be bothered
255 
256 #define MAXWADNAME 16
257 
258 typedef struct
259 {
260     char            identification[4];                     // should be WAD2/WAD3
261     int             numlumps;
262     int             infotableofs;
263 } wadinfo_t;
264 
265 typedef struct
266 {
267     int             filepos;
268     int             disksize;
269     int             size;                                  // uncompressed
270     char            type;
271     char            compression;
272     char            pad1, pad2;
273     char            name[MAXWADNAME];                      // must be null terminated
274 
275     int             iTexFile;                              // index of the wad this texture is located in
276 
277 } lumpinfo_t;
278 
CleanupName(const char * const in,char * out)279 static void     CleanupName(const char* const in, char* out)
280 {
281     int             i;
282 
283     for (i = 0; i < MAXWADNAME; i++)
284     {
285         if (!in[i])
286         {
287             break;
288         }
289 
290         out[i] = toupper(in[i]);
291     }
292 
293     for (; i < MAXWADNAME; i++)
294     {
295         out[i] = 0;
296     }
297 }
298 
autowad_UpdateUsedWads()299 void        autowad_UpdateUsedWads()
300 {
301     // see which wadfiles are needed
302     // code for this wad loop somewhat copied from below
303     wadinfo_t       thiswad;
304     lumpinfo_t*     thislump = NULL;
305     wadpath_t*      currentwad;
306     char*           pszWadFile;
307     FILE*           texfile;
308     const char*     pszWadroot = getenv("WADROOT");
309     int             i, j;
310     int             nTexLumps = 0;
311 
312 #ifdef _DEBUG
313     Log("[dbg] Starting wad dependency check\n");
314 #endif
315 
316     // open each wadpath and sort though its contents
317     for (i = 0; i < g_iNumWadPaths; i++)
318     {
319         currentwad = g_pWadPaths[i];
320         pszWadFile = currentwad->path;
321         currentwad->usedbymap = false;  // guilty until proven innocent
322 
323 #ifdef _DEBUG
324         Log(" Parsing wad: '%s'\n", pszWadFile);
325 #endif
326 
327         texfile = fopen(pszWadFile, "rb");
328 
329         #ifdef SYSTEM_WIN32
330         if (!texfile)
331         {
332             // cant find it, maybe this wad file has a hard code drive
333             if (pszWadFile[1] == ':')
334             {
335                 pszWadFile += 2;                           // skip past the drive
336                 texfile = fopen(pszWadFile, "rb");
337             }
338         }
339         #endif
340 
341         char            szTmp[_MAX_PATH];
342         if (!texfile && pszWadroot)
343         {
344             char            szFile[_MAX_PATH];
345             char            szSubdir[_MAX_PATH];
346 
347             ExtractFile(pszWadFile, szFile);
348 
349             ExtractFilePath(pszWadFile, szTmp);
350             ExtractFile(szTmp, szSubdir);
351 
352             // szSubdir will have a trailing separator
353             safe_snprintf(szTmp, _MAX_PATH, "%s" SYSTEM_SLASH_STR "%s%s", pszWadroot, szSubdir, szFile);
354             texfile = fopen(szTmp, "rb");
355 
356             #ifdef SYSTEM_POSIX
357             if (!texfile)
358             {
359                 // cant find it, Convert to lower case and try again
360                 strlwr(szTmp);
361                 texfile = fopen(szTmp, "rb");
362             }
363             #endif
364         }
365 
366         if (!texfile) // still cant find it, skip this one
367 		{
368 			if(pszWadroot)
369 			{
370 				Warning("Wad file '%s' not found, also tried '%s'",pszWadFile,szTmp);
371 			}
372 			else
373 			{
374 				Warning("Wad file '%s' not found",pszWadFile);
375 			}
376             continue;
377 		}
378 
379         // look and see if we're supposed to include the textures from this WAD in the bsp.
380         {
381             WadInclude_i    it;
382             bool            including = false;
383             for (it = g_WadInclude.begin(); it != g_WadInclude.end(); it++)
384             {
385                 if (stristr(pszWadFile, it->c_str()))
386                 {
387                     #ifdef _DEBUG
388                     Log("  - including wad\n");
389                     #endif
390                     including = true;
391                     currentwad->usedbymap = true;
392                     break;
393                 }
394             }
395             if (including)
396             {
397                 //fclose(texfile);
398                 //continue;
399             }
400         }
401 
402         // read in this wadfiles information
403         SafeRead(texfile, &thiswad, sizeof(thiswad));
404 
405         // make sure its a valid format
406         if (strncmp(thiswad.identification, "WAD2", 4) && strncmp(thiswad.identification, "WAD3", 4))
407         {
408             fclose(texfile);
409             continue;
410         }
411 
412         thiswad.numlumps        = LittleLong(thiswad.numlumps);
413         thiswad.infotableofs    = LittleLong(thiswad.infotableofs);
414 
415         // read in lump
416         if (fseek(texfile, thiswad.infotableofs, SEEK_SET))
417         {
418             fclose(texfile);
419             continue;   // had trouble reading, skip this wad
420         }
421 
422         // memalloc for this lump
423         thislump = (lumpinfo_t*)realloc(thislump, (nTexLumps + thiswad.numlumps) * sizeof(lumpinfo_t));
424         // BUGBUG: is this destructed?
425 
426         // for each texlump
427         for (j = 0; j < thiswad.numlumps; j++, nTexLumps++)
428         {
429             SafeRead(texfile, &thislump[nTexLumps], (sizeof(lumpinfo_t) - sizeof(int)) );  // iTexFile is NOT read from file
430 
431             CleanupName(thislump[nTexLumps].name, thislump[nTexLumps].name);
432 
433             if (autowad_IsUsedTexture(thislump[nTexLumps].name))
434             {
435                 currentwad->usedbymap = true;
436                 currentwad->usedtextures++;
437                 #ifdef _DEBUG
438                 Log("    - Used wadfile: [%s]\n", thislump[nTexLumps].name);
439                 #endif
440                 autowad_PurgeName(thislump[nTexLumps].name);
441             }
442         }
443 
444         fclose(texfile);
445     }
446 
447 #ifdef _DEBUG
448     Log("[dbg] End wad dependency check\n\n");
449 #endif
450     return;
451 }
452 
453 
454 #endif // HLCSG_AUTOWAD
455