diff options
| -rw-r--r-- | common/advancedDetector.cpp | 71 | ||||
| -rw-r--r-- | common/config-manager.cpp | 368 | ||||
| -rw-r--r-- | common/config-manager.h | 4 | ||||
| -rw-r--r-- | common/system.cpp | 129 | ||||
| -rw-r--r-- | common/system.h | 19 | 
5 files changed, 332 insertions, 259 deletions
| diff --git a/common/advancedDetector.cpp b/common/advancedDetector.cpp index 6496315e2e..adc6f9e327 100644 --- a/common/advancedDetector.cpp +++ b/common/advancedDetector.cpp @@ -305,13 +305,14 @@ static void reportUnknown(const StringMap &filesMD5, const IntMap &filesSize) {  	printf("\n");  } -static ADGameDescList detectGameFilebased(const FSList &fslist, const Common::ADParams ¶ms, IntMap &allFiles); +static ADGameDescList detectGameFilebased(const StringMap &allFiles, const Common::ADParams ¶ms);  static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams ¶ms, Language language, Platform platform, const Common::String extra) { -	StringSet filesList; +	StringMap allFiles; + +	StringSet detectFiles;  	StringMap filesMD5;  	IntMap filesSize; -	IntMap allFiles;  	const ADGameFileDescription *fileDesc;  	const ADGameDescription *g; @@ -319,16 +320,8 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p  	debug(3, "Starting detection"); -	// First we compose list of files which we need MD5s for -	for (descPtr = params.descs; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += params.descItemSize) { -		g = (const ADGameDescription *)descPtr; - -		for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { -			filesList[String(fileDesc->fileName)] = true; -		} -	} - -	// Get the information of the existing files +	// First we compose an efficient to query set of all files in  fslist. +	// Includes nifty stuff like removing trailing dots and ignoring case.  	for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {  		if (file->isDirectory())  			continue; @@ -339,23 +332,37 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p  		if (tstr.lastChar() == '.')  			tstr.deleteLastChar(); -		allFiles[tstr] = true;	// Record the presence of this file +		allFiles[tstr] = file->getPath();	// Record the presence of this file +	} -		debug(3, "+ %s", tstr.c_str()); +	// Compute the set of files for which we need MD5s for. I.e. files which are +	// included in some ADGameDescription *and* present in fslist. +	for (descPtr = params.descs; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += params.descItemSize) { +		g = (const ADGameDescription *)descPtr; -		if (!filesList.contains(tstr)) -			continue; +		for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { +			String tstr = fileDesc->fileName; +			if (allFiles.contains(tstr)) +				detectFiles[tstr] = true; +		} +	} + +	// Get the information for all detection files, if they exist +	for (StringSet::const_iterator file = detectFiles.begin(); file != detectFiles.end(); ++file) { +		String fname = file->_key; + +		debug(3, "+ %s", fname.c_str());  		char md5str[32+1]; -		if (!md5_file_string(*file, md5str, params.md5Bytes)) +		if (!md5_file_string(allFiles[fname].c_str(), md5str, params.md5Bytes))  			continue; -		filesMD5[tstr] = md5str; +		filesMD5[fname] = md5str; -		debug(3, "> %s: %s", tstr.c_str(), md5str); +		debug(3, "> %s: %s", fname.c_str(), md5str);  		File testFile; -		if (testFile.open(file->getPath())) { -			filesSize[tstr] = (int32)testFile.size(); +		if (testFile.open(allFiles[fname])) { +			filesSize[fname] = (int32)testFile.size();  			testFile.close();  		}  	} @@ -443,32 +450,16 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p  		// Filename based fallback  		if (params.fileBasedFallback != 0) -			matched = detectGameFilebased(fslist, params, allFiles); +			matched = detectGameFilebased(allFiles, params);  	}  	return matched;  } -static ADGameDescList detectGameFilebased(const FSList &fslist, const Common::ADParams ¶ms, IntMap &allFiles) { +static ADGameDescList detectGameFilebased(const StringMap &allFiles, const Common::ADParams ¶ms) {  	const ADFileBasedFallback *ptr;  	const char* const* filenames; -	// First we create list of files required for detection. -	// The filenames can be different than the MD5 based match ones. -	for (ptr = params.fileBasedFallback; ptr->desc; ++ptr) { -		for (filenames = ptr->filenames; *filenames; ++filenames) { -			String tstr = String(*filenames); - -			if (!allFiles.contains(tstr)) { -				File testFile; -				if (testFile.open(tstr) || testFile.open(tstr + ".")) { -					allFiles[tstr] = true; -					testFile.close(); -				} -			} -		} -	} -  	// Then we perform the actual filename matching. If there are  	// several matches, only the one with the maximum numbers of  	// files is considered. diff --git a/common/config-manager.cpp b/common/config-manager.cpp index 044474a927..c5c7098d25 100644 --- a/common/config-manager.cpp +++ b/common/config-manager.cpp @@ -32,27 +32,10 @@  #include "common/config-manager.h"  #include "common/file.h"  #include "common/util.h" +#include "common/system.h"  DECLARE_SINGLETON(Common::ConfigManager); -#ifdef __PLAYSTATION2__ -#include "backends/platform/ps2/systemps2.h" -#endif - -#ifdef IPHONE -#include "backends/platform/iphone/osys_iphone.h" -#endif - -#if defined(UNIX) -#ifdef MACOSX -#define DEFAULT_CONFIG_FILE "Library/Preferences/ScummVM Preferences" -#else -#define DEFAULT_CONFIG_FILE ".scummvmrc" -#endif -#else -#define DEFAULT_CONFIG_FILE "scummvm.ini" -#endif -  #define MAXLINELEN 256  static bool isValidDomainName(const Common::String &domName) { @@ -85,77 +68,22 @@ ConfigManager::ConfigManager()  void ConfigManager::loadDefaultConfigFile() { -	char configFile[MAXPATHLEN]; -	// GP2X is Linux based but Home dir can be read only so do not use it and put the config in the executable dir. -	// On the iPhone, the home dir of the user when you launch the app from the Springboard, is /. Which we don't want. -#if defined(UNIX) && !defined(GP2X) && !defined(IPHONE) -	const char *home = getenv("HOME"); -	if (home != NULL && strlen(home) < MAXPATHLEN) -		snprintf(configFile, MAXPATHLEN, "%s/%s", home, DEFAULT_CONFIG_FILE); -	else -		strcpy(configFile, DEFAULT_CONFIG_FILE); -#else -	#if defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) -		OSVERSIONINFO win32OsVersion; -		ZeroMemory(&win32OsVersion, sizeof(OSVERSIONINFO)); -		win32OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); -		GetVersionEx(&win32OsVersion); -		// Check for non-9X version of Windows. -		if (win32OsVersion.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) { -			// Use the Application Data directory of the user profile. -			if (win32OsVersion.dwMajorVersion >= 5) { -				if (!GetEnvironmentVariable("APPDATA", configFile, sizeof(configFile))) -					error("Unable to access application data directory"); -			} else { -				if (!GetEnvironmentVariable("USERPROFILE", configFile, sizeof(configFile))) -					error("Unable to access user profile directory"); - -				strcat(configFile, "\\Application Data"); -				CreateDirectory(configFile, NULL); -			} +	_appDomain.clear(); +	_gameDomains.clear(); +	_transientDomain.clear(); +	_domainSaveOrder.clear(); -			strcat(configFile, "\\ScummVM"); -			CreateDirectory(configFile, NULL); -			strcat(configFile, "\\" DEFAULT_CONFIG_FILE); - -			if (fopen(configFile, "r") == NULL) { -				// Check windows directory -				char oldConfigFile[MAXPATHLEN]; -				GetWindowsDirectory(oldConfigFile, MAXPATHLEN); -				strcat(oldConfigFile, "\\" DEFAULT_CONFIG_FILE); -				if (fopen(oldConfigFile, "r")) { -					printf("The default location of the config file (scummvm.ini) in ScummVM has changed,\n"); -					printf("under Windows NT4/2000/XP/Vista. You may want to consider moving your config\n"); -					printf("file from the old default location:\n"); -					printf("%s\n", oldConfigFile); -					printf("to the new default location:\n"); -					printf("%s\n\n", configFile); -					strcpy(configFile, oldConfigFile); -				} -			} -		} else { -			// Check windows directory -			GetWindowsDirectory(configFile, MAXPATHLEN); -			strcat(configFile, "\\" DEFAULT_CONFIG_FILE); -		} +	// Open the default config file +	SeekableReadStream *stream = g_system->openConfigFileForReading(); +	_filename.clear();	// clear the filename to indicate that we are using the default config file -	#elif defined(PALMOS_MODE) -		strcpy(configFile,"/PALM/Programs/ScummVM/" DEFAULT_CONFIG_FILE); -	#elif defined(IPHONE) -		strcpy(configFile, OSystem_IPHONE::getConfigPath());	 -	#elif defined(__PLAYSTATION2__) -		((OSystem_PS2*)g_system)->makeConfigPath(configFile); -	#elif defined(__PSP__) -		strcpy(configFile, "ms0:/" DEFAULT_CONFIG_FILE); -	#elif defined (__SYMBIAN32__) -		strcpy(configFile, Symbian::GetExecutablePath()); -		strcat(configFile, DEFAULT_CONFIG_FILE); -	#else -		strcpy(configFile, DEFAULT_CONFIG_FILE); -	#endif -#endif +	// ... load it ... +	assert(stream); +	loadStream(*stream); +	 +	// ... and close it again. +	delete stream; -	loadConfigFile(configFile);  	flushToDisk();  } @@ -163,160 +91,168 @@ void ConfigManager::loadConfigFile(const String &filename) {  	_appDomain.clear();  	_gameDomains.clear();  	_transientDomain.clear(); +	_domainSaveOrder.clear();  	_filename = filename; -	_domainSaveOrder.clear(); -	loadFile(_filename); -	printf("Using configuration file: %s\n", _filename.c_str()); -} -void ConfigManager::loadFile(const String &filename) {  	File cfg_file; -  	if (!cfg_file.open(filename)) {  		printf("Creating configuration file: %s\n", filename.c_str());  	} else { -		String domain; -		String comment; -		int lineno = 0; - -		// TODO: Detect if a domain occurs multiple times (or likewise, if -		// a key occurs multiple times inside one domain). - -		while (!cfg_file.eof() && !cfg_file.ioFailed()) { -			lineno++; - -			// Read a line -			String line; -			while (line.lastChar() != '\n') { -				char buf[MAXLINELEN]; -				if (!cfg_file.readLine_NEW(buf, MAXLINELEN)) -					break; -				line += buf; +		printf("Using configuration file: %s\n", _filename.c_str()); +		loadStream(cfg_file); +	} +} + +void ConfigManager::loadStream(SeekableReadStream &stream) { + +	String domain; +	String comment; +	int lineno = 0; + +	// TODO: Detect if a domain occurs multiple times (or likewise, if +	// a key occurs multiple times inside one domain). + +	while (!stream.eos() && !stream.ioFailed()) { +		lineno++; + +		// Read a line +		String line; +		while (line.lastChar() != '\n') { +			char buf[MAXLINELEN]; +			if (!stream.readLine_NEW(buf, MAXLINELEN)) +				break; +			line += buf; +		} + +		if (line.size() == 0) { +			// Do nothing +		} else if (line[0] == '#') { +			// Accumulate comments here. Once we encounter either the start +			// of a new domain, or a key-value-pair, we associate the value +			// of the 'comment' variable with that entity. +			comment += line; +		} else if (line[0] == '[') { +			// It's a new domain which begins here. +			const char *p = line.c_str() + 1; +			// Get the domain name, and check whether it's valid (that +			// is, verify that it only consists of alphanumerics, +			// dashes and underscores). +			while (*p && (isalnum(*p) || *p == '-' || *p == '_')) +				p++; + +			switch (*p) { +			case '\0': +				error("Config file buggy: missing ] in line %d", lineno); +				break; +			case ']': +				domain = String(line.c_str() + 1, p - (line.c_str() + 1)); +				//domain = String(line.c_str() + 1, p);	// TODO: Pending Common::String changes +				break; +			default: +				error("Config file buggy: Invalid character '%c' occured in domain name in line %d", *p, lineno);  			} -			if (line.size() == 0) { -				// Do nothing -			} else if (line[0] == '#') { -				// Accumulate comments here. Once we encounter either the start -				// of a new domain, or a key-value-pair, we associate the value -				// of the 'comment' variable with that entity. -				comment += line; -			} else if (line[0] == '[') { -				// It's a new domain which begins here. -				const char *p = line.c_str() + 1; -				// Get the domain name, and check whether it's valid (that -				// is, verify that it only consists of alphanumerics, -				// dashes and underscores). -				while (*p && (isalnum(*p) || *p == '-' || *p == '_')) -					p++; - -				switch (*p) { -				case '\0': -					error("Config file buggy: missing ] in line %d", lineno); -					break; -				case ']': -					domain = String(line.c_str() + 1, p - (line.c_str() + 1)); -					//domain = String(line.c_str() + 1, p);	// TODO: Pending Common::String changes -					break; -				default: -					error("Config file buggy: Invalid character '%c' occured in domain name in line %d", *p, lineno); -				} - -				// Store domain comment -				if (domain == kApplicationDomain) { -					_appDomain.setDomainComment(comment); -				} else { -					_gameDomains[domain].setDomainComment(comment); -				} -				comment.clear(); - -				_domainSaveOrder.push_back(domain); +			// Store domain comment +			if (domain == kApplicationDomain) { +				_appDomain.setDomainComment(comment);  			} else { -				// This line should be a line with a 'key=value' pair, or an empty one. -				 -				// Skip leading whitespaces -				const char *t = line.c_str(); -				while (isspace(*t)) -					t++; - -				// Skip empty lines / lines with only whitespace -				if (*t == 0) -					continue; - -				// If no domain has been set, this config file is invalid! -				if (domain.empty()) { -					error("Config file buggy: Key/value pair found outside a domain in line %d", lineno); -				} - -				// Split string at '=' into 'key' and 'value'. First, find the "=" delimeter. -				const char *p = strchr(t, '='); -				if (!p) -					error("Config file buggy: Junk found in line line %d: '%s'", lineno, t); - -				// Trim spaces before the '=' to obtain the key -				const char *p2 = p; -				while (p2 > t && isspace(*(p2-1))) -					p2--; -				String key(t, p2 - t); -				 -				// Skip spaces after the '=' -				t = p + 1; -				while (isspace(*t)) -					t++; - -				// Trim trailing spaces -				p2 = t + strlen(t); -				while (p2 > t && isspace(*(p2-1))) -					p2--; - -				String value(t, p2 - t); - -				// Finally, store the key/value pair in the active domain -				set(key, value, domain); - -				// Store comment -				if (domain == kApplicationDomain) { -					_appDomain.setKVComment(key, comment); -				} else { -					_gameDomains[domain].setKVComment(key, comment); -				} -				comment.clear(); +				_gameDomains[domain].setDomainComment(comment); +			} +			comment.clear(); + +			_domainSaveOrder.push_back(domain); +		} else { +			// This line should be a line with a 'key=value' pair, or an empty one. +			 +			// Skip leading whitespaces +			const char *t = line.c_str(); +			while (isspace(*t)) +				t++; + +			// Skip empty lines / lines with only whitespace +			if (*t == 0) +				continue; + +			// If no domain has been set, this config file is invalid! +			if (domain.empty()) { +				error("Config file buggy: Key/value pair found outside a domain in line %d", lineno);  			} + +			// Split string at '=' into 'key' and 'value'. First, find the "=" delimeter. +			const char *p = strchr(t, '='); +			if (!p) +				error("Config file buggy: Junk found in line line %d: '%s'", lineno, t); + +			// Extract the key/value pair +			String key(t, p); +			String value(p + 1); +			 +			// Trim of spaces +			key.trim(); +			value.trim(); + +			// Finally, store the key/value pair in the active domain +			set(key, value, domain); + +			// Store comment +			if (domain == kApplicationDomain) { +				_appDomain.setKVComment(key, comment); +			} else { +				_gameDomains[domain].setKVComment(key, comment); +			} +			comment.clear();  		}  	}  }  void ConfigManager::flushToDisk() {  #ifndef __DC__ -	DumpFile cfg_file; +	WriteStream *stream; -	if (!cfg_file.open(_filename)) { -		warning("Unable to write configuration file: %s", _filename.c_str()); +	if (_filename.empty()) { +		// Write to the default config file +		stream = g_system->openConfigFileForWriting(); +		if (!stream)	// If writing to the config file is not possible, do nothing +			return;  	} else { -		// First write the domains in _domainSaveOrder, in that order. -		// Note: It's possible for _domainSaveOrder to list domains which -		// are not present anymore. -		StringList::const_iterator i; -		for (i = _domainSaveOrder.begin(); i != _domainSaveOrder.end(); ++i) { -			if (kApplicationDomain == *i) { -				writeDomain(cfg_file, *i, _appDomain); -			} else if (_gameDomains.contains(*i)) { -				writeDomain(cfg_file, *i, _gameDomains[*i]); -			} +		DumpFile *dump = new DumpFile(); +		assert(dump); + +		if (!dump->open(_filename)) { +			warning("Unable to write configuration file: %s", _filename.c_str()); +			delete dump; +			return; +		} +		 +		stream = dump; +	} + +	// First write the domains in _domainSaveOrder, in that order. +	// Note: It's possible for _domainSaveOrder to list domains which +	// are not present anymore. +	StringList::const_iterator i; +	for (i = _domainSaveOrder.begin(); i != _domainSaveOrder.end(); ++i) { +		if (kApplicationDomain == *i) { +			writeDomain(*stream, *i, _appDomain); +		} else if (_gameDomains.contains(*i)) { +			writeDomain(*stream, *i, _gameDomains[*i]);  		} +	} -		DomainMap::const_iterator d; +	DomainMap::const_iterator d; -		// Now write the domains which haven't been written yet -		if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), kApplicationDomain) == _domainSaveOrder.end()) -			writeDomain(cfg_file, kApplicationDomain, _appDomain); -		for (d = _gameDomains.begin(); d != _gameDomains.end(); ++d) { -			if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), d->_key) == _domainSaveOrder.end()) -				writeDomain(cfg_file, d->_key, d->_value); -		} +	// Now write the domains which haven't been written yet +	if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), kApplicationDomain) == _domainSaveOrder.end()) +		writeDomain(*stream, kApplicationDomain, _appDomain); +	for (d = _gameDomains.begin(); d != _gameDomains.end(); ++d) { +		if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), d->_key) == _domainSaveOrder.end()) +			writeDomain(*stream, d->_key, d->_value);  	} + +	delete stream; +  #endif // !__DC__  } diff --git a/common/config-manager.h b/common/config-manager.h index bebb59b539..0b1aa73fdb 100644 --- a/common/config-manager.h +++ b/common/config-manager.h @@ -36,7 +36,7 @@  namespace Common {  class WriteStream; - +class SeekableReadStream;  /**   * The (singleton) configuration manager, used to query & set configuration @@ -156,7 +156,7 @@ private:  	friend class Singleton<SingletonBaseType>;  	ConfigManager(); -	void			loadFile(const String &filename); +	void			loadStream(SeekableReadStream &stream);  	void			writeDomain(WriteStream &stream, const String &name, const Domain &domain);  	Domain			_transientDomain; diff --git a/common/system.cpp b/common/system.cpp index 8d528258f4..2dd0192aec 100644 --- a/common/system.cpp +++ b/common/system.cpp @@ -121,3 +121,132 @@ void OSystem::clearScreen() {  	memset(screen->pixels, 0, screen->h * screen->pitch);  	unlockScreen();  } + + +/* +FIXME: The config file loading code below needs to be cleaned up. + Port specific variants should be pushed into the respective ports. + + Ideally, the default OSystem::openConfigFileForReading/Writing methods + should be removed completely.  +*/ + +#include "common/file.h" + +#ifdef __PLAYSTATION2__ +#include "backends/platform/ps2/systemps2.h" +#endif + +#ifdef IPHONE +#include "backends/platform/iphone/osys_iphone.h" +#endif + + +#if defined(UNIX) +#ifdef MACOSX +#define DEFAULT_CONFIG_FILE "Library/Preferences/ScummVM Preferences" +#else +#define DEFAULT_CONFIG_FILE ".scummvmrc" +#endif +#else +#define DEFAULT_CONFIG_FILE "scummvm.ini" +#endif + +static Common::String getDefaultConfigFileName() { +	char configFile[MAXPATHLEN]; + +#if defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) +	OSVERSIONINFO win32OsVersion; +	ZeroMemory(&win32OsVersion, sizeof(OSVERSIONINFO)); +	win32OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); +	GetVersionEx(&win32OsVersion); +	// Check for non-9X version of Windows. +	if (win32OsVersion.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) { +		// Use the Application Data directory of the user profile. +		if (win32OsVersion.dwMajorVersion >= 5) { +			if (!GetEnvironmentVariable("APPDATA", configFile, sizeof(configFile))) +				error("Unable to access application data directory"); +		} else { +			if (!GetEnvironmentVariable("USERPROFILE", configFile, sizeof(configFile))) +				error("Unable to access user profile directory"); + +			strcat(configFile, "\\Application Data"); +			CreateDirectory(configFile, NULL); +		} + +		strcat(configFile, "\\ScummVM"); +		CreateDirectory(configFile, NULL); +		strcat(configFile, "\\" DEFAULT_CONFIG_FILE); + +		if (fopen(configFile, "r") == NULL) { +			// Check windows directory +			char oldConfigFile[MAXPATHLEN]; +			GetWindowsDirectory(oldConfigFile, MAXPATHLEN); +			strcat(oldConfigFile, "\\" DEFAULT_CONFIG_FILE); +			if (fopen(oldConfigFile, "r")) { +				printf("The default location of the config file (scummvm.ini) in ScummVM has changed,\n"); +				printf("under Windows NT4/2000/XP/Vista. You may want to consider moving your config\n"); +				printf("file from the old default location:\n"); +				printf("%s\n", oldConfigFile); +				printf("to the new default location:\n"); +				printf("%s\n\n", configFile); +				strcpy(configFile, oldConfigFile); +			} +		} +	} else { +		// Check windows directory +		GetWindowsDirectory(configFile, MAXPATHLEN); +		strcat(configFile, "\\" DEFAULT_CONFIG_FILE); +	} + +#elif defined(PALMOS_MODE) +	strcpy(configFile,"/PALM/Programs/ScummVM/" DEFAULT_CONFIG_FILE); +#elif defined(IPHONE) +	strcpy(configFile, OSystem_IPHONE::getConfigPath());	 +#elif defined(__PLAYSTATION2__) +	((OSystem_PS2*)g_system)->makeConfigPath(configFile); +#elif defined(__PSP__) +	strcpy(configFile, "ms0:/" DEFAULT_CONFIG_FILE); +#elif defined (__SYMBIAN32__) +	strcpy(configFile, Symbian::GetExecutablePath()); +	strcat(configFile, DEFAULT_CONFIG_FILE); +#elif defined(UNIX) && !defined(GP2X) && !defined(IPHONE) +	// On UNIX type systems, by default we store the config file inside +	// to the HOME directory of the user. +	//	 +	// GP2X is Linux based but Home dir can be read only so do not use +	// it and put the config in the executable dir. +	// +	// On the iPhone, the home dir of the user when you launch the app +	// from the Springboard, is /. Which we don't want. +	const char *home = getenv("HOME"); +	if (home != NULL && strlen(home) < MAXPATHLEN) +		snprintf(configFile, MAXPATHLEN, "%s/%s", home, DEFAULT_CONFIG_FILE); +	else +		strcpy(configFile, DEFAULT_CONFIG_FILE); + +#else +	strcpy(configFile, DEFAULT_CONFIG_FILE); +#endif + + +	return configFile; +} + +Common::SeekableReadStream *OSystem::openConfigFileForReading() { +	Common::File *confFile = new Common::File(); +	assert(confFile); +	confFile->open(getDefaultConfigFileName()); +	return confFile; +} + +Common::WriteStream *OSystem::openConfigFileForWriting() { +#ifdef __DC__ +	return 0; +#else +	Common::DumpFile *confFile = new Common::DumpFile(); +	assert(confFile); +	confFile->open(getDefaultConfigFileName()); +	return confFile; +#endif +} diff --git a/common/system.h b/common/system.h index b895a5cfba..501d0802fd 100644 --- a/common/system.h +++ b/common/system.h @@ -44,6 +44,8 @@ namespace Common {  	class EventManager;  	class SaveFileManager;  	class TimerManager; +	class SeekableReadStream; +	class WriteStream;  }  class FilesystemFactory; @@ -900,10 +902,25 @@ public:  	/**  	 * Returns the FilesystemFactory object, depending on the current architecture.  	 * -	 * @return FilesystemFactory* The specific factory for the current architecture. +	 * @return the FSNode factory for the current architecture  	 */  	virtual FilesystemFactory *getFilesystemFactory() = 0; +	/** +	 * Open the default config file for reading, by returning a suitable +	 * ReadStream instance. It is the callers responsiblity to delete +	 * the stream after use. +	 */ +	virtual Common::SeekableReadStream *openConfigFileForReading(); + +	/** +	 * Open the default config file for writing, by returning a suitable +	 * WriteStream instance. It is the callers responsiblity to delete +	 * the stream after use. +	 * +	 * May return 0 to indicate that writing to config file is not possible. +	 */ +	virtual Common::WriteStream *openConfigFileForWriting();  	/**  	 * Return String which is used for backend-specific addition to theme | 
