aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/engine.cpp25
-rw-r--r--base/gameDetector.cpp4
-rw-r--r--base/main.cpp19
-rw-r--r--common/config-manager.cpp317
-rw-r--r--common/config-manager.h67
5 files changed, 274 insertions, 158 deletions
diff --git a/base/engine.cpp b/base/engine.cpp
index fb46949050..a3767d1bf4 100644
--- a/base/engine.cpp
+++ b/base/engine.cpp
@@ -56,12 +56,18 @@ Engine::~Engine() {
}
void Engine::initCommonGFX(GameDetector &detector, bool defaultTo1XScaler) {
+ const Common::ConfigManager::Domain *transientDomain = ConfMan.getDomain(Common::ConfigManager::kTransientDomain);
+ const Common::ConfigManager::Domain *gameDomain = ConfMan.getDomain(detector._targetName);
+
+ assert(transientDomain);
+
const bool useDefaultGraphicsMode =
- !ConfMan.hasKey("gfx_mode", Common::ConfigManager::kTransientDomain) &&
+ !transientDomain->contains("gfx_mode") &&
(
- !ConfMan.hasKey("gfx_mode", detector._targetName) ||
- !scumm_stricmp(ConfMan.get("gfx_mode", detector._targetName).c_str(), "normal") ||
- !scumm_stricmp(ConfMan.get("gfx_mode", detector._targetName).c_str(), "default")
+ !gameDomain ||
+ !gameDomain->contains("gfx_mode") ||
+ !scumm_stricmp(gameDomain->get("gfx_mode").c_str(), "normal") ||
+ !scumm_stricmp(gameDomain->get("gfx_mode").c_str(), "default")
);
// See if the game should default to 1x scaler
@@ -77,12 +83,19 @@ void Engine::initCommonGFX(GameDetector &detector, bool defaultTo1XScaler) {
}
}
+ // Note: The following code deals with the fullscreen / ASR settings. This
+ // is a bit tricky, because there are three ways the user can affect these
+ // settings: Via the config file, via the command line, and via in-game
+ // hotkeys.
+ // Any global or command line settings already have been applied at the time
+ // we get here. Hence we only do something
+
// (De)activate aspect-ratio correction as determined by the config settings
- if (ConfMan.hasKey("aspect_ratio", detector._targetName))
+ if (gameDomain && gameDomain->contains("aspect_ratio"))
_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio"));
// (De)activate fullscreen mode as determined by the config settings
- if (ConfMan.hasKey("fullscreen", detector._targetName))
+ if (gameDomain && gameDomain->contains("fullscreen"))
_system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen"));
}
diff --git a/base/gameDetector.cpp b/base/gameDetector.cpp
index b21ccffb6b..fe762b4994 100644
--- a/base/gameDetector.cpp
+++ b/base/gameDetector.cpp
@@ -602,6 +602,10 @@ void GameDetector::setTarget(const String &target) {
_gameid = ConfMan.get("gameid");
else
_gameid = _targetName;
+
+ // TODO: In the future, simply insert the gameid into the transient domain.
+ // That way, all code (including backends) can reliably access it.
+ //ConfMan.set("gameid", _gameid, Common::ConfigManager::kTransientDomain);
}
bool GameDetector::detectMain() {
diff --git a/base/main.cpp b/base/main.cpp
index fabcce5b89..afa163625c 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -314,8 +314,15 @@ extern "C" int scummvm_main(int argc, char *argv[]) {
setupDummyPalette(system);
// Unless a game was specified, show the launcher dialog
- if (detector._targetName.empty())
+ if (detector._targetName.empty()) {
+ // Discard any command line options. Those that affect the graphics
+ // mode etc. already have should have been handled by the backend at
+ // this point. And the others (like bootparam etc.) should not
+ // blindly be passed to the first game launched from the launcher.
+ ConfMan.getDomain(Common::ConfigManager::kTransientDomain)->clear();
+
running = launcherDialog(detector, system);
+ }
// FIXME: We're now looping the launcher. This, of course, doesn't
// work as well as it should. In theory everything should be destroyed
@@ -331,11 +338,11 @@ extern "C" int scummvm_main(int argc, char *argv[]) {
if (result == 0)
break;
- // There are some command-line options that it's
- // unlikely that we want to preserve now that we're
- // going to start a different game.
- ConfMan.removeKey("boot_param", ConfMan.kTransientDomain);
- ConfMan.removeKey("save_slot", ConfMan.kTransientDomain);
+ // Discard any command line options. It's unlikely that the user
+ // wanted to apply them to *all* games ever launched.
+ ConfMan.getDomain(Common::ConfigManager::kTransientDomain)->clear();
+
+ // TODO: Reset the game detector fully
// PluginManager::instance().unloadPlugins();
PluginManager::instance().loadPlugins();
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index bf87fb3b71..5472b2b4cf 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -54,8 +54,8 @@ static char *rtrim(char *t) {
return t;
}
-static bool isValidDomainName(const Common::String &domain) {
- const char *p = domain.c_str();
+static bool isValidDomainName(const Common::String &domName) {
+ const char *p = domName.c_str();
while (*p && (isalnum(*p) || *p == '-' || *p == '_'))
p++;
return *p == 0;
@@ -68,25 +68,17 @@ namespace Common {
const String ConfigManager::kApplicationDomain("scummvm");
const String ConfigManager::kTransientDomain("__TRANSIENT");
-const String trueStr("true");
-const String falseStr("false");
-
#else
const char *ConfigManager::kApplicationDomain = "scummvm";
const char *ConfigManager::kTransientDomain = "__TRANSIENT";
-const char *trueStr = "true";
-const char *falseStr = "false";
-
#endif
#pragma mark -
ConfigManager::ConfigManager() {
- // Ensure the global domain(s) are setup.
- _globalDomains[kApplicationDomain];
}
@@ -121,13 +113,10 @@ void ConfigManager::loadDefaultConfigFile() {
}
void ConfigManager::loadConfigFile(const String &filename) {
- _globalDomains.clear();
+ _appDomain.clear();
_gameDomains.clear();
_transientDomain.clear();
- // Ensure the global domain(s) are setup.
- _globalDomains[kApplicationDomain];
-
_filename = filename;
_domainSaveOrder.clear();
loadFile(_filename);
@@ -181,8 +170,8 @@ void ConfigManager::loadFile(const String &filename) {
}
// Store domain comment
- if (_globalDomains.contains(domain)) {
- _globalDomains[domain].setDomainComment(comment);
+ if (domain == kApplicationDomain) {
+ _appDomain.setDomainComment(comment);
} else {
_gameDomains[domain].setDomainComment(comment);
}
@@ -212,8 +201,8 @@ void ConfigManager::loadFile(const String &filename) {
set(key, value, domain);
// Store comment
- if (_globalDomains.contains(domain)) {
- _globalDomains[domain].setKVComment(key, comment);
+ if (domain == kApplicationDomain) {
+ _appDomain.setKVComment(key, comment);
} else {
_gameDomains[domain].setKVComment(key, comment);
}
@@ -239,8 +228,8 @@ void ConfigManager::flushToDisk() {
// are not present anymore.
StringList::const_iterator i;
for (i = _domainSaveOrder.begin(); i != _domainSaveOrder.end(); ++i) {
- if (_globalDomains.contains(*i)) {
- writeDomain(cfg_file, *i, _globalDomains[*i]);
+ if (kApplicationDomain == *i) {
+ writeDomain(cfg_file, *i, _appDomain);
} else if (_gameDomains.contains(*i)) {
writeDomain(cfg_file, *i, _gameDomains[*i]);
}
@@ -248,13 +237,9 @@ void ConfigManager::flushToDisk() {
DomainMap::const_iterator d;
- // Now write the global domains which weren't written yet
- for (d = _globalDomains.begin(); d != _globalDomains.end(); ++d) {
- if (!_domainSaveOrder.contains(d->_key))
- writeDomain(cfg_file, d->_key, d->_value);
- }
-
- // Finally write the remaining game domains
+ // Now write the domains which haven't been written yet
+ if (!_domainSaveOrder.contains(kApplicationDomain))
+ writeDomain(cfg_file, kApplicationDomain, _appDomain);
for (d = _gameDomains.begin(); d != _gameDomains.end(); ++d) {
if (!_domainSaveOrder.contains(d->_key))
writeDomain(cfg_file, d->_key, d->_value);
@@ -295,91 +280,142 @@ void ConfigManager::writeDomain(FILE *file, const String &name, const Domain &do
fprintf(file, "\n");
}
+
+#pragma mark -
+
+
+const ConfigManager::Domain *ConfigManager::getDomain(const String &domName) const {
+ assert(!domName.empty());
+ assert(isValidDomainName(domName));
+
+ if (domName == kTransientDomain)
+ return &_transientDomain;
+ if (domName == kApplicationDomain)
+ return &_appDomain;
+ if (_gameDomains.contains(domName))
+ return &_gameDomains[domName];
+
+ return 0;
+}
+
+ConfigManager::Domain *ConfigManager::getDomain(const String &domName) {
+ assert(!domName.empty());
+ assert(isValidDomainName(domName));
+
+ if (domName == kTransientDomain)
+ return &_transientDomain;
+ if (domName == kApplicationDomain)
+ return &_appDomain;
+ if (_gameDomains.contains(domName))
+ return &_gameDomains[domName];
+
+ return 0;
+}
+
+
#pragma mark -
bool ConfigManager::hasKey(const String &key) const {
// Search the domains in the following order:
- // 1) Transient domain
- // 2) Active game domain (if any)
- // 3) All global domains
+ // 1) the transient domain,
+ // 2) the active game domain (if any),
+ // 3) the application domain.
// The defaults domain is explicitly *not* checked.
if (_transientDomain.contains(key))
return true;
- if (!_activeDomain.empty() && _gameDomains[_activeDomain].contains(key))
+ if (_activeDomain && _activeDomain->contains(key))
return true;
- DomainMap::const_iterator iter;
- for (iter = _globalDomains.begin(); iter != _globalDomains.end(); ++iter) {
- if (iter->_value.contains(key))
- return true;
- }
+ if (_appDomain.contains(key))
+ return true;
return false;
}
-bool ConfigManager::hasKey(const String &key, const String &dom) const {
- assert(!dom.empty());
- assert(isValidDomainName(dom));
+bool ConfigManager::hasKey(const String &key, const String &domName) const {
+ // FIXME: For now we continue to allow empty domName to indicate
+ // "use 'default' domain". This is mainly needed for the SCUMM ConfigDialog
+ // and should be removed ASAP.
+ if (domName.empty())
+ return hasKey(key);
- if (dom == kTransientDomain)
- return _transientDomain.contains(key);
- if (_gameDomains.contains(dom))
- return _gameDomains[dom].contains(key);
- if (_globalDomains.contains(dom))
- return _globalDomains[dom].contains(key);
+ const Domain *domain = getDomain(domName);
- return false;
+ if (!domain)
+ return false;
+ return domain->contains(key);
}
-void ConfigManager::removeKey(const String &key, const String &dom) {
- assert(!dom.empty());
- assert(isValidDomainName(dom));
+void ConfigManager::removeKey(const String &key, const String &domName) {
+ Domain *domain = getDomain(domName);
- if (dom == kTransientDomain)
- _transientDomain.erase(key);
- else if (_gameDomains.contains(dom))
- _gameDomains[dom].erase(key);
- else if (_globalDomains.contains(dom))
- _globalDomains[dom].erase(key);
- else
- error("Removing key '%s' from non-existent domain '%s'", key.c_str(), dom.c_str());
+ if (!domain)
+ error("ConfigManager::removeKey(%s, %s) called on non-existent domain",
+ key.c_str(), domName.c_str());
+
+ domain->erase(key);
}
#pragma mark -
-const String & ConfigManager::get(const String &key, const String &domain) const {
- assert(isValidDomainName(domain));
+const String & ConfigManager::get(const String &key) const {
+ if (_transientDomain.contains(key))
+ return _transientDomain[key];
+ else if (_activeDomain && _activeDomain->contains(key))
+ return (*_activeDomain)[key];
+ else if (_appDomain.contains(key))
+ return _appDomain[key];
+ else if (_defaultsDomain.contains(key))
+ return _defaultsDomain[key];
- // Search the domains in the following order:
- // 1) Transient domain
- // 2) Active game domain (if any)
- // 3) All global domains
- // 4) The defaults
+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
+ return String::emptyString;
+#else
+ return ConfMan._emptyString;
+#endif
+}
- if ((domain.empty() || domain == kTransientDomain) && _transientDomain.contains(key))
- return _transientDomain[key];
+const String & ConfigManager::get(const String &key, const String &domName) const {
+ // FIXME: For now we continue to allow empty domName to indicate
+ // "use 'default' domain". This is mainly needed for the SCUMM ConfigDialog
+ // and should be removed ASAP.
+ if (domName.empty())
+ return get(key);
- const String &dom = domain.empty() ? _activeDomain : domain;
+ const Domain *domain = getDomain(domName);
- if (!dom.empty() && _gameDomains.contains(dom) && _gameDomains[dom].contains(key))
- return _gameDomains[dom][key];
+ if (!domain)
+ error("ConfigManager::get(%s,%s) called on non-existent domain",
+ key.c_str(), domName.c_str());
- DomainMap::const_iterator iter;
- for (iter = _globalDomains.begin(); iter != _globalDomains.end(); ++iter) {
- if (iter->_value.contains(key))
- return iter->_value[key];
- }
+ if (domain->contains(key))
+ return (*domain)[key];
return _defaultsDomain.get(key);
+
+ if (!domain->contains(key)) {
+#if 1
+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
+ return String::emptyString;
+#else
+ return ConfMan._emptyString;
+#endif
+#else
+ error("ConfigManager::get(%s,%s) called on non-existent key",
+ key.c_str(), domName.c_str());
+#endif
+ }
+
+ return (*domain)[key];
}
-int ConfigManager::getInt(const String &key, const String &dom) const {
- String value(get(key, dom));
+int ConfigManager::getInt(const String &key, const String &domName) const {
+ String value(get(key, domName));
char *errpos;
// For now, be tolerant against missing config keys. Strictly spoken, it is
@@ -390,67 +426,91 @@ int ConfigManager::getInt(const String &key, const String &dom) const {
int ivalue = (int)strtol(value.c_str(), &errpos, 10);
if (value.c_str() == errpos)
- error("Config file buggy: '%s' is not a valid integer", errpos);
+ error("ConfigManager::getInt(%s,%s): '%s' is not a valid integer",
+ key.c_str(), domName.c_str(), errpos);
return ivalue;
}
-bool ConfigManager::getBool(const String &key, const String &dom) const {
- String value(get(key, dom));
+bool ConfigManager::getBool(const String &key, const String &domName) const {
+ String value(get(key, domName));
- if ((value == trueStr) || (value == "yes") || (value == "1"))
+ if ((value == "true") || (value == "yes") || (value == "1"))
return true;
- if ((value == falseStr) || (value == "no") || (value == "0"))
+ if ((value == "false") || (value == "no") || (value == "0"))
return false;
- error("Config file buggy: '%s' is not a valid bool", value.c_str());
+ error("ConfigManager::getBool(%s,%s): '%s' is not a valid bool",
+ key.c_str(), domName.c_str(), value.c_str());
}
#pragma mark -
-void ConfigManager::set(const String &key, const String &value, const String &dom) {
- assert(isValidDomainName(dom));
- if (dom.empty()) {
- // Remove the transient domain value
- _transientDomain.erase(key);
-
- if (_activeDomain.empty())
- _globalDomains[kApplicationDomain][key] = value;
- else
- _gameDomains[_activeDomain][key] = value;
+void ConfigManager::set(const String &key, const String &value) {
+ // Remove the transient domain value, if any.
+ _transientDomain.erase(key);
- } else {
-
- if (dom == kTransientDomain)
- _transientDomain[key] = value;
- else {
- if (_globalDomains.contains(dom)) {
- _globalDomains[dom][key] = value;
- if (_activeDomain.empty() || !_gameDomains[_activeDomain].contains(key))
- _transientDomain.erase(key);
- } else {
- _gameDomains[dom][key] = value;
- if (dom == _activeDomain)
- _transientDomain.erase(key);
- }
+ // Write the new key/value pair into the active domain, resp. into
+ // the application domain if no game domain is active.
+ if (_activeDomain)
+ (*_activeDomain)[key] = value;
+ else
+ _appDomain[key] = value;
+}
+
+void ConfigManager::set(const String &key, const String &value, const String &domName) {
+ // FIXME: For now we continue to allow empty domName to indicate
+ // "use 'default' domain". This is mainly needed for the SCUMM ConfigDialog
+ // and should be removed ASAP.
+ if (domName.empty())
+ return set(key, value);
+
+ Domain *domain = getDomain(domName);
+
+ if (!domain)
+ error("ConfigManager::set(%s,%s,%s) called on non-existent domain",
+ key.c_str(), value.c_str(), domName.c_str());
+
+ (*domain)[key] = value;
+
+ // TODO/FIXME: We used to erase the given key from the transient domain
+ // here. Do we still want to do that?
+ // It was probably there to simplify the options dialogs code:
+ // Imagine you are editing the current options (via the SCUMM ConfigDialog,
+ // for example). If you edit the game domain for that, but a matching
+ // entry in the transient domain is present, than your changes may not take
+ // effect. So you want to remove the key from the transient domain before
+ // adding it to the active domain.
+ // But doing this here seems rather evil... need to comb the options dialog
+ // code to find out if it's still necessary, and if that's the case, how
+ // to replace it in a clean fashion...
+/*
+ if (domName == kTransientDomain)
+ _transientDomain[key] = value;
+ else {
+ if (domName == kApplicationDomain) {
+ _appDomain[key] = value;
+ if (_activeDomainName.empty() || !_gameDomains[_activeDomainName].contains(key))
+ _transientDomain.erase(key);
+ } else {
+ _gameDomains[domName][key] = value;
+ if (domName == _activeDomainName)
+ _transientDomain.erase(key);
}
}
+*/
}
-void ConfigManager::set(const String &key, const char *value, const String &dom) {
- set(key, String(value), dom);
-}
-
-void ConfigManager::set(const String &key, int value, const String &dom) {
+void ConfigManager::set(const String &key, int value, const String &domName) {
char tmp[128];
snprintf(tmp, sizeof(tmp), "%i", value);
- set(key, String(tmp), dom);
+ set(key, String(tmp), domName);
}
-void ConfigManager::set(const String &key, bool value, const String &dom) {
- set(key, value ? trueStr : falseStr, dom);
+void ConfigManager::set(const String &key, bool value, const String &domName) {
+ set(key, String(value ? "true" : "false"), domName);
}
@@ -472,24 +532,27 @@ void ConfigManager::registerDefault(const String &key, int value) {
}
void ConfigManager::registerDefault(const String &key, bool value) {
- registerDefault(key, value ? trueStr : falseStr);
+ registerDefault(key, value ? "true" : "false");
}
#pragma mark -
-void ConfigManager::setActiveDomain(const String &domain) {
- assert(!domain.empty());
- assert(isValidDomainName(domain));
- _activeDomain = domain;
- _gameDomains[domain];
+void ConfigManager::setActiveDomain(const String &domName) {
+ if (domName.empty()) {
+ _activeDomain = 0;
+ } else {
+ assert(isValidDomainName(domName));
+ _activeDomain = & _gameDomains[domName];
+ }
+ _activeDomainName = domName;
}
-void ConfigManager::removeGameDomain(const String &domain) {
- assert(!domain.empty());
- assert(isValidDomainName(domain));
- _gameDomains.erase(domain);
+void ConfigManager::removeGameDomain(const String &domName) {
+ assert(!domName.empty());
+ assert(isValidDomainName(domName));
+ _gameDomains.erase(domName);
}
void ConfigManager::renameGameDomain(const String &oldName, const String &newName) {
@@ -511,9 +574,9 @@ void ConfigManager::renameGameDomain(const String &oldName, const String &newNam
_gameDomains.erase(oldName);
}
-bool ConfigManager::hasGameDomain(const String &domain) const {
- assert(!domain.empty());
- return isValidDomainName(domain) && _gameDomains.contains(domain);
+bool ConfigManager::hasGameDomain(const String &domName) const {
+ assert(!domName.empty());
+ return isValidDomainName(domName) && _gameDomains.contains(domName);
}
diff --git a/common/config-manager.h b/common/config-manager.h
index 8793a35db8..10313f64d5 100644
--- a/common/config-manager.h
+++ b/common/config-manager.h
@@ -92,37 +92,64 @@ public:
void loadDefaultConfigFile();
void loadConfigFile(const String &filename);
+ /**
+ * Retrieve the config domain with the given name.
+ * @param domName the name of the domain to retrieve
+ * @return pointer to the domain, or 0 if the domain doesn't exist.
+ */
+ Domain * getDomain(const String &domName);
+ const Domain * getDomain(const String &domName) const;
+
+
+ //
+ // Generic access methods: No domain specified, use the values from the
+ // various domains in the order of their priority.
+ //
+
bool hasKey(const String &key) const;
- bool hasKey(const String &key, const String &dom) const;
-
- void removeKey(const String &key, const String &dom);
+ const String & get(const String &key) const;
+ void set(const String &key, const String &value);
+
+#if 1
+ //
+ // Domain specific access methods: Acces *one specific* domain and modify it.
+ // TODO: I'd like to get rid of most of those if possible, or at least reduce
+ // their usage, by using getDomain as often as possible. For example in the
+ // options dialog code...
+ //
+
+ bool hasKey(const String &key, const String &domName) const;
+ const String & get(const String &key, const String &domName) const;
+ void set(const String &key, const String &value, const String &domName);
+
+ void removeKey(const String &key, const String &domName);
+#endif
- const String & get(const String &key, const String &dom = String::emptyString) const;
- int getInt(const String &key, const String &dom = String::emptyString) const;
- bool getBool(const String &key, const String &dom = String::emptyString) const;
+ //
+ // Some additional convenience accessors.
+ //
+ int getInt(const String &key, const String &domName = String::emptyString) const;
+ bool getBool(const String &key, const String &domName = String::emptyString) const;
+ void set(const String &key, int value, const String &domName = String::emptyString);
+ void set(const String &key, bool value, const String &domName = String::emptyString);
- void set(const String &key, const String &value, const String &dom = String::emptyString);
- void set(const String &key, const char *value, const String &dom = String::emptyString);
- void set(const String &key, int value, const String &dom = String::emptyString);
- void set(const String &key, bool value, const String &dom = String::emptyString);
void registerDefault(const String &key, const String &value);
void registerDefault(const String &key, const char *value);
void registerDefault(const String &key, int value);
void registerDefault(const String &key, bool value);
-// ...
void flushToDisk();
- void setActiveDomain(const String &domain);
- const String & getActiveDomain() const { return _activeDomain; }
+ void setActiveDomain(const String &domName);
+ const String & getActiveDomain() const { return _activeDomainName; }
-// void addDomain(const String &name);
- void removeGameDomain(const String &name);
+// void addDomain(const String &domName);
+ void removeGameDomain(const String &domName);
void renameGameDomain(const String &oldName, const String &newName);
- bool hasGameDomain(const String &domain) const;
+ bool hasGameDomain(const String &domName) const;
const DomainMap & getGameDomains() const { return _gameDomains; }
-
+
/*
TODO: Callback/change notification system
typedef void (*ConfigCallback)(const ConstString &key, void *refCon);
@@ -140,12 +167,14 @@ private:
Domain _transientDomain;
DomainMap _gameDomains;
- DomainMap _globalDomains;
+ Domain _appDomain;
Domain _defaultsDomain;
StringList _domainSaveOrder;
- String _activeDomain;
+ String _activeDomainName;
+ Domain * _activeDomain;
+
String _filename;
};