aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/detection/detection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/gob/detection/detection.cpp')
-rw-r--r--engines/gob/detection/detection.cpp151
1 files changed, 132 insertions, 19 deletions
diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp
index bcfd5dacfa..8fb0052a5b 100644
--- a/engines/gob/detection/detection.cpp
+++ b/engines/gob/detection/detection.cpp
@@ -25,40 +25,146 @@
#include "engines/obsolete.h"
#include "gob/gob.h"
+#include "gob/dataio.h"
#include "gob/detection/tables.h"
class GobMetaEngine : public AdvancedMetaEngine {
public:
- GobMetaEngine() : AdvancedMetaEngine(Gob::gameDescriptions, sizeof(Gob::GOBGameDescription), gobGames) {
- _singleid = "gob";
- _guioptions = GUIO1(GUIO_NOLAUNCHLOAD);
- }
+ GobMetaEngine();
- virtual GameDescriptor findGame(const char *gameid) const {
- return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable);
- }
+ virtual GameDescriptor findGame(const char *gameid) const;
+
+ virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+
+ virtual const char *getName() const;
+ virtual const char *getOriginalCopyright() const;
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+
+ virtual Common::Error createInstance(OSystem *syst, Engine **engine) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+
+private:
+ /**
+ * Inspect the game archives to detect which Once Upon A Time game this is.
+ */
+ static const Gob::GOBGameDescription *detectOnceUponATime(const Common::FSList &fslist);
+};
+
+GobMetaEngine::GobMetaEngine() :
+ AdvancedMetaEngine(Gob::gameDescriptions, sizeof(Gob::GOBGameDescription), gobGames) {
+
+ _singleid = "gob";
+ _guioptions = GUIO1(GUIO_NOLAUNCHLOAD);
+}
+
+GameDescriptor GobMetaEngine::findGame(const char *gameid) const {
+ return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable);
+}
+
+const ADGameDescription *GobMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADFilePropertiesMap filesProps;
+
+ const Gob::GOBGameDescription *game;
+ game = (const Gob::GOBGameDescription *)detectGameFilebased(allFiles, fslist, Gob::fileBased, &filesProps);
+ if (!game)
+ return 0;
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- return detectGameFilebased(allFiles, Gob::fileBased);
+ if (game->gameType == Gob::kGameTypeOnceUponATime) {
+ game = detectOnceUponATime(fslist);
+ if (!game)
+ return 0;
}
- virtual const char *getName() const {
- return "Gob";
+ reportUnknown(fslist.begin()->getParent(), filesProps);
+ return (const ADGameDescription *)game;
+}
+
+const Gob::GOBGameDescription *GobMetaEngine::detectOnceUponATime(const Common::FSList &fslist) {
+ // Add the game path to the search manager
+ SearchMan.clear();
+ SearchMan.addDirectory(fslist.begin()->getParent().getPath(), fslist.begin()->getParent());
+
+ // Open the archives
+ Gob::DataIO dataIO;
+ if (!dataIO.openArchive("stk1.stk", true) ||
+ !dataIO.openArchive("stk2.stk", true) ||
+ !dataIO.openArchive("stk3.stk", true)) {
+
+ SearchMan.clear();
+ return 0;
}
- virtual const char *getOriginalCopyright() const {
- return "Goblins Games (C) Coktel Vision";
+ Gob::OnceUponATime gameType = Gob::kOnceUponATimeInvalid;
+ Gob::OnceUponATimePlatform platform = Gob::kOnceUponATimePlatformInvalid;
+
+ // If these animal files are present, it's Abracadabra
+ if (dataIO.hasFile("arai.anm") &&
+ dataIO.hasFile("crab.anm") &&
+ dataIO.hasFile("crap.anm") &&
+ dataIO.hasFile("drag.anm") &&
+ dataIO.hasFile("guep.anm") &&
+ dataIO.hasFile("loup.anm") &&
+ dataIO.hasFile("mous.anm") &&
+ dataIO.hasFile("rhin.anm") &&
+ dataIO.hasFile("saut.anm") &&
+ dataIO.hasFile("scor.anm"))
+ gameType = Gob::kOnceUponATimeAbracadabra;
+
+ // If these animal files are present, it's Baba Yaga
+ if (dataIO.hasFile("abei.anm") &&
+ dataIO.hasFile("arai.anm") &&
+ dataIO.hasFile("drag.anm") &&
+ dataIO.hasFile("fauc.anm") &&
+ dataIO.hasFile("gren.anm") &&
+ dataIO.hasFile("rena.anm") &&
+ dataIO.hasFile("sang.anm") &&
+ dataIO.hasFile("serp.anm") &&
+ dataIO.hasFile("tort.anm") &&
+ dataIO.hasFile("vaut.anm"))
+ gameType = Gob::kOnceUponATimeBabaYaga;
+
+ // Detect the platform by endianness and existence of a MOD file
+ Common::SeekableReadStream *villeDEC = dataIO.getFile("ville.dec");
+ if (villeDEC && (villeDEC->size() > 6)) {
+ byte data[6];
+
+ if (villeDEC->read(data, 6) == 6) {
+ if (!memcmp(data, "\000\000\000\001\000\007", 6)) {
+ // Big endian -> Amiga or Atari ST
+
+ if (dataIO.hasFile("mod.babayaga"))
+ platform = Gob::kOnceUponATimePlatformAmiga;
+ else
+ platform = Gob::kOnceUponATimePlatformAtariST;
+
+ } else if (!memcmp(data, "\000\000\001\000\007\000", 6))
+ // Little endian -> DOS
+ platform = Gob::kOnceUponATimePlatformDOS;
+ }
+
+ delete villeDEC;
}
- virtual bool hasFeature(MetaEngineFeature f) const;
+ SearchMan.clear();
- virtual Common::Error createInstance(OSystem *syst, Engine **engine) const {
- Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
- return AdvancedMetaEngine::createInstance(syst, engine);
+ if ((gameType == Gob::kOnceUponATimeInvalid) || (platform == Gob::kOnceUponATimePlatformInvalid)) {
+ warning("GobMetaEngine::detectOnceUponATime(): Detection failed (%d, %d)",
+ (int) gameType, (int) platform);
+ return 0;
}
- virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
-};
+
+ return &Gob::fallbackOnceUpon[gameType][platform];
+}
+
+const char *GobMetaEngine::getName() const {
+ return "Gob";
+}
+
+const char *GobMetaEngine::getOriginalCopyright() const {
+ return "Goblins Games (C) Coktel Vision";
+}
bool GobMetaEngine::hasFeature(MetaEngineFeature f) const {
return false;
@@ -68,6 +174,12 @@ bool Gob::GobEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsRTL);
}
+
+Common::Error GobMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
+ Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
+ return AdvancedMetaEngine::createInstance(syst, engine);
+}
+
bool GobMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
const Gob::GOBGameDescription *gd = (const Gob::GOBGameDescription *)desc;
if (gd) {
@@ -77,6 +189,7 @@ bool GobMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD
return gd != 0;
}
+
#if PLUGIN_ENABLED_DYNAMIC(GOB)
REGISTER_PLUGIN_DYNAMIC(GOB, PLUGIN_TYPE_ENGINE, GobMetaEngine);
#else