wadcfg.cpp 13 KB

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