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