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