aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/detection
diff options
context:
space:
mode:
authorSven Hesse2012-06-27 20:48:39 +0200
committerSven Hesse2012-07-30 01:44:42 +0200
commit55c75756ea3c38cdd7074caff7085e35a658c9e7 (patch)
tree2e001344e64b25375bfb116471b699dcdd854805 /engines/gob/detection
parent4a380ce668c45e5eaba1cdba9406d0c7fe7f3635 (diff)
downloadscummvm-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/detection')
-rw-r--r--engines/gob/detection/detection.cpp95
-rw-r--r--engines/gob/detection/tables_fallback.h110
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