Пример #1
0
const char *physfsDrive::GetInfo() {
	char **files = PHYSFS_getSearchPath(), **list = files;
	sprintf(info,"PHYSFS directory %s in ",basedir);
	while (*files != NULL) {
		strcat(info,*files++);
		strcat(info,", ");
	}
	if (PHYSFS_getWriteDir() != NULL) {
		strcat(info,"writing to ");
		strcat(info,PHYSFS_getWriteDir());
	} else {
		strcat(info,"read-only");
	}
	PHYSFS_freeList(list);
	return info;
}
Пример #2
0
/***************************************************************************
	Make a directory in write path and set a variable to point to it.
***************************************************************************/
static void make_dir(char *dest, const char *dirname, const char *subdir)
{
	strcpy(dest, dirname);
	if (subdir != NULL)
	{
		strcat(dest, "/");
		strcat(dest, subdir);
	}
	{
		size_t l = strlen(dest);

		if (dest[l - 1] != '/')
		{
			dest[l] = '/';
			dest[l + 1] = '\0';
		}
	}
	PHYSFS_mkdir(dest);
	if (!PHYSFS_mkdir(dest))
	{
		debug(LOG_FATAL, "Unable to create directory \"%s\" in write dir \"%s\"!",
		      dest, PHYSFS_getWriteDir());
		exit(EXIT_FAILURE);
	}
}
Пример #3
0
void wzPerfShutdown()
{
	if (perfList.size() == 0)
	{
		return;
	}
	QString ourfile = PHYSFS_getWriteDir();
	ourfile.append("gfx-performance.csv");
	// write performance counter list to file
	QFile perf(ourfile);
	perf.open(QIODevice::WriteOnly);
	perf.write("START, EFF, TERRAIN, LOAD, PRTCL, WATER, MODELS, MISC\n");
	for (int i = 0; i < perfList.size(); i++)
	{
		QString line;
		line += QString::number(perfList[i].counters[PERF_START_FRAME]);
		for (int j = 1; j < PERF_COUNT; j++)
		{
			line += ", " + QString::number(perfList[i].counters[j]);
		}
		line += "\n";
		perf.write(line.toUtf8());
	}
	// all done, clear data
	perfStarted = false;
	perfList.clear();
	queryActive = PERF_COUNT;
}
Пример #4
0
void vsLog_Show()
{
	const char*writeDir = PHYSFS_getWriteDir();
	if ( writeDir )
	{
		vsSystem::Launch(writeDir);
	}
}
Пример #5
0
std::string CResourceManager::GetSaveLocation()
{
    if (PHYSFS_isInit())
    {
        return PHYSFS_getWriteDir();
    }
    return "";
}
Пример #6
0
physfsDrive::physfsDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid)
		   :localDrive(startdir,_bytes_sector,_sectors_cluster,_total_clusters,_free_clusters,_mediaid) {

	char newname[CROSS_LEN+1];

	/* No writedir given, use capture directory */
	if(startdir[0] == ':') {
		strcpy(newname,capturedir.c_str());
		strcat(newname,startdir);
	} else {
		strcpy(newname,startdir);
	}

	CROSS_FILENAME(newname);	
	if (!physfs_used) {
		PHYSFS_init("");
		PHYSFS_permitSymbolicLinks(1);
	}

	physfs_used++;
	char *lastdir = newname;
	char *dir = strchr(lastdir+(((lastdir[0]|0x20) >= 'a' && (lastdir[0]|0x20) <= 'z')?2:0),':');
	while (dir) {
		*dir++ = 0;
		if((lastdir == newname) && !strchr(dir+(((dir[0]|0x20) >= 'a' && (dir[0]|0x20) <= 'z')?2:0),':')) {
			// If the first parameter is a directory, the next one has to be the archive file,
			// do not confuse it with basedir if trailing : is not there!
			int tmp = strlen(dir)-1;
			dir[tmp++] = ':';
			dir[tmp++] = CROSS_FILESPLIT;
			dir[tmp] = '\0';
		}
		if (*lastdir && PHYSFS_addToSearchPath(lastdir,true) == 0) {
			LOG_MSG("PHYSFS couldn't add '%s': %s",lastdir,PHYSFS_getLastError());
		}
		lastdir = dir;
		dir = strchr(lastdir+(((lastdir[0]|0x20) >= 'a' && (lastdir[0]|0x20) <= 'z')?2:0),':');
	}
	const char *oldwrite = PHYSFS_getWriteDir();
	if (oldwrite) oldwrite = strdup(oldwrite);
	if (!PHYSFS_setWriteDir(newname)) {
		if (!oldwrite)
			LOG_MSG("PHYSFS can't use '%s' for writing, you might encounter problems",newname);
		else
			PHYSFS_setWriteDir(oldwrite);
	}
	if (oldwrite) free((char *)oldwrite);
	
	strcpy(basedir,lastdir);

	allocation.bytes_sector=_bytes_sector;
	allocation.sectors_cluster=_sectors_cluster;
	allocation.total_clusters=_total_clusters;
	allocation.free_clusters=_free_clusters;
	allocation.mediaid=_mediaid;

	dirCache.SetBaseDir(basedir, this);
}
Пример #7
0
	std::vector<std::string> getSaveDirList()
	{
		auto writeDir = PHYSFS_getWriteDir();
		if (writeDir != nullptr)
		{
			return geDirList("", writeDir);
		}
		return {};
	}
Пример #8
0
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()) );
	}
}
Пример #9
0
	std::string getSaveDir()
	{
		std::string saveDir = PHYSFS_getWriteDir();
		if (Utils::endsWith(saveDir, "\\") == false &&
			Utils::endsWith(saveDir, "/") == false)
		{
			saveDir += PHYSFS_getDirSeparator();
		}
		return saveDir;
	}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
void probeDir(const std::string& dirname)
{
    if (PHYSFS_isDirectory(dirname.c_str()) == 0)
    {
        if (PHYSFS_exists(dirname.c_str()))
        {
            PHYSFS_delete(dirname.c_str());
        }
        if (PHYSFS_mkdir(dirname.c_str()))
        {
            std::cout << PHYSFS_getWriteDir() <<
                dirname << " created" << std::endl;
        }
        else
        {
            std::cout << "Warning: Creation of" << 
                PHYSFS_getWriteDir() << dirname <<
                " failed!" << std::endl;
        }
    }
}
Пример #13
0
 void print_search_path()
 {
   const char* writedir = PHYSFS_getWriteDir();
   log_info << "PhysfsWritedDir: " << (writedir ? writedir : "(null)") << std::endl;
   log_info << "PhysfsSearchPath:" << std::endl;
   char** searchpath = PHYSFS_getSearchPath();
   for(char** i = searchpath; *i != NULL; ++i)
   {
     log_info << "  " << *i << std::endl;
   }
   PHYSFS_freeList(searchpath);
 }
Пример #14
0
	bool deleteAll(const char* filePath, bool deleteRoot)
	{
		PHYSFS_Stat fileStat;
		if (PHYSFS_stat(filePath, &fileStat) == 0)
		{
			return false;
		}
		bool ret = false;
		if (fileStat.filetype == PHYSFS_FILETYPE_DIRECTORY)
		{
			auto paths = PHYSFS_enumerateFiles(filePath);
			if (paths != nullptr)
			{
				auto writeDir = PHYSFS_getWriteDir();
				if (writeDir != nullptr)
				{
					for (char** path = paths; *path != nullptr; path++)
					{
						auto fullPath = std::string(filePath) + '/' + *path;
						if (PHYSFS_stat(fullPath.c_str(), &fileStat) == 0)
						{
							continue;
						}
						if (fileStat.filetype == PHYSFS_FILETYPE_DIRECTORY)
						{
							deleteAll(fullPath.c_str(), true);
						}
						else
						{
							auto realDir = PHYSFS_getRealDir(fullPath.c_str());
							if (realDir != nullptr)
							{
								if (std::strcmp(writeDir, realDir) == 0)
								{
									ret = PHYSFS_delete(fullPath.c_str()) != 0;
								}
							}
						}
					}
				}
				PHYSFS_freeList(paths);
			}
			if (deleteRoot == true)
			{
				ret = PHYSFS_delete(filePath) != 0;
			}
		}
		else
		{
			ret = PHYSFS_delete(filePath) != 0;
		}
		return ret;
	}
Пример #15
0
// returns -1 if error
// Gets bytes free in current write dir
PHYSFS_sint64 PHYSFSX_getFreeDiskSpace()
{
#if defined(__linux__) || (defined(__MACH__) && defined(__APPLE__))
	struct statfs sfs;
	
	if (!statfs(PHYSFS_getWriteDir(), &sfs))
		return (PHYSFS_sint64)(sfs.f_bavail * sfs.f_bsize);
	
	return -1;
#else
	return 0x7FFFFFFF;
#endif
}
Пример #16
0
	bool deleteFile(const char* filePath) noexcept
	{
		auto writeDir = PHYSFS_getWriteDir();
		auto realDir = PHYSFS_getRealDir(filePath);
		if (writeDir != nullptr && realDir != nullptr)
		{
			if (strcmp(writeDir, realDir) == 0)
			{
				return PHYSFS_delete(filePath) != 0;
			}
		}
		return false;
	}
Пример #17
0
std::map<std::string, EcKey::Key> const &getKnownPlayers()
{
	if (knownPlayersIni == nullptr)
	{
		knownPlayersIni = new QSettings(PHYSFS_getWriteDir() + QString("/") + "knownPlayers.ini", QSettings::IniFormat);
		QStringList names = knownPlayersIni->allKeys();
		for (int i = 0; i < names.size(); ++i)
		{
			knownPlayers[names[i].toUtf8().constData()] = base64Decode(knownPlayersIni->value(names[i]).toString().toStdString());
		}
	}
	return knownPlayers;
}
Пример #18
0
void FileSystem::probeDir(const std::string& dirname)
{
	if ( !isDirectory(dirname) )
	{
		if (exists(dirname))
		{
			/// \todo simple delete such files without a warning???
			deleteFile(dirname);
		}
		
		if (mkdir(dirname))
		{
			std::cout << PHYSFS_getWriteDir() <<
				dirname << " created" << std::endl;
		}
		 else
		{
			std::cout << "Warning: Creation of" << 
				PHYSFS_getWriteDir() << dirname <<
				" failed!" << std::endl;
		}
	}
}
Пример #19
0
/**\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();
}
Пример #20
0
bool physfsFile::prepareWrite() {
	const char *wdir = PHYSFS_getWriteDir();
	if (wdir == NULL) {
		LOG_MSG("PHYSFS could not fulfill write request: no write directory set.");
		return false;
	}
	//LOG_MSG("Goto write (%s at %i)",pname,PHYSFS_tell(fhandle));
	const char *fdir = PHYSFS_getRealDir(pname);
	PHYSFS_uint64 pos = PHYSFS_tell(fhandle);
	char *slash = strrchr(pname,'/');
	if (slash && slash != pname) {
		*slash = 0;
		PHYSFS_mkdir(pname);
		*slash = '/';
	}
	if (strcmp(fdir,wdir)) { /* we need COW */
		//LOG_MSG("COW",pname,PHYSFS_tell(fhandle));
		PHYSFS_file *whandle = PHYSFS_openWrite(pname);
		if (whandle == NULL) {
			LOG_MSG("PHYSFS copy-on-write failed: %s.",PHYSFS_getLastError());
			return false;
		}
		char buffer[65536];
		PHYSFS_sint64 size;
		PHYSFS_seek(fhandle, 0);
		while ((size = PHYSFS_read(fhandle,buffer,1,65536)) > 0) {
			if (PHYSFS_write(whandle,buffer,1,(PHYSFS_uint32)size) != size) {
				LOG_MSG("PHYSFS copy-on-write failed: %s.",PHYSFS_getLastError());
				PHYSFS_close(whandle);
				return false;
			}
		}
		PHYSFS_seek(whandle, pos);
		PHYSFS_close(fhandle);
		fhandle = whandle;
	} else { // megayuck - physfs on posix platforms uses O_APPEND. We illegally access the fd directly and clear that flag.
		//LOG_MSG("noCOW",pname,PHYSFS_tell(fhandle));
		PHYSFS_close(fhandle);
		fhandle = PHYSFS_openAppend(pname);
#ifndef WIN32
		fcntl(**(int**)fhandle->opaque,F_SETFL,0);
#endif
		PHYSFS_seek(fhandle, pos);
	}
	return true;
}
Пример #21
0
bool File::open(Mode mode)
{
	if (mode == CLOSED)
		return true;

	// File must exist if read mode.
	if ((mode == READ) && !PHYSFS_exists(filename.c_str()))
		throw love::Exception("Could not open file %s. Does not exist.", filename.c_str());

	// Check whether the write directory is set.
	if ((mode == APPEND || mode == WRITE) && (PHYSFS_getWriteDir() == 0) && !hack_setupWriteDirectory())
		throw love::Exception("Could not set write directory.");

	// File already open?
	if (file != 0)
		return false;

	this->mode = mode;

	switch (mode)
	{
	case READ:
		file = PHYSFS_openRead(filename.c_str());
		break;
	case APPEND:
		file = PHYSFS_openAppend(filename.c_str());
		break;
	case WRITE:
		file = PHYSFS_openWrite(filename.c_str());
		break;
	default:
		break;
	}

	if (file != 0 && !setBuffer(bufferMode, bufferSize))
	{
		// Revert to buffer defaults if we don't successfully set the buffer.
		bufferMode = BUFFER_NONE;
		bufferSize = 0;
	}

	return (file != 0);
}
Пример #22
0
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;
}
Пример #23
0
	bool File::open()
	{
		// Check whether the write directory is set.
		if((mode == love::FILE_APPEND || mode == love::FILE_WRITE) && (PHYSFS_getWriteDir() == 0))
			if(!setupWriteDirectory())
				return false;

		switch(mode)
		{
		case love::FILE_READ:
			file = PHYSFS_openRead(filename.c_str());
			break;
		case love::FILE_APPEND:
			file = PHYSFS_openAppend(filename.c_str());
			break;
		case love::FILE_WRITE:
			file = PHYSFS_openWrite(filename.c_str());
			break;
		}

		return (file != 0);
	}
Пример #24
0
	bool File::open(Mode mode)
	{
		if(mode == CLOSED)
			return true;

		// File must exist if read mode.
		if((mode == READ) && !PHYSFS_exists(filename.c_str()))
			throw love::Exception("Could not open file %s. Does not exist.", filename.c_str());

		// Check whether the write directory is set.
		if((mode == APPEND || mode == WRITE) && (PHYSFS_getWriteDir() == 0) && !hack_setupWriteDirectory())
			throw love::Exception("Could not set write directory.");

		// File already open?
		if(file != 0)
			return false;

		this->mode = mode;

		switch(mode)
		{
		case READ:
			file = PHYSFS_openRead(filename.c_str());
			break;
		case APPEND:
			file = PHYSFS_openAppend(filename.c_str());
			break;
		case WRITE:
			file = PHYSFS_openWrite(filename.c_str());
			break;
		default:
			break;
		}

		return (file != 0);
	}
Пример #25
0
/*!
 * \brief Rebuilds the PHYSFS searchPath with mode specific subdirs
 *
 * Priority:
 * maps > mods > base > base.wz
 */
bool rebuildSearchPath( searchPathMode mode, bool force )
{
	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)
				{
					std::string realPathAndDir = std::string(PHYSFS_getRealDir(current_map)) + current_map;
					PHYSFS_addToSearchPath(realPathAndDir.c_str(), 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;
}
Пример #26
0
// Saves and loads the relevant part of the config files for MP games
// Ensures that others' games don't change our own configuration settings
bool reloadMPConfig(void)
{
	QSettings ini(PHYSFS_getWriteDir() + QString("/") + fileName, QSettings::IniFormat);
	if (ini.status() != QSettings::NoError)
	{
		debug(LOG_ERROR, "Could not open configuration file \"%s\"", fileName);
		return false;
	}
	debug(LOG_WZ, "Reloading prefs prefs to registry");

	// If we're in-game, we already have our own configuration set, so no need to reload it.
	if (NetPlay.isHost && !ingame.localJoiningInProgress)
	{
		if (bMultiPlayer && !NetPlay.bComms)
		{
			// one-player skirmish mode sets game name to "One Player Skirmish", so
			// reset the name
			if (ini.contains("gameName"))
			{
				sstrcpy(game.name, ini.value("gameName").toString().toUtf8().constData());
			}
		}
		return true;
	}

	// If we're host and not in-game, we can safely save our settings and return.
	if (NetPlay.isHost && ingame.localJoiningInProgress)
	{
		if (bMultiPlayer && NetPlay.bComms)
		{
			ini.setValue("gameName", game.name);			//  last hosted game
		}
		else
		{
			// One-player skirmish mode sets game name to "One Player Skirmish", so
			// reset the name
			if (ini.contains("gameName"))
			{
				sstrcpy(game.name, ini.value("gameName").toString().toUtf8().constData());
			}
		}

		// Set a default map to prevent hosting games without a map.
		sstrcpy(game.map, "Sk-Rush");
		game.hash.setZero();
		game.maxPlayers = 4;

		ini.setValue("power", game.power);				// power
		ini.setValue("base", game.base);				// size of base
		ini.setValue("alliance", game.alliance);		// allow alliances
		return true;
	}

	// We're not host, so let's get rid of the host's game settings and restore our own.

	// game name
	if (ini.contains("gameName"))
	{
		sstrcpy(game.name, ini.value("gameName").toString().toUtf8().constData());
	}

	// Set a default map to prevent hosting games without a map.
	sstrcpy(game.map, "Sk-Rush");
	game.hash.setZero();
	game.maxPlayers = 4;

	game.power = ini.value("power", LEV_MED).toInt();
	game.base = ini.value("base", CAMP_BASE).toInt();
	game.alliance = ini.value("alliance", NO_ALLIANCES).toInt();

	return true;
}
Пример #27
0
/*!
 * \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);
	}
}
Пример #28
0
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());
}
Пример #29
0
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;
}
Пример #30
0
// ////////////////////////////////////////////////////////////////////////////
bool loadConfig()
{
	QSettings ini(PHYSFS_getWriteDir() + QString("/") + fileName, QSettings::IniFormat);
	if (ini.status() != QSettings::NoError)
	{
		debug(LOG_ERROR, "Could not open configuration file \"%s\"", fileName);
		return false;
	}
	debug(LOG_WZ, "Reading configuration from %s", ini.fileName().toUtf8().constData());
	if (ini.contains("voicevol")) sound_SetUIVolume(ini.value("voicevol").toDouble() / 100.0);
	if (ini.contains("fxvol")) sound_SetEffectsVolume(ini.value("fxvol").toDouble() / 100.0);
	if (ini.contains("cdvol")) sound_SetMusicVolume(ini.value("cdvol").toDouble() / 100.0);
	if (ini.contains("music_enabled")) war_SetMusicEnabled(ini.value("music_enabled").toBool());
	if (ini.contains("language")) setLanguage(ini.value("language").toString().toUtf8().constData());
	if (ini.contains("nomousewarp")) setMouseWarp(ini.value("nomousewarp").toBool());
	if (ini.contains("notexturecompression")) wz_texture_compression = GL_RGBA;
	showFPS = ini.value("showFPS", false).toBool();
	scroll_speed_accel = ini.value("scroll", DEFAULTSCROLL).toInt();
	setShakeStatus(ini.value("shake", false).toBool());
	setDrawShadows(ini.value("shadows", true).toBool());
	war_setSoundEnabled(ini.value("sound", true).toBool());
	setInvertMouseStatus(ini.value("mouseflip", true).toBool());
	setRightClickOrders(ini.value("RightClickOrders", false).toBool());
	setMiddleClickRotate(ini.value("MiddleClickRotate", false).toBool());
	rotateRadar = ini.value("rotateRadar", true).toBool();
	war_SetPauseOnFocusLoss(ini.value("PauseOnFocusLoss", false).toBool());
	NETsetMasterserverName(ini.value("masterserver_name", "lobby.wz2100.net").toString().toUtf8().constData());
	iV_font(ini.value("fontname", "DejaVu Sans").toString().toUtf8().constData(),
		ini.value("fontface", "Book").toString().toUtf8().constData(),
		ini.value("fontfacebold", "Bold").toString().toUtf8().constData());
	NETsetMasterserverPort(ini.value("masterserver_port", MASTERSERVERPORT).toInt());
	NETsetGameserverPort(ini.value("gameserver_port", GAMESERVERPORT).toInt());
	war_SetFMVmode((FMV_MODE)ini.value("FMVmode", FMV_FULLSCREEN).toInt());
	war_setScanlineMode((SCANLINE_MODE)ini.value("scanlines", SCANLINES_OFF).toInt());
	seq_SetSubtitles(ini.value("subtitles", true).toBool());
	setDifficultyLevel((DIFFICULTY_LEVEL)ini.value("difficulty", DL_NORMAL).toInt());
	war_SetSPcolor(ini.value("colour", 0).toInt());	// default is green (0)
	war_setMPcolour(ini.value("colourMP", -1).toInt());  // default is random (-1)
	sstrcpy(game.name, ini.value("gameName", _("My Game")).toString().toUtf8().constData());
	sstrcpy(sPlayer, ini.value("playerName", _("Player")).toString().toUtf8().constData());

	// Set a default map to prevent hosting games without a map.
	sstrcpy(game.map, "Sk-Rush");
	game.hash.setZero();
	game.maxPlayers = 4;

	game.power = ini.value("power", LEV_MED).toInt();
	game.base = ini.value("base", CAMP_BASE).toInt();
	game.alliance = ini.value("alliance", NO_ALLIANCES).toInt();
	game.scavengers = ini.value("scavengers", false).toBool();
	memset(&ingame.phrases, 0, sizeof(ingame.phrases));
	for (int i = 1; i < 5; i++)
	{
		QString key("phrase" + QString::number(i));
		if (ini.contains(key)) sstrcpy(ingame.phrases[i], ini.value(key).toString().toUtf8().constData());
	}
	bEnemyAllyRadarColor = ini.value("radarObjectMode").toBool();
	radarDrawMode = (RADAR_DRAW_MODE)ini.value("radarTerrainMode", RADAR_MODE_DEFAULT).toInt();
	radarDrawMode = (RADAR_DRAW_MODE)MIN(NUM_RADAR_MODES - 1, radarDrawMode); // restrict to allowed values
	if (ini.contains("textureSize")) setTextureSize(ini.value("textureSize").toInt());
	NetPlay.isUPNP = ini.value("UPnP", true).toBool();
	if (ini.contains("FSAA")) war_setFSAA(ini.value("FSAA").toInt());
	// Leave this to false, some system will fail and they can't see the system popup dialog!
	war_setFullscreen(ini.value("fullscreen", false).toBool());
	war_SetTrapCursor(ini.value("trapCursor", false).toBool());
	// this should be enabled on all systems by default
	war_SetVsync(ini.value("vsync", true).toBool());
	// 640x480 is minimum that we will support
	int width = ini.value("width", 640).toInt();
	int height = ini.value("height", 480).toInt();
	if (width < 640 || height < 480)	// sanity check
	{
		width = 640;
		height = 480;
	}
	pie_SetVideoBufferWidth(width);
	pie_SetVideoBufferHeight(height);
	war_SetWidth(width);
	war_SetHeight(height);

	if (ini.contains("bpp")) pie_SetVideoBufferDepth(ini.value("bpp").toInt());
	return true;
}