// AJM: ADDED THIS ENTIRE FILE IN #include "csg.h" #ifdef HLCSG_WADCFG //#ifdef SYSTEM_WIN32 #if defined(SYSTEM_WIN32) && !defined( __GNUC__ ) # include "atlbase.h" // win32 registry API #pragma warning(disable:4996) #else char *g_apppath = NULL; //JK: Stores application path #endif #define WAD_CONFIG_FILE "wad.cfg" typedef struct wadname_s { char wadname[_MAX_PATH]; bool wadinclude; struct wadname_s* next; } wadname_t; typedef struct wadconfig_s { char name[_MAX_PATH]; int entries; wadname_t* firstentry; wadconfig_s* next; } wadconfig_t; wadconfig_t* g_WadCfg; // anchor for the wadconfigurations linked list bool g_bWadConfigsLoaded = false; int g_wadcfglinecount = 1; //JK: added in char *g_wadcfgfile = NULL; // little helper function void stripwadpath (char *str) { char *p = str + strlen (str) - 1; while ((*p == ' ' || *p == '\n' || *p == '\t') && p >= str) *p-- = '\0'; } // ===================================================================================== // WadCfgParseError // ===================================================================================== void WadCfgParseError(const char* message, int linenum, char* got) { stripwadpath(got); // strip newlines Log("Error parsing " WAD_CONFIG_FILE ", line %i:\n" "%s, got '%s'\n", linenum, message, got); 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" " in the zip file with these tools.\n"); g_bWadConfigsLoaded = false; } // ============================================================================ // IsWhitespace // ============================================================================ bool IsWhitespace(const char ThinkChar) { if ((ThinkChar == ' ') || (ThinkChar == '\t') || (ThinkChar == '\n') || (ThinkChar == 13) /* strange whitespace char */) return true; return false; } // ============================================================================ // Safe_GetToken // ============================================================================ void Safe_GetToken(FILE* source, char* TokenBuffer, const unsigned int MaxBufferLength) { char ThinkChar[1]; // 2 char array = thinkchar and null terminator bool InToken = false; // are we getting a token? bool InQuotes = false; // are we in quotes? bool InComment = false; // are we in a comment (//)? //fpos_t* sourcepos; long sourcepos; TokenBuffer[0] = '\0'; ThinkChar[1] = '\0'; while(!feof(source)) { if (strlen(TokenBuffer) >= MaxBufferLength) return; // we cant add any more chars onto the buffer, its maxed out ThinkChar[0] = fgetc(source); if (ThinkChar[0] == '\n') // newline { g_wadcfglinecount++; InComment = false; } if (ThinkChar[0] == 'ÿ') return; if (IsWhitespace(ThinkChar[0]) && !InToken) continue; // whitespace before token, ignore if (ThinkChar[0] == '"') // quotes { if(InQuotes) InQuotes = false; else InQuotes = true; continue; // dont include quotes } if (ThinkChar[0] == '/') { sourcepos = ftell(source); // might be a comment, see if the next char is a forward slash if (fgetc(source) == '/') // if it is, were in a comment { InComment = true; continue; } else // if not, rewind pretend nothing happened... { fseek(source, sourcepos, 0); } } if ( (IsWhitespace(ThinkChar[0]) && InToken && !InQuotes) // whitespace AFTER token and not in quotes || (InToken && InComment) // we hit a comment, and we have our token ) { //printf("[gt: %s]\n", TokenBuffer); return; } if (!InComment) { strcat(TokenBuffer, ThinkChar); InToken = true; } } } // ===================================================================================== // GetWadConfig // return true if we didnt encounter any fatal errors #define MAX_TOKENBUFFER _MAX_PATH // ===================================================================================== bool GetWadConfig(FILE* wadcfg, wadconfig_t* wadconfig) { char TokenBuffer[MAX_TOKENBUFFER]; wadname_t* current; wadname_t* previous; while (!feof(wadcfg)) { Safe_GetToken(wadcfg, TokenBuffer, MAX_TOKENBUFFER); if (!strcmp(TokenBuffer, "}")) return true; // no more work to do if (!strcmp(TokenBuffer, ";")) continue; // old seperator, no longer used but here for backwards compadibility if (!strcmp(TokenBuffer, "{")) // wtf { WadCfgParseError("Expected wadpath (Nested blocks illegal)", g_wadcfglinecount, TokenBuffer); return false; } // otherwise assume its a wadpath, make an entry in this configuration current = (wadname_t*)malloc(sizeof(wadname_t)); wadconfig->entries++; current->next = NULL; current->wadinclude = false; if (!strcmp(TokenBuffer, "include")) { current->wadinclude = true; Safe_GetToken(wadcfg, TokenBuffer, MAX_TOKENBUFFER); } strcpy_s(current->wadname, TokenBuffer); if (!wadconfig->firstentry) { wadconfig->firstentry = current; } else { previous->next = current; } previous = current; previous->next = NULL; } safe_snprintf(TokenBuffer, MAX_TOKENBUFFER, "Unexptected end of file encountered while parsing configuration '%s'", wadconfig->name); WadCfgParseError(TokenBuffer, g_wadcfglinecount, "(eof)"); return false; } #undef MAX_TOKENBUFFER // ===================================================================================== // LoadWadConfigFile // ===================================================================================== void LoadWadConfigFile() { FILE* wadcfg; wadconfig_t* current; wadconfig_t* previous; char temp[_MAX_PATH]; //JK: If exists lets use user-defined file if (g_wadcfgfile && q_exists(g_wadcfgfile)) { wadcfg = fopen(g_wadcfgfile, "r"); } else // find the wad.cfg file { char appdir[_MAX_PATH]; char tmp[_MAX_PATH]; memset(tmp, 0, sizeof(tmp)); memset(appdir, 0, sizeof(appdir)); // Get application directory (only an approximation on posix systems) // try looking in the directory we were run from #ifdef SYSTEM_WIN32 GetModuleFileName(NULL, tmp, _MAX_PATH); #else safe_strncpy(tmp, g_apppath, _MAX_PATH); #endif ExtractFilePath(tmp, appdir); safe_snprintf(tmp, _MAX_PATH, "%s%s", appdir, WAD_CONFIG_FILE); #ifdef _DEBUG Log("[dbg] Trying '%s'\n", tmp); #endif if (!q_exists(tmp)) { // try the Half-Life directory #ifdef SYSTEM_WIN32 { HKEY HLMachineKey; DWORD disposition; DWORD dwType, dwSize; // REG: create machinekey RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Valve\\Half-Life"), 0, NULL, 0, 0, NULL, &HLMachineKey, &disposition); // REG: get hl dir dwType = REG_SZ; dwSize = _MAX_PATH; RegQueryValueEx(HLMachineKey, TEXT("InstallPath"), NULL, &dwType, (PBYTE)&appdir, &dwSize); } safe_strncpy(tmp, appdir, _MAX_PATH); safe_strncat(tmp, SYSTEM_SLASH_STR, _MAX_PATH); // system slash pointless as this will only work on win32, but anyway... safe_strncat(tmp, WAD_CONFIG_FILE, _MAX_PATH); #ifdef _DEBUG Log("[dbg] Trying '%s'\n", tmp); #endif if (!q_exists(tmp)) #endif // SYSTEM_WIN32 { // still cant find it, error out Log("Warning: could not find wad configurations file\n" "Make sure that wad.cfg is in the Half-Life directory or the current working directory\n" ); return; } } wadcfg = fopen(tmp, "r"); } if (!wadcfg) { // cant open it, die Log("Warning: could not open the wad configurations file\n" "Make sure that wad.cfg is in the Half-Life directory or the current working directory\n" ); return; } while(!feof(wadcfg)) { Safe_GetToken(wadcfg, temp, MAX_WAD_CFG_NAME); if (!strcmp(temp, "HalfLifePath=")) // backwards compadibitly { Safe_GetToken(wadcfg, temp, MAX_WAD_CFG_NAME); Warning("Redundant line in " WAD_CONFIG_FILE ": \"HalfLifePath= %s\" - Ignoring...\n", temp); continue; } if (feof(wadcfg)) break; // assume its the name of a configuration current = (wadconfig_t*)malloc(sizeof(wadconfig_t)); safe_strncpy(current->name, temp, _MAX_PATH); current->entries = 0; current->next = NULL; current->firstentry = NULL; // make sure the next char starts a wad configuration Safe_GetToken(wadcfg, temp, _MAX_PATH); if (strcmp(temp, "{")) { WadCfgParseError("Expected start of wadfile configuration, '{'", g_wadcfglinecount, temp); //Log("[dbg] temp[0] is %i\n", temp[0]); fclose(wadcfg); return; } // otherwise were ok, get the definition if (!GetWadConfig(wadcfg, current)) { fclose(wadcfg); return; } // add this config to the list if (!g_WadCfg) { g_WadCfg = current; } else { previous->next = current; } previous = current; previous->next = NULL; } g_bWadConfigsLoaded = true; } // ===================================================================================== // ProcessWadConfiguration // ===================================================================================== void ProcessWadConfiguration() { int usedwads = 0; char szTmp[1024]; // arbitrary, but needs to be large. probably bigger than this. wadconfig_t* config; wadname_t* path; if(!g_bWadConfigsLoaded) // we did a graceful exit due to some warning/error, so dont complain about it { Log("Using mapfile wad configuration\n"); return; } szTmp[0] = 0; config = g_WadCfg; if (!wadconfigname) return; // this should never happen if (!config) { Warning("No configurations detected in wad.cfg\n" "using map wad configuration"); return; } while (1) { if (!strcmp(config->name, wadconfigname)) { path = config->firstentry; while (1) { if (!path) break; Verbose("Wadpath from wad.cfg: '%s'\n", path->wadname); PushWadPath(path->wadname, true); safe_snprintf(szTmp, 1024, "%s%s;", szTmp, path->wadname); usedwads++; if (path->wadinclude) g_WadInclude.push_back(path->wadname); // next path path = path->next; } break; // the user can only specify one wad configuration, were done here } // next config config = config->next; if (!config) break; } if (usedwads) { Log("Using custom wadfile configuration: '%s' (with %i wad%s)\n", wadconfigname, usedwads, usedwads > 1 ? "s" : ""); SetKeyValue(&g_entities[0], "wad", szTmp); SetKeyValue(&g_entities[0], "_wad", szTmp); } else { Warning("no wadfiles are specified in configuration '%s' --\n" "Using map wadfile configuration", wadconfigname); g_bWadConfigsLoaded = false; } return; } // ===================================================================================== // WadCfg_cleanup // ===================================================================================== void WadCfg_cleanup() { wadconfig_t* config; wadconfig_t* nextconfig; wadname_t* path; wadname_t* nextpath; config = g_WadCfg; while (config) { path = config->firstentry; while (path) { nextpath = path->next; free(path); path = nextpath; } nextconfig = config->next; free(config); config = nextconfig; } g_WadCfg = NULL; g_bWadConfigsLoaded = false; return; } #endif // HLCSG_WADCFG