mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 05:38:56 +00:00
Simplified advanced detector file sys scanning code
svn-id: r33455
This commit is contained in:
parent
04c05d3ca0
commit
fbe4f0dd48
@ -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.
|
||||
|
@ -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");
|
||||
_appDomain.clear();
|
||||
_gameDomains.clear();
|
||||
_transientDomain.clear();
|
||||
_domainSaveOrder.clear();
|
||||
|
||||
strcat(configFile, "\\Application Data");
|
||||
CreateDirectory(configFile, NULL);
|
||||
}
|
||||
// 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
|
||||
|
||||
strcat(configFile, "\\ScummVM");
|
||||
CreateDirectory(configFile, NULL);
|
||||
strcat(configFile, "\\" DEFAULT_CONFIG_FILE);
|
||||
// ... load it ...
|
||||
assert(stream);
|
||||
loadStream(*stream);
|
||||
|
||||
// ... and close it again.
|
||||
delete stream;
|
||||
|
||||
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);
|
||||
#else
|
||||
strcpy(configFile, DEFAULT_CONFIG_FILE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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;
|
||||
printf("Using configuration file: %s\n", _filename.c_str());
|
||||
loadStream(cfg_file);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Detect if a domain occurs multiple times (or likewise, if
|
||||
// a key occurs multiple times inside one domain).
|
||||
void ConfigManager::loadStream(SeekableReadStream &stream) {
|
||||
|
||||
while (!cfg_file.eof() && !cfg_file.ioFailed()) {
|
||||
lineno++;
|
||||
String domain;
|
||||
String comment;
|
||||
int lineno = 0;
|
||||
|
||||
// Read a line
|
||||
String line;
|
||||
while (line.lastChar() != '\n') {
|
||||
char buf[MAXLINELEN];
|
||||
if (!cfg_file.readLine_NEW(buf, MAXLINELEN))
|
||||
break;
|
||||
line += buf;
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
// 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;
|
||||
|
||||
|
||||
// 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__
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user