1 // AJM: ADDED THIS ENTIRE FILE IN
2
3 #include "csg.h"
4 #ifdef HLCSG_WADCFG
5
6 //#ifdef SYSTEM_WIN32
7 #if defined(SYSTEM_WIN32) && !defined( __GNUC__ )
8 # include "atlbase.h" // win32 registry API
9 #else
10 char *g_apppath = NULL; //JK: Stores application path
11 #endif
12
13 #define WAD_CONFIG_FILE "wad.cfg"
14
15 typedef struct wadname_s
16 {
17 char wadname[_MAX_PATH];
18 bool wadinclude;
19 struct wadname_s* next;
20 } wadname_t;
21
22 typedef struct wadconfig_s
23 {
24 char name[_MAX_PATH];
25 int entries;
26 wadname_t* firstentry;
27 wadconfig_s* next;
28 } wadconfig_t;
29
30 wadconfig_t* g_WadCfg; // anchor for the wadconfigurations linked list
31
32 bool g_bWadConfigsLoaded = false;
33 int g_wadcfglinecount = 1;
34
35 //JK: added in
36 char *g_wadcfgfile = NULL;
37
38 // little helper function
stripwadpath(char * str)39 void stripwadpath (char *str)
40 {
41 char *p = str + strlen (str) - 1;
42 while ((*p == ' ' || *p == '\n' || *p == '\t') && p >= str) *p-- = '\0';
43 }
44
45 // =====================================================================================
46 // WadCfgParseError
47 // =====================================================================================
WadCfgParseError(const char * message,int linenum,char * got)48 void WadCfgParseError(const char* message, int linenum, char* got)
49 {
50 stripwadpath(got); // strip newlines
51
52 Log("Error parsing " WAD_CONFIG_FILE ", line %i:\n"
53 "%s, got '%s'\n", linenum, message, got);
54
55 Log("If you need help on usage of the wad.cfg file, be sure to check http://www.zhlt.info/using-wad.cfg.html that came"
56 " in the zip file with these tools.\n");
57
58 g_bWadConfigsLoaded = false;
59 }
60
61 // ============================================================================
62 // IsWhitespace
63 // ============================================================================
IsWhitespace(const char ThinkChar)64 bool IsWhitespace(const char ThinkChar)
65 {
66 if ((ThinkChar == ' ') || (ThinkChar == '\t') || (ThinkChar == '\n') || (ThinkChar == 13) /* strange whitespace char */)
67 return true;
68
69 return false;
70 }
71
72 // ============================================================================
73 // Safe_GetToken
74 // ============================================================================
Safe_GetToken(FILE * source,char * TokenBuffer,const unsigned int MaxBufferLength)75 void Safe_GetToken(FILE* source, char* TokenBuffer, const unsigned int MaxBufferLength)
76 {
77 char ThinkChar[1]; // 2 char array = thinkchar and null terminator
78 bool InToken = false; // are we getting a token?
79 bool InQuotes = false; // are we in quotes?
80 bool InComment = false; // are we in a comment (//)?
81 //fpos_t* sourcepos;
82 long sourcepos;
83
84 TokenBuffer[0] = '\0';
85 ThinkChar[1] = '\0';
86
87 while(!feof(source))
88 {
89 if (strlen(TokenBuffer) >= MaxBufferLength)
90 return; // we cant add any more chars onto the buffer, its maxed out
91
92 ThinkChar[0] = fgetc(source);
93
94 if (ThinkChar[0] == '\n') // newline
95 {
96 g_wadcfglinecount++;
97 InComment = false;
98 }
99
100 if (ThinkChar[0] == '�')
101 return;
102
103 if (IsWhitespace(ThinkChar[0]) && !InToken)
104 continue; // whitespace before token, ignore
105
106 if (ThinkChar[0] == '"') // quotes
107 {
108 if(InQuotes)
109 InQuotes = false;
110 else
111 InQuotes = true;
112 continue; // dont include quotes
113 }
114
115 if (ThinkChar[0] == '/')
116 {
117 sourcepos = ftell(source);
118 // might be a comment, see if the next char is a forward slash
119 if (fgetc(source) == '/') // if it is, were in a comment
120 {
121 InComment = true;
122 continue;
123 }
124 else // if not, rewind pretend nothing happened...
125 {
126 fseek(source, sourcepos, 0);
127 }
128 }
129
130 if (
131 (IsWhitespace(ThinkChar[0]) && InToken && !InQuotes) // whitespace AFTER token and not in quotes
132 || (InToken && InComment) // we hit a comment, and we have our token
133 )
134 {
135 //printf("[gt: %s]\n", TokenBuffer);
136 return;
137 }
138
139 if (!InComment)
140 {
141 strcat(TokenBuffer, ThinkChar);
142 InToken = true;
143 }
144 }
145 }
146
147 // =====================================================================================
148 // GetWadConfig
149 // return true if we didnt encounter any fatal errors
150 #define MAX_TOKENBUFFER _MAX_PATH
151 // =====================================================================================
GetWadConfig(FILE * wadcfg,wadconfig_t * wadconfig)152 bool GetWadConfig(FILE* wadcfg, wadconfig_t* wadconfig)
153 {
154 char TokenBuffer[MAX_TOKENBUFFER];
155 wadname_t* current;
156 wadname_t* previous;
157
158 while (!feof(wadcfg))
159 {
160 Safe_GetToken(wadcfg, TokenBuffer, MAX_TOKENBUFFER);
161
162 if (!strcmp(TokenBuffer, "}"))
163 return true; // no more work to do
164
165 if (!strcmp(TokenBuffer, ";"))
166 continue; // old seperator, no longer used but here for backwards compadibility
167
168 if (!strcmp(TokenBuffer, "{")) // wtf
169 {
170 WadCfgParseError("Expected wadpath (Nested blocks illegal)", g_wadcfglinecount, TokenBuffer);
171 return false;
172 }
173
174 // otherwise assume its a wadpath, make an entry in this configuration
175 current = (wadname_t*)malloc(sizeof(wadname_t));
176 wadconfig->entries++;
177 current->next = NULL;
178 current->wadinclude = false;
179
180 if (!strcmp(TokenBuffer, "include"))
181 {
182 current->wadinclude = true;
183 Safe_GetToken(wadcfg, TokenBuffer, MAX_TOKENBUFFER);
184 }
185
186 strcpy_s(current->wadname, TokenBuffer);
187
188 if (!wadconfig->firstentry)
189 {
190 wadconfig->firstentry = current;
191 }
192 else
193 {
194 previous->next = current;
195 }
196
197 previous = current;
198 previous->next = NULL;
199 }
200
201 safe_snprintf(TokenBuffer, MAX_TOKENBUFFER, "Unexptected end of file encountered while parsing configuration '%s'", wadconfig->name);
202 WadCfgParseError(TokenBuffer, g_wadcfglinecount, "(eof)");
203 return false;
204 }
205 #undef MAX_TOKENBUFFER
206
207 // =====================================================================================
208 // LoadWadConfigFile
209 // =====================================================================================
LoadWadConfigFile()210 void LoadWadConfigFile()
211 {
212 FILE* wadcfg;
213 wadconfig_t* current;
214 wadconfig_t* previous;
215
216 char temp[_MAX_PATH];
217
218 //JK: If exists lets use user-defined file
219 if (g_wadcfgfile && q_exists(g_wadcfgfile))
220 {
221 wadcfg = fopen(g_wadcfgfile, "r");
222 }
223 else // find the wad.cfg file
224 {
225 char appdir[_MAX_PATH];
226 char tmp[_MAX_PATH];
227
228 memset(tmp, 0, sizeof(tmp));
229 memset(appdir, 0, sizeof(appdir));
230
231 // Get application directory (only an approximation on posix systems)
232 // try looking in the directory we were run from
233 #ifdef SYSTEM_WIN32
234 GetModuleFileName(NULL, tmp, _MAX_PATH);
235 #else
236 safe_strncpy(tmp, g_apppath, _MAX_PATH);
237 #endif
238
239 ExtractFilePath(tmp, appdir);
240 safe_snprintf(tmp, _MAX_PATH, "%s%s", appdir, WAD_CONFIG_FILE);
241
242 #ifdef _DEBUG
243 Log("[dbg] Trying '%s'\n", tmp);
244 #endif
245
246 if (!q_exists(tmp))
247 {
248 // try the Half-Life directory
249 #ifdef SYSTEM_WIN32
250 {
251 HKEY HLMachineKey;
252 DWORD disposition;
253 DWORD dwType, dwSize;
254
255 // REG: create machinekey
256 RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Valve\\Half-Life"), 0, NULL,
257 0, 0, NULL, &HLMachineKey, &disposition);
258 // REG: get hl dir
259 dwType = REG_SZ;
260 dwSize = _MAX_PATH;
261 RegQueryValueEx(HLMachineKey, TEXT("InstallPath"), NULL, &dwType, (PBYTE)&appdir, &dwSize);
262 }
263
264 safe_strncpy(tmp, appdir, _MAX_PATH);
265 safe_strncat(tmp, SYSTEM_SLASH_STR, _MAX_PATH); // system slash pointless as this will only work on win32, but anyway...
266 safe_strncat(tmp, WAD_CONFIG_FILE, _MAX_PATH);
267
268 #ifdef _DEBUG
269 Log("[dbg] Trying '%s'\n", tmp);
270 #endif
271
272 if (!q_exists(tmp))
273 #endif // SYSTEM_WIN32
274 {
275 // still cant find it, error out
276 Log("Warning: could not find wad configurations file\n"
277 "Make sure that wad.cfg is in the Half-Life directory or the current working directory\n"
278 );
279 return;
280 }
281 }
282
283 wadcfg = fopen(tmp, "r");
284 }
285
286 if (!wadcfg)
287 {
288 // cant open it, die
289 Log("Warning: could not open the wad configurations file\n"
290 "Make sure that wad.cfg is in the Half-Life directory or the current working directory\n"
291 );
292 return;
293 }
294
295 while(!feof(wadcfg))
296 {
297 Safe_GetToken(wadcfg, temp, MAX_WAD_CFG_NAME);
298
299 if (!strcmp(temp, "HalfLifePath=")) // backwards compadibitly
300 {
301 Safe_GetToken(wadcfg, temp, MAX_WAD_CFG_NAME);
302 Warning("Redundant line in " WAD_CONFIG_FILE ": \"HalfLifePath= %s\" - Ignoring...\n",
303 temp);
304 continue;
305 }
306
307 if (feof(wadcfg))
308 break;
309
310 // assume its the name of a configuration
311 current = (wadconfig_t*)malloc(sizeof(wadconfig_t));
312 safe_strncpy(current->name, temp, _MAX_PATH);
313 current->entries = 0;
314 current->next = NULL;
315 current->firstentry = NULL;
316
317 // make sure the next char starts a wad configuration
318 Safe_GetToken(wadcfg, temp, _MAX_PATH);
319 if (strcmp(temp, "{"))
320 {
321 WadCfgParseError("Expected start of wadfile configuration, '{'", g_wadcfglinecount, temp);
322 //Log("[dbg] temp[0] is %i\n", temp[0]);
323 fclose(wadcfg);
324 return;
325 }
326
327 // otherwise were ok, get the definition
328 if (!GetWadConfig(wadcfg, current))
329 {
330 fclose(wadcfg);
331 return;
332 }
333
334 // add this config to the list
335 if (!g_WadCfg)
336 {
337 g_WadCfg = current;
338 }
339 else
340 {
341 previous->next = current;
342 }
343
344 previous = current;
345 previous->next = NULL;
346 }
347
348 g_bWadConfigsLoaded = true;
349 }
350
351 // =====================================================================================
352 // ProcessWadConfiguration
353 // =====================================================================================
ProcessWadConfiguration()354 void ProcessWadConfiguration()
355 {
356 int usedwads = 0;
357 char szTmp[1024]; // arbitrary, but needs to be large. probably bigger than this.
358 wadconfig_t* config;
359 wadname_t* path;
360
361 if(!g_bWadConfigsLoaded) // we did a graceful exit due to some warning/error, so dont complain about it
362 {
363 Log("Using mapfile wad configuration\n");
364 return;
365 }
366
367 szTmp[0] = 0;
368 config = g_WadCfg;
369
370 if (!wadconfigname)
371 return; // this should never happen
372
373 if (!config)
374 {
375 Warning("No configurations detected in wad.cfg\n"
376 "using map wad configuration");
377 return;
378 }
379
380 while (1)
381 {
382 if (!strcmp(config->name, wadconfigname))
383 {
384 path = config->firstentry;
385 while (1)
386 {
387 if (!path)
388 break;
389
390 Verbose("Wadpath from wad.cfg: '%s'\n", path->wadname);
391 PushWadPath(path->wadname, true);
392 safe_snprintf(szTmp, 1024, "%s%s;", szTmp, path->wadname);
393 usedwads++;
394
395 if (path->wadinclude)
396 g_WadInclude.push_back(path->wadname);
397
398 // next path
399 path = path->next;
400 }
401 break; // the user can only specify one wad configuration, were done here
402 }
403
404 // next config
405 config = config->next;
406 if (!config)
407 break;
408 }
409
410 if (usedwads)
411 {
412 Log("Using custom wadfile configuration: '%s' (with %i wad%s)\n", wadconfigname, usedwads, usedwads > 1 ? "s" : "");
413 SetKeyValue(&g_entities[0], "wad", szTmp);
414 SetKeyValue(&g_entities[0], "_wad", szTmp);
415 }
416 else
417 {
418 Warning("no wadfiles are specified in configuration '%s' --\n"
419 "Using map wadfile configuration", wadconfigname);
420 g_bWadConfigsLoaded = false;
421 }
422
423 return;
424 }
425
426 // =====================================================================================
427 // WadCfg_cleanup
428 // =====================================================================================
WadCfg_cleanup()429 void WadCfg_cleanup()
430 {
431 wadconfig_t* config;
432 wadconfig_t* nextconfig;
433 wadname_t* path;
434 wadname_t* nextpath;
435
436 config = g_WadCfg;
437 while (config)
438 {
439 path = config->firstentry;
440 while (path)
441 {
442 nextpath = path->next;
443 free(path);
444 path = nextpath;
445 }
446
447 nextconfig = config->next;
448 free(config);
449 config = nextconfig;
450 }
451
452 g_WadCfg = NULL;
453 g_bWadConfigsLoaded = false;
454 return;
455 }
456
457
458
459 #endif // HLCSG_WADCFG
460
461