aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEinar Johan Trøan Sømåen2012-07-22 07:28:17 +0200
committerEinar Johan Trøan Sømåen2012-07-22 07:28:17 +0200
commitc8b1c747242df4d8c596873ee320d64583380be0 (patch)
treeeb65cd47de6758d8df4eca4da4853414b2a610e7
parent742521c20db68e965761ba9309bb0a3dea379217 (diff)
downloadscummvm-rg350-c8b1c747242df4d8c596873ee320d64583380be0.tar.gz
scummvm-rg350-c8b1c747242df4d8c596873ee320d64583380be0.tar.bz2
scummvm-rg350-c8b1c747242df4d8c596873ee320d64583380be0.zip
WINTERMUTE: Add in a fallback-detector for unknown games. (flagged as "fangame" for now)
This does a minimal engine-startup to open any dcp's and get the proper "startup.settings"-file, and then get the name/caption fields from that file. There are currently no handling of localized strings used there (base_string_table would be the culprit). And, there is also no secondary checks for language (but for that matter, there is no support for chosing language if multiple exist at this point either).
-rw-r--r--engines/wintermute/detection.cpp62
-rw-r--r--engines/wintermute/wintermute.cpp62
-rw-r--r--engines/wintermute/wintermute.h3
3 files changed, 125 insertions, 2 deletions
diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp
index 285c3ffaeb..5e259f717d 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -32,6 +32,24 @@
#include "engines/wintermute/detection_tables.h"
+namespace WinterMute {
+
+/**
+ * The fallback game descriptor used by the WinterMute engine's fallbackDetector.
+ * Contents of this struct are overwritten by the fallbackDetector. (logic copied partially
+ * from the SCI-engine).
+ */
+static ADGameDescription s_fallbackDesc = {
+ "",
+ "",
+ AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+};
+static char s_fallbackGameIdBuf[256];
+
class WinterMuteMetaEngine : public AdvancedMetaEngine {
public:
WinterMuteMetaEngine() : AdvancedMetaEngine(WinterMute::gameDescriptions, sizeof(ADGameDescription), WinterMute::wintermuteGames) {
@@ -83,6 +101,44 @@ public:
}
return detectedGames;
}*/
+
+
+ virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ // Set some defaults
+ s_fallbackDesc.extra = "";
+ s_fallbackDesc.language = Common::UNK_LANG;
+ s_fallbackDesc.flags = ADGF_UNSTABLE;
+ s_fallbackDesc.platform = Common::kPlatformWindows; // default to Windows
+ s_fallbackDesc.gameid = "wintermute";
+ s_fallbackDesc.guioptions = GUIO0();
+
+ if (allFiles.contains("data.dcp")) {
+ Common::String name, caption;
+ if (WinterMuteEngine::getGameInfo(fslist, name, caption)) {
+ for (int32 i = 0; i < name.size(); i++) {
+ // Replace spaces with underscores
+ if (name[i] == ' ') {
+ name.setChar('_', (uint32)i);
+ }
+ }
+ // Prefix to avoid collisions with actually known games
+ name = "wmefan-" + name;
+ strncpy(s_fallbackGameIdBuf, name.c_str(), sizeof(s_fallbackGameIdBuf) - 1);
+ s_fallbackDesc.gameid = s_fallbackGameIdBuf;
+ if (caption != name) {
+ caption += " (fangame) ";
+ char *offset = s_fallbackGameIdBuf + name.size() + 1;
+ uint32 remainingLength = (sizeof(s_fallbackGameIdBuf) - 1) - (name.size() + 1);
+ strncpy(offset, caption.c_str(), remainingLength);
+ s_fallbackDesc.extra = offset;
+ s_fallbackDesc.flags |= ADGF_USEEXTRAASTITLE;
+ }
+ return &s_fallbackDesc;
+ } // Fall through to return 0;
+ }
+ return 0;
+ }
+
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
assert(syst);
assert(engine);
@@ -141,8 +197,10 @@ public:
}
};
+} // end of namespace WinterMute
+
#if PLUGIN_ENABLED_DYNAMIC(WINTERMUTE)
-REGISTER_PLUGIN_DYNAMIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, WinterMuteMetaEngine);
+REGISTER_PLUGIN_DYNAMIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, WinterMute::WinterMuteMetaEngine);
#else
-REGISTER_PLUGIN_STATIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, WinterMuteMetaEngine);
+REGISTER_PLUGIN_STATIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, WinterMute::WinterMuteMetaEngine);
#endif
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index 69c5df5bc5..9040de66e6 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -29,6 +29,7 @@
#include "common/EventRecorder.h"
#include "common/file.h"
#include "common/fs.h"
+#include "common/tokenizer.h"
#include "engines/util.h"
#include "engines/wintermute/ad/ad_game.h"
@@ -37,12 +38,24 @@
#include "engines/wintermute/base/base_registry.h"
#include "engines/wintermute/base/sound/base_sound_manager.h"
+#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/scriptables/script_engine.h"
namespace WinterMute {
WinterMuteEngine *g_wintermute;
+// Simple constructor for detection - we need to setup the persistence to avoid special-casing in-engine
+// This might not be the prettiest solution
+WinterMuteEngine::WinterMuteEngine() : Engine(g_system) {
+ g_wintermute = this;
+ _classReg = new SystemClassRegistry();
+ _classReg->registerClasses();
+
+ _game = new AdGame();
+ _rnd = NULL;
+}
+
WinterMuteEngine::WinterMuteEngine(OSystem *syst, const ADGameDescription *desc)
: Engine(syst), _gameDescription(desc) {
// Put your engine in a sane state, but do nothing big yet;
@@ -74,7 +87,10 @@ WinterMuteEngine::~WinterMuteEngine() {
debug("WinterMuteEngine::~WinterMuteEngine");
// Dispose your resources here
+ delete _classReg;
delete _rnd;
+ delete _game;
+ g_wintermute = NULL;
// Remove all of our debug levels here
DebugMan.clearAllDebugChannels();
@@ -320,6 +336,52 @@ int WinterMuteEngine::messageLoop() {
void WinterMuteEngine::deinit() {
delete _classReg;
+ _classReg = NULL;
+}
+
+bool WinterMuteEngine::getGameInfo(const Common::FSList &fslist, Common::String &name, Common::String &caption) {
+ bool retVal = false;
+ caption = name = "(invalid)";
+
+ // Quick-fix, instead of possibly breaking the persistence-system, let's just roll with it
+ WinterMuteEngine *engine = new WinterMuteEngine();
+
+ engine->_game->initialize1();
+ engine->_game->_fileManager->registerPackages(fslist);
+ if (engine->_game->loadSettings("startup.settings")) {
+ // We do some manual parsing here, as the engine needs gfx to be initalized to do that.
+ Common::SeekableReadStream *stream = engine->_game->_fileManager->openFile((engine->_game->_settingsGameFile ? engine->_game->_settingsGameFile : "default.game"), false, false);
+ while (!stream->eos() && !stream->err()) {
+ Common::String line = stream->readLine();
+ line.trim(); // Get rid of indentation
+ // Expect "GAME {" or comment, or empty line
+ if (line.size() == 0 || line[0] == ';' || (line.contains("{")))
+ continue;
+ else {
+ Common::StringTokenizer token(line, "=");
+ Common::String key = token.nextToken();
+ Common::String value = token.nextToken();
+ if (value.size() == 0)
+ continue;
+ if (value[0] == '\"')
+ value.deleteChar(0);
+ else
+ continue; // not a string
+ if (value.lastChar() == '\"')
+ value.deleteLastChar();
+ if (key == "NAME") {
+ retVal = true;
+ name = value;
+ } else if (key == "CAPTION") {
+ retVal = true;
+ caption = value;
+ }
+ }
+ }
+ delete stream;
+ }
+ delete engine;
+ return retVal;
}
uint32 WinterMuteEngine::randInt(int from, int to) {
diff --git a/engines/wintermute/wintermute.h b/engines/wintermute/wintermute.h
index b37f495b5e..e850a72196 100644
--- a/engines/wintermute/wintermute.h
+++ b/engines/wintermute/wintermute.h
@@ -44,6 +44,7 @@ enum {
class WinterMuteEngine : public Engine {
public:
WinterMuteEngine(OSystem *syst, const ADGameDescription *desc);
+ WinterMuteEngine();
~WinterMuteEngine();
virtual Common::Error run();
@@ -51,6 +52,8 @@ public:
Common::SaveFileManager *getSaveFileMan() { return _saveFileMan; }
SystemClassRegistry *getClassRegistry(){ return _classReg; }
uint32 randInt(int from, int to);
+ // For detection-purposes:
+ static bool getGameInfo(const Common::FSList &fslist, Common::String &name, Common::String &caption);
private:
int init();
void deinit();