aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pitkanen2011-05-25 16:27:35 +0300
committerEugene Sandulenko2011-08-13 23:26:22 +0100
commit3fd26de37978a404e228f9500883936c979da032 (patch)
tree0a483052671ea546522bb83ad527a0e12cfa35ef
parentab784944eac1530fa257191ee7b21a154d9f639f (diff)
downloadscummvm-rg350-3fd26de37978a404e228f9500883936c979da032.tar.gz
scummvm-rg350-3fd26de37978a404e228f9500883936c979da032.tar.bz2
scummvm-rg350-3fd26de37978a404e228f9500883936c979da032.zip
AGI: Detect the bootable floppy version of Donald Duck's Playground
Also create a framework into which more booter games can be added.
-rw-r--r--engines/agi/agi.h22
-rw-r--r--engines/agi/detection.cpp53
-rw-r--r--engines/agi/detection_tables.h35
3 files changed, 107 insertions, 3 deletions
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 0155caf11d..2bc11449b9 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -646,6 +646,28 @@ public:
virtual int loadWords(const char *) = 0;
};
+class AgiLoader_v1 : public AgiLoader {
+private:
+ AgiEngine *_vm;
+ Common::String _dsk0Name;
+ Common::String _dsk1Name;
+
+public:
+ AgiLoader_v1(AgiEngine *vm, Common::String dsk0, Common::String dsk1) {
+ _vm = vm;
+ _dsk0Name = dsk0;
+ _dsk1Name = dsk1;
+ }
+
+ virtual int init() { return 0; }
+ virtual int deinit() { return 0; }
+ virtual int detectGame() { return 0; }
+ virtual int loadResource(int, int) { return 0; }
+ virtual int unloadResource(int, int) { return 0; }
+ virtual int loadObjects(const char *) { return 0; }
+ virtual int loadWords(const char *) { return 0; }
+};
+
class AgiLoader_v2 : public AgiLoader {
private:
AgiEngine *_vm;
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 93fcd2d283..854658cc57 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -28,6 +28,7 @@
#include "engines/advancedDetector.h"
#include "common/config-manager.h"
#include "common/file.h"
+#include "common/md5.h"
#include "common/savefile.h"
#include "common/textconsole.h"
#include "graphics/thumbnail.h"
@@ -47,6 +48,9 @@ struct AGIGameDescription {
int gameType;
uint32 features;
uint16 version;
+
+ Common::String dsk0Name;
+ Common::String dsk1Name;
};
uint32 AgiBase::getGameID() const {
@@ -290,7 +294,9 @@ SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int sl
const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const {
typedef Common::HashMap<Common::String, int32> IntMap;
+ typedef Common::HashMap<Common::String, Common::FSNode> NodeMap;
IntMap allFiles;
+ NodeMap allNodes;
bool matchedUsingFilenames = false;
bool matchedUsingWag = false;
int wagFileCount = 0;
@@ -317,7 +323,8 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
if (file->isDirectory()) continue;
Common::String filename = file->getName();
filename.toLowercase();
- allFiles[filename] = true; // Save the filename in a hash table
+ allFiles[filename] = true; // Save the filename in a hash table
+ allNodes[filename] = *file; // ...and also the FSNode
if (filename.hasSuffix(".wag")) {
// Save latest found *.wag file's path (Can be used to open the file, the name can't)
@@ -420,6 +427,46 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
warning("More than one (%d) *.wag files found. WAG files ignored", wagFileCount);
}
+ // Try to detect disk images of AGI v1 and AGI v2.001 booter games
+ if (!matchedUsingFilenames && !matchedUsingWag) {
+ int index = -1;
+
+ for (IntMap::const_iterator f = allFiles.begin(); f != allFiles.end(); ++f) {
+ if (f->_key.hasSuffix(".dsk") || f->_key.hasSuffix(".img")) {
+ Common::File file;
+ file.open(allNodes[f->_key]);
+ Common::String md5str = Common::computeStreamMD5AsString(file, detectionParams.md5Bytes);
+ debug(3, "Agi::fallbackDetector: disk image (%s) found with md5 sum (%s) ", f->_key.c_str(), md5str.c_str());
+
+ for (int i = 0; !booterDescription[i].md5str_dsk0.empty(); i++) {
+ if (booterDescription[i].md5str_dsk0 == md5str) {
+ index = i;
+ g_fallbackDesc.dsk0Name = f->_key;
+ }
+ if (booterDescription[i].md5str_dsk1 == md5str) {
+ index = i;
+ g_fallbackDesc.dsk1Name = f->_key;
+ }
+ }
+ }
+ }
+
+ if (index >= 0) {
+ if ((booterDescription[index].md5str_dsk0.empty() == g_fallbackDesc.dsk0Name.empty()) &&
+ (booterDescription[index].md5str_dsk1.empty() == g_fallbackDesc.dsk1Name.empty())) {
+ g_fallbackDesc.gameID = booterDescription[index].gameID;
+ g_fallbackDesc.gameType = booterDescription[index].gameType;
+ g_fallbackDesc.features = booterDescription[index].features;
+ g_fallbackDesc.version = booterDescription[index].version;
+
+ g_fallbackDesc.desc.gameid = booterDescription[index].id.c_str();
+ g_fallbackDesc.desc.extra = booterDescription[index].extra.c_str();
+
+ return (const ADGameDescription *)&g_fallbackDesc;
+ }
+ }
+ }
+
// Check that the AGI interpreter version is a supported one
if (!(g_fallbackDesc.version >= 0x2000 && g_fallbackDesc.version < 0x4000)) {
warning("Unsupported AGI interpreter version 0x%x in AGI's fallback detection. Using default 0x2917", g_fallbackDesc.version);
@@ -477,7 +524,9 @@ int AgiEngine::agiDetectGame() {
assert(_gameDescription != NULL);
- if (getVersion() <= 0x2999) {
+ if (getVersion() <= 0x2001) {
+ _loader = new AgiLoader_v1(this, _gameDescription->dsk0Name, _gameDescription->dsk1Name);
+ } else if (getVersion() <= 0x2999) {
_loader = new AgiLoader_v2(this);
} else {
_loader = new AgiLoader_v3(this);
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index cd3edf50c6..ade45243f7 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -38,6 +38,8 @@ using Common::GUIO_NONE;
interp, \
features, \
ver, \
+ "", \
+ "" \
}
#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \
@@ -54,6 +56,8 @@ using Common::GUIO_NONE;
interp, \
features, \
ver, \
+ "", \
+ "" \
}
#define GAME(id,extra,md5,ver,gid) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2)
@@ -197,6 +201,8 @@ static const AGIGameDescription gameDescriptions[] = {
GType_V3,
GF_MACGOLDRUSH,
0x3149,
+ "",
+ ""
},
@@ -515,6 +521,8 @@ static const AGIGameDescription gameDescriptions[] = {
GType_V2,
0,
0x2936,
+ "",
+ ""
},
@@ -660,6 +668,8 @@ static const AGIGameDescription gameDescriptions[] = {
GType_V2,
GF_AGDS,
0x2440,
+ "",
+ ""
},
{
@@ -677,6 +687,8 @@ static const AGIGameDescription gameDescriptions[] = {
GType_V2,
0,
0x2440,
+ "",
+ ""
},
FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE),
@@ -832,6 +844,8 @@ static const AGIGameDescription gameDescriptions[] = {
GType_V3,
GF_FANMADE,
0x3149,
+ "",
+ "",
},
FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3),
@@ -839,7 +853,7 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"),
FANMADE("Wizaro (v0.1)", "abeec1eda6eaf8dbc52443ea97ff140c"),
- { AD_TABLE_END_MARKER, 0, 0, 0, 0 }
+ { AD_TABLE_END_MARKER, 0, 0, 0, 0, "", "" }
};
/**
@@ -860,6 +874,25 @@ static AGIGameDescription g_fallbackDesc = {
GType_V2,
GF_FANMADE,
0x2917,
+ "",
+ ""
+};
+
+/**
+ * Detection table for booter games.
+ */
+static const struct {
+ Common::String md5str_dsk0;
+ Common::String md5str_dsk1;
+ Common::String id;
+ Common::String extra;
+ int gameID;
+ int gameType;
+ uint32 features;
+ uint16 version;
+} booterDescription[] = {
+ { "f323f10abf8140ffb2668b09af2e7b87", "", "ddp", "booter", GID_DDP, GType_V2, ADGF_NO_FLAGS, 0x2001 },
+ { "", "", "", "", 0, 0, 0, 0 }
};
} // End of namespace Agi