char* physfs_addmappath(char *path) { char *p_path, *p_result; char *result; int length; result = (char *)malloc(PATH_MAX * sizeof(char)); result[0] = '\0'; p_result = result; length = strlen(path); if (length >= 3 && strcmp(&path[length-3], ".wz")==0) { PHYSFS_mount(path, NULL, 1); strcat(p_result, "multiplay/maps/"); p_result += strlen("multiplay/maps/"); p_path = strrchr(path, PHYSFS_getDirSeparator()[0]); if (p_path) { // Remove the path p_path++; strcpy(p_result, p_path); path[strlen(path) - strlen(result) - 1] = '\0'; PHYSFS_mount(path, NULL, 1); } else { strcpy(p_result, path); } // remove ".wz" from end length = strlen(result); result[length-3] = '\0'; } else { if (PHYSFS_exists("multiplay/maps")) { strcat(p_result, "multiplay/maps/"); p_result += strlen("multiplay/maps/"); } p_path = strrchr(path, PHYSFS_getDirSeparator()[0]); if (p_path) { // Remove the path p_path++; strcpy(p_result, p_path); } else { strcpy(p_result, path); } } return result; }
static void replaceSeparators(std::string& path) { static const std::regex pattern_replace("[\\\\\\/]"); path = std::regex_replace(path, pattern_replace, PHYSFS_getDirSeparator()); static const std::regex pattern_match("^.*[\\\\\\/]$"); if (std::regex_match(path, pattern_match)) path.append(PHYSFS_getDirSeparator()); }
int main(int argc, char **argv) { int i, err; static char filename[4096]; lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_newtable(L); for(i = 0; i < argc; i++) { lua_pushinteger(L, i + 1); lua_pushstring(L, argv[i]); lua_settable(L, -3); } lua_setglobal(L, "args"); lua_settop(L, 0); /* Temporarily initialize PhysicsFS so that we can append the base directory to package.cpath */ PHYSFS_init(argv[0]); lua_getglobal(L, "package"); lua_pushstring(L, PHYSFS_getBaseDir()); lua_pushstring(L, "?.so;"); lua_pushstring(L, PHYSFS_getDirSeparator()); lua_pushstring(L, "?.so;"); lua_getfield(L, -5, "cpath"); lua_concat(L, 5); lua_setfield(L, -2, "cpath"); lua_pushstring(L, PHYSFS_getBaseDir()); lua_pushstring(L, "?.dll;"); lua_pushstring(L, PHYSFS_getDirSeparator()); lua_pushstring(L, "?.dll;"); lua_getfield(L, -5, "cpath"); lua_concat(L, 5); lua_setfield(L, -2, "cpath"); lua_pop(L, 1); sprintf(filename, "%s%s%s", PHYSFS_getBaseDir(), PHYSFS_getDirSeparator(), "server"); PHYSFS_deinit(); if((err = luaL_dofile(L, filename))) { const char *message = lua_tostring(L, -1); fprintf(stderr, "Error: %s\n", message); return err; } lua_getglobal(L, "init"); if((err = lua_pcall(L, 0, 0, 0))) { const char *message = lua_tostring(L, -1); fprintf(stderr, "Error: %s\n", message); return err; } return 0; }
/*! * Register searchPath above the path with next lower priority * For information about what can be a search path, refer to PhysFS documentation */ void registerSearchPath(const char path[], unsigned int priority) { wzSearchPath *curSearchPath = searchPathRegistry, * tmpSearchPath = nullptr; tmpSearchPath = (wzSearchPath *)malloc(sizeof(*tmpSearchPath)); sstrcpy(tmpSearchPath->path, path); if (path[strlen(path) - 1] != *PHYSFS_getDirSeparator()) { sstrcat(tmpSearchPath->path, PHYSFS_getDirSeparator()); } tmpSearchPath->priority = priority; debug(LOG_WZ, "registerSearchPath: Registering %s at priority %i", path, priority); if (!curSearchPath) { searchPathRegistry = tmpSearchPath; searchPathRegistry->lowerPriority = nullptr; searchPathRegistry->higherPriority = nullptr; return; } while (curSearchPath->higherPriority && priority > curSearchPath->priority) { curSearchPath = curSearchPath->higherPriority; } while (curSearchPath->lowerPriority && priority < curSearchPath->priority) { curSearchPath = curSearchPath->lowerPriority; } if (priority < curSearchPath->priority) { tmpSearchPath->lowerPriority = curSearchPath->lowerPriority; tmpSearchPath->higherPriority = curSearchPath; } else { tmpSearchPath->lowerPriority = curSearchPath; tmpSearchPath->higherPriority = curSearchPath->higherPriority; } if (tmpSearchPath->lowerPriority) { tmpSearchPath->lowerPriority->higherPriority = tmpSearchPath; } if (tmpSearchPath->higherPriority) { tmpSearchPath->higherPriority->lowerPriority = tmpSearchPath; } }
void ResourceManager::searchAndAddArchives(const std::string &path, const std::string &ext, bool append) { const char *dirSep = PHYSFS_getDirSeparator(); char **list = PHYSFS_enumerateFiles(path.c_str()); for (char **i = list; *i != NULL; i++) { size_t len = strlen(*i); if (len > ext.length() && !ext.compare((*i)+(len - ext.length()))) { std::string file, realPath, archive; file = path + (*i); realPath = std::string(PHYSFS_getRealDir(file.c_str())); archive = realPath + dirSep + file; addToSearchPath(archive, append); } } PHYSFS_freeList(list); }
/*! * Tries to mount a list of directories, found in /basedir/subdir/<list>. * \param basedir Base directory * \param subdir A subdirectory of basedir * \param appendToPath Whether to append or prepend * \param checkList List of directories to check. NULL means any. */ void addSubdirs( const char * basedir, const char * subdir, const bool appendToPath, char * checkList[], bool addToModList ) { char tmpstr[PATH_MAX]; char buf[256]; char ** subdirlist = PHYSFS_enumerateFiles( subdir ); char ** i = subdirlist; while( *i != NULL ) { #ifdef DEBUG debug( LOG_NEVER, "addSubdirs: Examining subdir: [%s]", *i ); #endif // DEBUG if (*i[0] != '.' && (!checkList || inList(checkList, *i))) { snprintf(tmpstr, sizeof(tmpstr), "%s%s%s%s", basedir, subdir, PHYSFS_getDirSeparator(), *i); #ifdef DEBUG debug( LOG_NEVER, "addSubdirs: Adding [%s] to search path", tmpstr ); #endif // DEBUG if (addToModList) { addLoadedMod(*i); snprintf(buf, sizeof(buf), "mod: %s", *i); addDumpInfo(buf); } PHYSFS_addToSearchPath( tmpstr, appendToPath ); } i++; } PHYSFS_freeList( subdirlist ); }
/* extracts the dirname and the basename from the path */ static void splitPath(const char *path, char **dir, char **base) { char *ptr; const char *dirsep = NULL; *base = (char *)path; *dir = (char *)"."; dirsep = PHYSFS_getDirSeparator(); if (strlen(dirsep) == 1) { /* fast path. */ ptr = strrchr(path, *dirsep); } else { ptr = strstr(path, dirsep); if (ptr != NULL) { char *p = ptr; while (p != NULL) { ptr = p; p = strstr(p + 1, dirsep); } } } if (ptr != NULL) { size_t size = (size_t) (ptr - path); *dir = (char *) malloc(size + 1); memcpy(*dir, path, size); (*dir)[size] = '\0'; *base = ptr + strlen(dirsep); } }
/**Returns the full path to the file * \return path successful.*/ string File::GetAbsolutePath(){ string abs = PHYSFS_getRealDir( validName.c_str() ); abs += PHYSFS_getDirSeparator() + validName; return abs; }
void removeSubdirs( const char * basedir, const char * subdir, char * checkList[] ) { char tmpstr[PATH_MAX]; char ** subdirlist = PHYSFS_enumerateFiles( subdir ); char ** i = subdirlist; while( *i != NULL ) { #ifdef DEBUG debug( LOG_NEVER, "removeSubdirs: Examining subdir: [%s]", *i ); #endif // DEBUG if( !checkList || inList( checkList, *i ) ) { snprintf(tmpstr, sizeof(tmpstr), "%s%s%s%s", basedir, subdir, PHYSFS_getDirSeparator(), *i); #ifdef DEBUG debug( LOG_NEVER, "removeSubdirs: Removing [%s] from search path", tmpstr ); #endif // DEBUG if (!PHYSFS_removeFromSearchPath( tmpstr )) { #ifdef DEBUG // spams a ton! debug(LOG_NEVER, "Couldn't remove %s from search path because %s", tmpstr, PHYSFS_getLastError()); #endif // DEBUG } } i++; } PHYSFS_freeList( subdirlist ); }
static DirHandle *DIR_openArchive(const char *name, int forWriting) { const char *dirsep = PHYSFS_getDirSeparator(); DirHandle *retval = NULL; size_t namelen = strlen(name); size_t seplen = strlen(dirsep); BAIL_IF_MACRO(!DIR_isArchive(name, forWriting), ERR_UNSUPPORTED_ARCHIVE, NULL); retval = (DirHandle *) malloc(sizeof (DirHandle)); BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); retval->opaque = malloc(namelen + seplen + 1); if (retval->opaque == NULL) { free(retval); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ /* make sure there's a dir separator at the end of the string */ strcpy((char *) (retval->opaque), name); if (strcmp((name + namelen) - seplen, dirsep) != 0) strcat((char *) (retval->opaque), dirsep); retval->funcs = &__PHYSFS_DirFunctions_DIR; return(retval); } /* DIR_openArchive */
void vsFile::EnsureWriteDirectoryExists( const vsString &writeDirectoryName ) // static method { if ( !DirectoryExists(writeDirectoryName) ) { int mkdirResult = PHYSFS_mkdir( writeDirectoryName.c_str() ); vsAssert( mkdirResult != 0, vsFormatString("Failed to create directory '%s%s%s': %s", PHYSFS_getWriteDir(), PHYSFS_getDirSeparator(), writeDirectoryName.c_str(), PHYSFS_getLastError()) ); } }
std::string getSaveDir() { std::string saveDir = PHYSFS_getWriteDir(); if (Utils::endsWith(saveDir, "\\") == false && Utils::endsWith(saveDir, "/") == false) { saveDir += PHYSFS_getDirSeparator(); } return saveDir; }
std::string Resources::getRealWriteName(const char* filename) { const char* dir = PHYSFS_getWriteDir(); if (dir == 0) { PError << "no writedir defined" << endl; return NULL; } std::string realname = dir; realname += PHYSFS_getDirSeparator(); realname += filename; return realname; }
std::string Resources::getRealName(const char* filename) { const char* dir = PHYSFS_getRealDir(filename); if (dir == 0) { PError << "no such path '" << filename << "'" << endl; return NULL; }; std::string realname = dir; realname += PHYSFS_getDirSeparator(); realname += filename; return realname; }
std::string getRealWriteName(const char* filename) { const char* dir = PHYSFS_getWriteDir(); if (dir == 0) { throw Exception("no writedir defined"); } std::string realname = dir; realname += PHYSFS_getDirSeparator(); realname += filename; return realname; }
const char * basename(const char * filename) { const char * last_found = filename; const char * sep; do { sep = strstr(last_found, PHYSFS_getDirSeparator()); last_found = sep ? sep + 1 : last_found; } while (sep); return last_found; }
std::string getRealName(const char* filename) { const char* dir = PHYSFS_getRealDir(filename); if (dir == 0) { throw Exception("no such path '%s'", filename); } std::string realname = dir; realname += PHYSFS_getDirSeparator(); realname += filename; return realname; }
static void getPlatformUserDir(char * const tmpstr, size_t const size) { #if defined(WZ_OS_WIN) wchar_t tmpWStr[MAX_PATH]; if ( SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, tmpWStr ) ) ) { if (WideCharToMultiByte(CP_UTF8, 0, tmpWStr, -1, tmpstr, size, NULL, NULL) == 0) { debug(LOG_ERROR, "Encoding conversion error."); exit(1); } strlcat(tmpstr, PHYSFS_getDirSeparator(), size); } else #elif defined(WZ_OS_MAC) FSRef fsref; OSErr error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &fsref); if (!error) error = FSRefMakePath(&fsref, (UInt8 *) tmpstr, size); if (!error) strlcat(tmpstr, PHYSFS_getDirSeparator(), size); else #endif if (PHYSFS_getUserDir()) { strlcpy(tmpstr, PHYSFS_getUserDir(), size); // Use PhysFS supplied UserDir (As fallback on Windows / Mac, default on Linux) } // If PhysicsFS fails (might happen if environment variable HOME is unset or wrong) then use the current working directory else if (getCurrentDir(tmpstr, size)) { strlcat(tmpstr, PHYSFS_getDirSeparator(), size); } else { debug(LOG_FATAL, "Can't get UserDir?"); abort(); } }
void setupPHYSFS() { std::string separator = PHYSFS_getDirSeparator(); // Game should be playable out of the source package on all // platforms PHYSFS_addToSearchPath("data", 1); PHYSFS_addToSearchPath("data/gfx.zip", 1); PHYSFS_addToSearchPath("data/sounds.zip", 1); PHYSFS_addToSearchPath("data/scripts.zip", 1); PHYSFS_addToSearchPath("data/backgrounds.zip", 1); #if defined(WIN32) // Just write in installation directory PHYSFS_setWriteDir("data"); #else // handle the case when it is installed PHYSFS_addToSearchPath(BLOBBY_INSTALL_PREFIX "/share/blobby", 1); PHYSFS_addToSearchPath(BLOBBY_INSTALL_PREFIX "/share/blobby/gfx.zip", 1); PHYSFS_addToSearchPath(BLOBBY_INSTALL_PREFIX "/share/blobby/sounds.zip", 1); PHYSFS_addToSearchPath(BLOBBY_INSTALL_PREFIX "/share/blobby/scripts.zip", 1); PHYSFS_addToSearchPath(BLOBBY_INSTALL_PREFIX "/share/blobby/backgrounds.zip", 1); // Create a search path in the home directory and ensure that // all paths exist and are actually directories std::string userdir = PHYSFS_getUserDir(); std::string userAppend = ".blobby"; std::string homedir = userdir + userAppend; PHYSFS_addToSearchPath(userdir.c_str(), 0); PHYSFS_setWriteDir(userdir.c_str()); probeDir(userAppend); probeDir(userAppend + separator + "replays"); probeDir(userAppend + separator + "gfx"); probeDir(userAppend + separator + "sounds"); probeDir(userAppend + separator + "scripts"); probeDir(userAppend + separator + "backgrounds"); PHYSFS_removeFromSearchPath(userdir.c_str()); PHYSFS_setWriteDir(homedir.c_str()); PHYSFS_addToSearchPath(homedir.c_str(), 0); #if defined(GAMEDATADIR) // A global installation path makes only sense on non-Windows // platforms std::string basedir = GAMEDATADIR; PHYSFS_addToSearchPath(basedir.c_str(), 1); PHYSFS_addToSearchPath((basedir + separator + "gfx.zip").c_str(), 1); PHYSFS_addToSearchPath((basedir + separator + "sounds.zip").c_str(), 1); PHYSFS_addToSearchPath((basedir + separator + "scripts.zip").c_str(), 1); PHYSFS_addToSearchPath((basedir + separator + "backgrounds.zip").c_str(), 1); #endif #endif }
/**\brief Save an XML file for this player * \details The filename is by default the player's name. */ void Player::Save( string scenario ) { xmlDocPtr xmlPtr; LogMsg( INFO, "Creation of %s", GetFileName().c_str() ); // Create new XML Document xmlPtr = xmlNewDoc( BAD_CAST "1.0" ); xmlNodePtr root_node = ToXMLNode("player"); xmlDocSetRootElement(xmlPtr, root_node); xmlSaveFormatFileEnc( (std::string(PHYSFS_getWriteDir()) + std::string(PHYSFS_getDirSeparator()) + GetFileName()).c_str(), xmlPtr, "ISO-8859-1", 1); // Update and Save this player's info in the master players list. PlayerList::Instance()->GetPlayerInfo( GetName() )->Update( this, scenario ); PlayerList::Instance()->Save(); }
int PHYSFSX_getRealPath(const char *stdPath, char *realPath) { const char *realDir = PHYSFS_getRealDir(stdPath); const char *sep = PHYSFS_getDirSeparator(); char *p; if (!realDir) { realDir = PHYSFS_getWriteDir(); if (!realDir) return 0; } strncpy(realPath, realDir, PATH_MAX - 1); if (strlen(realPath) >= strlen(sep)) { p = realPath + strlen(realPath) - strlen(sep); if (strcmp(p, sep)) // no sep at end of realPath strncat(realPath, sep, PATH_MAX - 1 - strlen(realPath)); } if (strlen(stdPath) >= 1) if (*stdPath == '/') stdPath++; while (*stdPath) { if (*stdPath == '/') strncat(realPath, sep, PATH_MAX - 1 - strlen(realPath)); else { if (strlen(realPath) < PATH_MAX - 2) { p = realPath + strlen(realPath); p[0] = *stdPath; p[1] = '\0'; } } stdPath++; } return 1; }
static void *DIR_openArchive(const char *name, int forWriting) { const char *dirsep = PHYSFS_getDirSeparator(); char *retval = NULL; size_t namelen = strlen(name); size_t seplen = strlen(dirsep); /* !!! FIXME: when is this not called right before openArchive? */ BAIL_IF_MACRO(!DIR_isArchive(name, forWriting), ERR_UNSUPPORTED_ARCHIVE, 0); retval = allocator.Malloc(namelen + seplen + 1); BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); /* make sure there's a dir separator at the end of the string */ strcpy(retval, name); if (strcmp((name + namelen) - seplen, dirsep) != 0) strcat(retval, dirsep); return(retval); } /* DIR_openArchive */
void ResourceManager::discoverWorkDir(const std::string& appName, const std::string& existentFile) { // search for modules directory std::string sep = PHYSFS_getDirSeparator(); std::string possiblePaths[] = { "", g_resources.getBaseDir(), g_resources.getBaseDir() + ".." + sep, g_resources.getBaseDir() + ".." + sep + "share" + sep + appName + sep, g_resources.getBaseDir() + appName + sep }; bool found = false; for(const std::string& dir : possiblePaths) { // try to directory to modules path to see if it exists std::ifstream fin(dir + existentFile); if(fin) { g_logger.debug(stdext::format("Found work dir at '%s'", dir.c_str())); m_workDir = dir; found = true; break; } } if(!found) g_logger.fatal(stdext::format("Unable to find %s, the application cannot be initialized.", existentFile)); }
std::string FileSystem::getDirSeparator() { return PHYSFS_getDirSeparator(); }
/*! * \brief Adds default data dirs * * Priority: * Lower loads first. Current: * -datadir > User's home dir > source tree data > AutoPackage > BaseDir > DEFAULT_DATADIR * * Only -datadir and home dir are allways examined. Others only if data still not found. * * We need ParseCommandLine, before we can add any mods... * * \sa rebuildSearchPath */ static void scanDataDirs( void ) { char tmpstr[PATH_MAX], prefix[PATH_MAX]; char* separator; #if defined(WZ_OS_MAC) // version-independent location for video files registerSearchPath("/Library/Application Support/Warzone 2100/", 1); #endif // Find out which PREFIX we are in... sstrcpy(prefix, PHYSFS_getBaseDir()); separator = strrchr(prefix, *PHYSFS_getDirSeparator()); if (separator) { *separator = '\0'; // Trim ending '/', which getBaseDir always provides separator = strrchr(prefix, *PHYSFS_getDirSeparator()); if (separator) { *separator = '\0'; // Skip the last dir from base dir } } // Commandline supplied datadir if( strlen( datadir ) != 0 ) registerSearchPath( datadir, 1 ); // User's home dir registerSearchPath( PHYSFS_getWriteDir(), 2 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Data in source tree sstrcpy(tmpstr, prefix); sstrcat(tmpstr, "/data/"); registerSearchPath( tmpstr, 3 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Relocation for AutoPackage sstrcpy(tmpstr, prefix); sstrcat(tmpstr, "/share/warzone2100/"); registerSearchPath( tmpstr, 4 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Program dir registerSearchPath( PHYSFS_getBaseDir(), 5 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Guessed fallback default datadir on Unix registerSearchPath( WZ_DATADIR, 6 ); rebuildSearchPath( mod_multiplay, true ); } } } } #ifdef WZ_OS_MAC if( !PHYSFS_exists("gamedesc.lev") ) { CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); char resourcePath[PATH_MAX]; if( CFURLGetFileSystemRepresentation( resourceURL, true, (UInt8 *) resourcePath, PATH_MAX) ) { chdir( resourcePath ); registerSearchPath( "data", 7 ); rebuildSearchPath( mod_multiplay, true ); } else { debug( LOG_ERROR, "Could not change to resources directory." ); } if( resourceURL != NULL ) { CFRelease( resourceURL ); } } #endif /** Debugging and sanity checks **/ printSearchPath(); if( PHYSFS_exists("gamedesc.lev") ) { debug( LOG_WZ, "gamedesc.lev found at %s", PHYSFS_getRealDir( "gamedesc.lev" ) ); } else { debug( LOG_FATAL, "Could not find game data. Aborting." ); exit(1); } }
static void getPlatformUserDir(char * const tmpstr, size_t const size) { #if defined(WZ_OS_WIN) // When WZ_PORTABLE is passed, that means we want the config directory at the same location as the program file DWORD dwRet; wchar_t tmpWStr[MAX_PATH]; #ifndef WZ_PORTABLE if ( SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, tmpWStr ) ) ) { #else if (dwRet = GetCurrentDirectoryW(MAX_PATH, tmpWStr)) { if(dwRet > MAX_PATH) { debug(LOG_FATAL, "Buffer exceeds maximum path to create directory. Exiting."); exit(1); } #endif if (WideCharToMultiByte(CP_UTF8, 0, tmpWStr, -1, tmpstr, size, NULL, NULL) == 0) { debug(LOG_FATAL, "Config directory encoding conversion error."); exit(1); } strlcat(tmpstr, PHYSFS_getDirSeparator(), size); } else #elif defined(WZ_OS_MAC) FSRef fsref; OSErr error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &fsref); if (!error) error = FSRefMakePath(&fsref, (UInt8 *) tmpstr, size); if (!error) strlcat(tmpstr, PHYSFS_getDirSeparator(), size); else #endif if (PHYSFS_getUserDir()) { strlcpy(tmpstr, PHYSFS_getUserDir(), size); // Use PhysFS supplied UserDir (As fallback on Windows / Mac, default on Linux) } // If PhysicsFS fails (might happen if environment variable HOME is unset or wrong) then use the current working directory else if (getCurrentDir(tmpstr, size)) { strlcat(tmpstr, PHYSFS_getDirSeparator(), size); } else { debug(LOG_FATAL, "Can't get UserDir?"); abort(); } } static void initialize_ConfigDir(void) { char tmpstr[PATH_MAX] = { '\0' }; if (strlen(configdir) == 0) { getPlatformUserDir(tmpstr, sizeof(tmpstr)); if (!PHYSFS_setWriteDir(tmpstr)) // Workaround for PhysFS not creating the writedir as expected. { debug(LOG_FATAL, "Error setting write directory to \"%s\": %s", tmpstr, PHYSFS_getLastError()); exit(1); } if (!PHYSFS_mkdir(WZ_WRITEDIR)) // s.a. { debug(LOG_FATAL, "Error creating directory \"%s\": %s", WZ_WRITEDIR, PHYSFS_getLastError()); exit(1); } // Append the Warzone subdir sstrcat(tmpstr, WZ_WRITEDIR); sstrcat(tmpstr, PHYSFS_getDirSeparator()); if (!PHYSFS_setWriteDir(tmpstr)) { debug( LOG_FATAL, "Error setting write directory to \"%s\": %s", tmpstr, PHYSFS_getLastError() ); exit(1); } } else { sstrcpy(tmpstr, configdir); // Make sure that we have a directory separator at the end of the string if (tmpstr[strlen(tmpstr) - 1] != PHYSFS_getDirSeparator()[0]) sstrcat(tmpstr, PHYSFS_getDirSeparator()); debug(LOG_WZ, "Using custom configuration directory: %s", tmpstr); if (!PHYSFS_setWriteDir(tmpstr)) // Workaround for PhysFS not creating the writedir as expected. { debug(LOG_FATAL, "Error setting write directory to \"%s\": %s", tmpstr, PHYSFS_getLastError()); exit(1); } // NOTE: This is currently only used for mingw builds for now. #if defined (WZ_CC_MINGW) if (!OverrideRPTDirectory(tmpstr)) { // since it failed, we just use our default path, and not the user supplied one. debug(LOG_ERROR, "Error setting exception hanlder to use directory %s", tmpstr); } #endif } // User's home dir first so we allways see what we write PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), PHYSFS_PREPEND ); PHYSFS_permitSymbolicLinks(1); debug(LOG_WZ, "Write dir: %s", PHYSFS_getWriteDir()); debug(LOG_WZ, "Base dir: %s", PHYSFS_getBaseDir()); }
// Initialise PhysicsFS, set up basic search paths and add arguments from .ini file. // The .ini file can be in either the user directory or the same directory as the program. // The user directory is searched first. void PHYSFSX_init(int argc, char *argv[]) { #if defined(__unix__) const char *path = NULL; #endif #ifdef macintosh // Mac OS 9 char base_dir[PATH_MAX]; int bundle = 0; #else #define base_dir PHYSFS_getBaseDir() #endif PHYSFS_init(argv[0]); atexit(PHYSFSX_deinit); PHYSFS_permitSymbolicLinks(1); #ifdef macintosh strcpy(base_dir, PHYSFS_getBaseDir()); if (strstr(base_dir, ".app:Contents:MacOSClassic")) // the Mac OS 9 program is still in the .app bundle { char *p; bundle = 1; if (base_dir[strlen(base_dir) - 1] == ':') base_dir[strlen(base_dir) - 1] = '\0'; p = strrchr(base_dir, ':'); *p = '\0'; // path to 'Contents' p = strrchr(base_dir, ':'); *p = '\0'; // path to bundle p = strrchr(base_dir, ':'); *p = '\0'; // path to directory containing bundle } #endif #if (defined(__APPLE__) && defined(__MACH__)) // others? chdir(base_dir); // make sure relative hogdir paths work #endif #if defined(__unix__) char fullPath[PATH_MAX + 5]; # if !(defined(__APPLE__) && defined(__MACH__)) path = "~/.d2x-rebirth/"; # else path = "~/Library/Preferences/D2X Rebirth/"; # endif if (path[0] == '~') // yes, this tilde can be put before non-unix paths. { const char *home = PHYSFS_getUserDir(); strcpy(fullPath, home); // prepend home to the path path++; if (*path == *PHYSFS_getDirSeparator()) path++; strncat(fullPath, path, PATH_MAX + 5 - strlen(home)); } else strncpy(fullPath, path, PATH_MAX + 5); PHYSFS_setWriteDir(fullPath); if (!PHYSFS_getWriteDir()) { // need to make it char *p; char ancestor[PATH_MAX + 5]; // the directory which actually exists char child[PATH_MAX + 5]; // the directory relative to the above we're trying to make strcpy(ancestor, fullPath); while (!PHYSFS_getWriteDir() && ((p = strrchr(ancestor, *PHYSFS_getDirSeparator())))) { if (p[1] == 0) { // separator at the end (intended here, for safety) *p = 0; // kill this separator if (!((p = strrchr(ancestor, *PHYSFS_getDirSeparator())))) break; // give up, this is (usually) the root directory } p[1] = 0; // go to parent PHYSFS_setWriteDir(ancestor); } strcpy(child, fullPath + strlen(ancestor)); for (p = child; (p = strchr(p, *PHYSFS_getDirSeparator())); p++) *p = '/'; PHYSFS_mkdir(child); PHYSFS_setWriteDir(fullPath); } PHYSFS_addToSearchPath(PHYSFS_getWriteDir(), 1); #endif PHYSFS_addToSearchPath(base_dir, 1); InitArgs( argc,argv ); PHYSFS_removeFromSearchPath(base_dir); if (!PHYSFS_getWriteDir()) { PHYSFS_setWriteDir(base_dir); if (!PHYSFS_getWriteDir()) Error("can't set write dir: %s\n", PHYSFS_getLastError()); else PHYSFS_addToSearchPath(PHYSFS_getWriteDir(), 0); } //tell PHYSFS where hogdir is if (GameArg.SysHogDir) PHYSFS_addToSearchPath(GameArg.SysHogDir,1); #if defined(__unix__) else if (!GameArg.SysNoHogDir) PHYSFS_addToSearchPath(SHAREPATH, 1); #endif PHYSFSX_addRelToSearchPath("data", 1); // 'Data' subdirectory // For Macintosh, add the 'Resources' directory in the .app bundle to the searchpaths #if defined(__APPLE__) && defined(__MACH__) { ProcessSerialNumber psn = { 0, kCurrentProcess }; FSRef fsref; OSStatus err; err = GetProcessBundleLocation(&psn, &fsref); if (err == noErr) err = FSRefMakePath(&fsref, (ubyte *)fullPath, PATH_MAX); if (err == noErr) { strncat(fullPath, "/Contents/Resources/", PATH_MAX + 4 - strlen(fullPath)); fullPath[PATH_MAX + 4] = '\0'; PHYSFS_addToSearchPath(fullPath, 1); } } #elif defined(macintosh) if (bundle) { base_dir[strlen(base_dir)] = ':'; // go back in the bundle base_dir[strlen(base_dir)] = ':'; // go back in 'Contents' strncat(base_dir, ":Resources:", PATH_MAX - 1 - strlen(base_dir)); base_dir[PATH_MAX - 1] = '\0'; PHYSFS_addToSearchPath(base_dir, 1); } #endif }
int realmain(int argc, char *argv[]) { // The libcrypto startup stuff... May or may not actually be needed for anything at all. ERR_load_crypto_strings(); // This is needed for descriptive error messages. OpenSSL_add_all_algorithms(); // Don't actually use the EVP functions, so probably not needed. OPENSSL_config(nullptr); // What does this actually do? #ifdef WZ_OS_WIN RAND_screen(); // Uses a screenshot as a random seed, on systems lacking /dev/random. #endif wzMain(argc, argv); int utfargc = argc; const char** utfargv = (const char**)argv; #ifdef WZ_OS_MAC cocoaInit(); #endif debug_init(); debug_register_callback( debug_callback_stderr, NULL, NULL, NULL ); #if defined(WZ_OS_WIN) && defined(DEBUG_INSANE) debug_register_callback( debug_callback_win32debug, NULL, NULL, NULL ); #endif // WZ_OS_WIN && DEBUG_INSANE // ***** // NOTE: Try *NOT* to use debug() output routines without some other method of informing the user. All this output is sent to /dev/nul at this point on some platforms! // ***** if (!getUTF8CmdLine(&utfargc, &utfargv)) { return EXIT_FAILURE; } QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); // make Qt treat all C strings in Warzone as UTF-8 setupExceptionHandler(utfargc, utfargv, version_getFormattedVersionString()); /*** Initialize PhysicsFS ***/ initialize_PhysicsFS(utfargv[0]); /*** Initialize translations ***/ initI18n(); // find early boot info if (!ParseCommandLineEarly(utfargc, utfargv)) { return EXIT_FAILURE; } /* Initialize the write/config directory for PhysicsFS. * This needs to be done __after__ the early commandline parsing, * because the user might tell us to use an alternative configuration * directory. */ initialize_ConfigDir(); /*** Initialize directory structure ***/ make_dir(ScreenDumpPath, "screenshots", NULL); make_dir(SaveGamePath, "savegames", NULL); PHYSFS_mkdir("savegames/campaign"); PHYSFS_mkdir("savegames/skirmish"); make_dir(MultiCustomMapsPath, "maps", NULL); // MUST have this to prevent crashes when getting map PHYSFS_mkdir("music"); PHYSFS_mkdir("logs"); // a place to hold our netplay, mingw crash reports & WZ logs PHYSFS_mkdir("userdata"); // a place to store per-mod data user generated data memset(rulesettag, 0, sizeof(rulesettag)); // tag to add to userdata to find user generated stuff make_dir(MultiPlayersPath, "multiplay", NULL); make_dir(MultiPlayersPath, "multiplay", "players"); if (!customDebugfile) { // there was no custom debug file specified (--debug-file=blah) // so we use our write directory to store our logs. time_t aclock; struct tm *newtime; char buf[PATH_MAX]; time( &aclock ); // Get time in seconds newtime = localtime( &aclock ); // Convert time to struct // Note: We are using fopen(), and not physfs routines to open the file // log name is logs/(or \)WZlog-MMDD_HHMMSS.txt snprintf(buf, sizeof(buf), "%slogs%sWZlog-%02d%02d_%02d%02d%02d.txt", PHYSFS_getWriteDir(), PHYSFS_getDirSeparator(), newtime->tm_mon + 1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec ); debug_register_callback( debug_callback_file, debug_callback_file_init, debug_callback_file_exit, buf ); // FIXME: Change this to LOG_WZ on next release debug(LOG_INFO, "Using %s debug file", buf); } // NOTE: it is now safe to use debug() calls to make sure output gets captured. check_Physfs(); debug(LOG_WZ, "Warzone 2100 - %s", version_getFormattedVersionString()); debug(LOG_WZ, "Using language: %s", getLanguage()); debug(LOG_WZ, "Backend: %s", BACKEND); debug(LOG_MEMORY, "sizeof: SIMPLE_OBJECT=%ld, BASE_OBJECT=%ld, DROID=%ld, STRUCTURE=%ld, FEATURE=%ld, PROJECTILE=%ld", (long)sizeof(SIMPLE_OBJECT), (long)sizeof(BASE_OBJECT), (long)sizeof(DROID), (long)sizeof(STRUCTURE), (long)sizeof(FEATURE), (long)sizeof(PROJECTILE)); /* Put in the writedir root */ sstrcpy(KeyMapPath, "keymap.map"); // initialise all the command line states war_SetDefaultStates(); debug(LOG_MAIN, "initializing"); PhysicsEngineHandler engine; // register abstract physfs filesystem loadConfig(); // parse the command line if (!ParseCommandLine(utfargc, utfargv)) { return EXIT_FAILURE; } // Save new (commandline) settings saveConfig(); // Find out where to find the data scanDataDirs(); // Now we check the mods to see if they exist or not (specified on the command line) // They are all capped at 100 mods max(see clparse.c) // FIX ME: I know this is a bit hackish, but better than nothing for now? { char *modname; char modtocheck[256]; int i = 0; int result = 0; // check global mods for(i=0; i < 100; i++) { modname = global_mods[i]; if (modname == NULL) { break; } ssprintf(modtocheck, "mods/global/%s", modname); result = PHYSFS_exists(modtocheck); result |= PHYSFS_isDirectory(modtocheck); if (!result) { debug(LOG_ERROR, "The (global) mod (%s) you have specified doesn't exist!", modname); } else { info("(global) mod (%s) is enabled", modname); } } // check campaign mods for(i=0; i < 100; i++) { modname = campaign_mods[i]; if (modname == NULL) { break; } ssprintf(modtocheck, "mods/campaign/%s", modname); result = PHYSFS_exists(modtocheck); result |= PHYSFS_isDirectory(modtocheck); if (!result) { debug(LOG_ERROR, "The mod_ca (%s) you have specified doesn't exist!", modname); } else { info("mod_ca (%s) is enabled", modname); } } // check multiplay mods for(i=0; i < 100; i++) { modname = multiplay_mods[i]; if (modname == NULL) { break; } ssprintf(modtocheck, "mods/multiplay/%s", modname); result = PHYSFS_exists(modtocheck); result |= PHYSFS_isDirectory(modtocheck); if (!result) { debug(LOG_ERROR, "The mod_mp (%s) you have specified doesn't exist!", modname); } else { info("mod_mp (%s) is enabled", modname); } } } if (!wzMain2(war_getFSAA(), war_getFullscreen(), war_GetVsync())) { return EXIT_FAILURE; } int w = pie_GetVideoBufferWidth(); int h = pie_GetVideoBufferHeight(); char buf[256]; ssprintf(buf, "Video Mode %d x %d (%s)", w, h, war_getFullscreen() ? "fullscreen" : "window"); addDumpInfo(buf); debug(LOG_MAIN, "Final initialization"); if (!frameInitialise()) { return EXIT_FAILURE; } if (!screenInitialise()) { return EXIT_FAILURE; } if (!pie_LoadShaders()) { return EXIT_FAILURE; } war_SetWidth(pie_GetVideoBufferWidth()); war_SetHeight(pie_GetVideoBufferHeight()); pie_SetFogStatus(false); pie_ScreenFlip(CLEAR_BLACK); pal_Init(); pie_LoadBackDrop(SCREEN_RANDOMBDROP); pie_SetFogStatus(false); pie_ScreenFlip(CLEAR_BLACK); if (!systemInitialise()) { return EXIT_FAILURE; } //set all the pause states to false setAllPauseStates(false); // Copy this info to be used by the crash handler for the dump file ssprintf(buf,"Using Backend: %s", BACKEND); addDumpInfo(buf); ssprintf(buf,"Using language: %s", getLanguageName()); addDumpInfo(buf); // Do the game mode specific initialisation. switch(GetGameMode()) { case GS_TITLE_SCREEN: startTitleLoop(); break; case GS_SAVEGAMELOAD: initSaveGameLoad(); break; case GS_NORMAL: startGameLoop(); break; default: debug(LOG_ERROR, "Weirdy game status, I'm afraid!!"); break; } #if defined(WZ_CC_MSVC) && defined(DEBUG) debug_MEMSTATS(); #endif debug(LOG_MAIN, "Entering main loop"); wzMain3(); saveConfig(); systemShutdown(); #ifdef WZ_OS_WIN // clean up the memory allocated for the command line conversion for (int i=0; i<argc; i++) { const char*** const utfargvF = &utfargv; free((void *)(*utfargvF)[i]); } free(utfargv); #endif wzShutdown(); debug(LOG_MAIN, "Completed shutting down Warzone 2100"); return EXIT_SUCCESS; }
void updateDirSeparator() { dirSeparator = PHYSFS_getDirSeparator(); }
/*! * \brief Rebuilds the PHYSFS searchPath with mode specific subdirs * * Priority: * maps > mods > base > base.wz */ bool rebuildSearchPath(searchPathMode mode, bool force, const char *current_map) { static searchPathMode current_mode = mod_clean; static std::string current_current_map; wzSearchPath * curSearchPath = searchPathRegistry; char tmpstr[PATH_MAX] = "\0"; if (mode != current_mode || (current_map != NULL? current_map : "") != current_current_map || force || (use_override_mods && strcmp(override_mod_list, getModList()))) { if (mode != mod_clean) { rebuildSearchPath( mod_clean, false ); } current_mode = mode; current_current_map = current_map != NULL? current_map : ""; // Start at the lowest priority while( curSearchPath->lowerPriority ) curSearchPath = curSearchPath->lowerPriority; switch ( mode ) { case mod_clean: debug(LOG_WZ, "Cleaning up"); clearLoadedMods(); while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Removing [%s] from search path", curSearchPath->path); #endif // DEBUG // Remove maps and mods removeSubdirs( curSearchPath->path, "maps", NULL ); removeSubdirs( curSearchPath->path, "mods/music", NULL ); removeSubdirs( curSearchPath->path, "mods/global", NULL ); removeSubdirs( curSearchPath->path, "mods/campaign", NULL ); removeSubdirs( curSearchPath->path, "mods/multiplay", NULL ); removeSubdirs( curSearchPath->path, "mods/autoload", NULL ); // Remove multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); PHYSFS_removeFromSearchPath( tmpstr ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); PHYSFS_removeFromSearchPath( tmpstr ); // Remove plain dir PHYSFS_removeFromSearchPath( curSearchPath->path ); // Remove base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_removeFromSearchPath( tmpstr ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_removeFromSearchPath( tmpstr ); // remove video search path as well sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_removeFromSearchPath( tmpstr ); curSearchPath = curSearchPath->higherPriority; } break; case mod_campaign: debug(LOG_WZ, "*** Switching to campaign mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) curSearchPath = curSearchPath->lowerPriority; while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and campaign mods PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false ); addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true ); addSubdirs( curSearchPath->path, "mods/campaign", PHYSFS_APPEND, use_override_mods?override_mods:campaign_mods, true ); if (!PHYSFS_removeFromSearchPath( curSearchPath->path )) { debug(LOG_WZ, "* Failed to remove path %s again", curSearchPath->path); } // Add plain dir PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); curSearchPath = curSearchPath->higherPriority; } break; case mod_multiplay: debug(LOG_WZ, "*** Switching to multiplay mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } // Add the selected map first, for mapmod support if (current_map != NULL) { QString realPathAndDir = QString::fromUtf8(PHYSFS_getRealDir(current_map)) + current_map; realPathAndDir.replace('/', PHYSFS_getDirSeparator()); // Windows fix PHYSFS_addToSearchPath(realPathAndDir.toUtf8().constData(), PHYSFS_APPEND); } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) curSearchPath = curSearchPath->lowerPriority; while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and multiplay mods PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false ); addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true ); addSubdirs( curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, use_override_mods?override_mods:multiplay_mods, true ); PHYSFS_removeFromSearchPath( curSearchPath->path ); // Add multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); // Add plain dir PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); curSearchPath = curSearchPath->higherPriority; } break; default: debug(LOG_ERROR, "Can't switch to unknown mods %i", mode); return false; } if (use_override_mods && mode != mod_clean) { if (strcmp(getModList(),override_mod_list)) { debug(LOG_POPUP, _("The required mod could not be loaded: %s\n\nWarzone will try to load the game without it."), override_mod_list); } clearOverrideMods(); current_mode = mod_override; } // User's home dir must be first so we allways see what we write PHYSFS_removeFromSearchPath(PHYSFS_getWriteDir()); PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), PHYSFS_PREPEND ); #ifdef DEBUG printSearchPath(); #endif // DEBUG } else if (use_override_mods) { // override mods are already the same as current mods, so no need to do anything clearOverrideMods(); } return true; }