diff options
author | Sven Hesse | 2012-06-27 20:48:39 +0200 |
---|---|---|
committer | Sven Hesse | 2012-07-30 01:44:42 +0200 |
commit | 55c75756ea3c38cdd7074caff7085e35a658c9e7 (patch) | |
tree | 2e001344e64b25375bfb116471b699dcdd854805 /engines/gob | |
parent | 4a380ce668c45e5eaba1cdba9406d0c7fe7f3635 (diff) | |
download | scummvm-rg350-55c75756ea3c38cdd7074caff7085e35a658c9e7.tar.gz scummvm-rg350-55c75756ea3c38cdd7074caff7085e35a658c9e7.tar.bz2 scummvm-rg350-55c75756ea3c38cdd7074caff7085e35a658c9e7.zip |
GOB: Add a more complex detection for Once Upon A Time titles
The hard-coded Once Upon A Time titles, Abracadabra and Baba Yaga,
are impossible to distinguish by file name alone. The same is true
for the each three platforms, DOS, Amiga and Atari ST.
We do need to know exactly which game and platform a specific path
holds, though, because they're
a) completely hard-coded
b) the data files have platform-specific endianness
Therefore, when the filename-based fallback detector finds one of
those games, we open the archives and look inside them.
We detect the specific game by looking at which animal names are
present; and the platform by inspecting the endianness of the
title screen's DEC file, in addition to the existence of a MOD
file to distinguish the Atari ST from the Amiga version.
Diffstat (limited to 'engines/gob')
-rw-r--r-- | engines/gob/detection/detection.cpp | 95 | ||||
-rw-r--r-- | engines/gob/detection/tables_fallback.h | 110 |
2 files changed, 203 insertions, 2 deletions
diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp index 8b4fab4409..8fb0052a5b 100644 --- a/engines/gob/detection/detection.cpp +++ b/engines/gob/detection/detection.cpp @@ -25,6 +25,7 @@ #include "engines/obsolete.h" #include "gob/gob.h" +#include "gob/dataio.h" #include "gob/detection/tables.h" @@ -43,6 +44,12 @@ public: 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() : @@ -59,12 +66,96 @@ GameDescriptor GobMetaEngine::findGame(const char *gameid) const { const ADGameDescription *GobMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { ADFilePropertiesMap filesProps; - const ADGameDescription *game = detectGameFilebased(allFiles, fslist, Gob::fileBased, &filesProps); + const Gob::GOBGameDescription *game; + game = (const Gob::GOBGameDescription *)detectGameFilebased(allFiles, fslist, Gob::fileBased, &filesProps); if (!game) return 0; + if (game->gameType == Gob::kGameTypeOnceUponATime) { + game = detectOnceUponATime(fslist); + if (!game) + return 0; + } + reportUnknown(fslist.begin()->getParent(), filesProps); - return game; + 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; + } + + 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; + } + + SearchMan.clear(); + + if ((gameType == Gob::kOnceUponATimeInvalid) || (platform == Gob::kOnceUponATimePlatformInvalid)) { + warning("GobMetaEngine::detectOnceUponATime(): Detection failed (%d, %d)", + (int) gameType, (int) platform); + return 0; + } + + return &Gob::fallbackOnceUpon[gameType][platform]; } const char *GobMetaEngine::getName() const { diff --git a/engines/gob/detection/tables_fallback.h b/engines/gob/detection/tables_fallback.h index 0e0aa92ae1..05f579c08c 100644 --- a/engines/gob/detection/tables_fallback.h +++ b/engines/gob/detection/tables_fallback.h @@ -23,6 +23,8 @@ #ifndef GOB_DETECTION_TABLES_FALLBACK_H #define GOB_DETECTION_TABLES_FALLBACK_H +// -- Tables for the filename-based fallback -- + static const GOBGameDescription fallbackDescs[] = { { //0 { @@ -451,4 +453,112 @@ static const ADFileBasedFallback fileBased[] = { { 0, { 0 } } }; +// -- Tables for detecting the specific Once Upon A Time game -- + +enum OnceUponATime { + kOnceUponATimeInvalid = -1, + kOnceUponATimeAbracadabra = 0, + kOnceUponATimeBabaYaga = 1, + kOnceUponATimeMAX +}; + +enum OnceUponATimePlatform { + kOnceUponATimePlatformInvalid = -1, + kOnceUponATimePlatformDOS = 0, + kOnceUponATimePlatformAmiga = 1, + kOnceUponATimePlatformAtariST = 2, + kOnceUponATimePlatformMAX +}; + +static const GOBGameDescription fallbackOnceUpon[kOnceUponATimeMAX][kOnceUponATimePlatformMAX] = { + { // kOnceUponATimeAbracadabra + { // kOnceUponATimePlatformDOS + { + "abracadabra", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH) + }, + kGameTypeAbracadabra, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // kOnceUponATimePlatformAmiga + { + "abracadabra", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH) + }, + kGameTypeAbracadabra, + kFeaturesEGA, + 0, 0, 0 + }, + { // kOnceUponATimePlatformAtariST + { + "abracadabra", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH) + }, + kGameTypeAbracadabra, + kFeaturesEGA, + 0, 0, 0 + } + }, + { // kOnceUponATimeBabaYaga + { // kOnceUponATimePlatformDOS + { + "babayaga", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH) + }, + kGameTypeBabaYaga, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // kOnceUponATimePlatformAmiga + { + "babayaga", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH) + }, + kGameTypeBabaYaga, + kFeaturesEGA, + 0, 0, 0 + }, + { // kOnceUponATimePlatformAtariST + { + "babayaga", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH) + }, + kGameTypeBabaYaga, + kFeaturesEGA, + 0, 0, 0 + } + } +}; + #endif // GOB_DETECTION_TABLES_FALLBACK_H |