aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorJussi Pitkanen2011-06-04 18:12:26 +0300
committerEugene Sandulenko2011-08-13 23:26:29 +0100
commit4d4a558f7beda9e3732dd30f16a6e73f5e805df2 (patch)
tree217ab81b0137dbd567b5cd2efe7202f8d4d3e51b /engines
parent1f680ecbc83f34749911dd45be130b0580eb37a9 (diff)
downloadscummvm-rg350-4d4a558f7beda9e3732dd30f16a6e73f5e805df2.tar.gz
scummvm-rg350-4d4a558f7beda9e3732dd30f16a6e73f5e805df2.tar.bz2
scummvm-rg350-4d4a558f7beda9e3732dd30f16a6e73f5e805df2.zip
AGI: Do not try to pass filenames of disk images from the detector to engine
Diffstat (limited to 'engines')
-rw-r--r--engines/agi/agi.h29
-rw-r--r--engines/agi/detection.cpp136
-rw-r--r--engines/agi/detection_tables.h51
-rw-r--r--engines/agi/loader_v1.cpp17
4 files changed, 145 insertions, 88 deletions
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index bf730fcfb4..2d9432be52 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -631,6 +631,24 @@ struct AgiGame {
Common::Rect mouseFence; /**< rectangle set by fence.mouse command */
};
+/**
+ * Check if a disk image with the given MD5 sum exists in the search path.
+ *
+ * @param md5 MD5 sum of the disk image to be searched
+ * @param filename Filled with a filename in case the image is found
+ * @return True if found, otherwise false.
+ */
+bool diskImageExists(Common::String md5, Common::String &filename);
+
+/**
+ * Get MD5 sums for a given game from the booter game description table.
+ *
+ * @param gid Game ID of the game
+ * @param md5Disk0 Filled with the MD5 sum of disk 0
+ * @param md5Disk1 Filled with the MD5 sum of disk 1 if there are two disks
+ */
+bool getBooterMD5Sums(AgiGameID gid, Common::String &md5Disk0, Common::String &md5Disk1);
+
class AgiLoader {
public:
@@ -649,18 +667,14 @@ public:
class AgiLoader_v1 : public AgiLoader {
private:
AgiEngine *_vm;
- Common::String _dsk0Name;
- Common::String _dsk1Name;
+ Common::String _filenameDisk0;
+ Common::String _filenameDisk1;
int loadDir(AgiDir *agid, int offset, int num);
uint8 *loadVolRes(AgiDir *agid);
public:
- AgiLoader_v1(AgiEngine *vm, Common::String dsk0, Common::String dsk1) {
- _vm = vm;
- _dsk0Name = dsk0;
- _dsk1Name = dsk1;
- }
+ AgiLoader_v1(AgiEngine *vm);
virtual int init();
virtual int deinit();
@@ -715,6 +729,7 @@ public:
virtual int loadWords(const char *);
};
+
class GfxMgr;
class SpritesMgr;
class Menu;
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 854658cc57..7c6cf0eaff 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -48,9 +48,6 @@ struct AGIGameDescription {
int gameType;
uint32 features;
uint16 version;
-
- Common::String dsk0Name;
- Common::String dsk1Name;
};
uint32 AgiBase::getGameID() const {
@@ -97,6 +94,20 @@ void AgiBase::initVersion() {
_gameVersion = _gameDescription->version;
}
+struct AGIBooterDescription {
+ Common::String md5Disk0;
+ Common::String md5Disk1;
+ Common::String id;
+ Common::String extra;
+ int gameID;
+ int gameType;
+ uint32 features;
+ uint16 version;
+};
+
+bool isDiskImage(Common::SeekableReadStream *stream, Common::String filename, Common::String md5);
+bool diskImageExistsInFSList(const Common::FSList &fslist, Common::String md5, Common::String &filename);
+
}
static const PlainGameDescriptor agiGames[] = {
@@ -294,9 +305,7 @@ 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;
@@ -324,7 +333,6 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
Common::String filename = file->getName();
filename.toLowercase();
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)
@@ -429,41 +437,25 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
// 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;
- }
+ for (int i = 0; !booterDescription[i].md5Disk0.empty(); i++) {
+ Common::String filenameDisk0;
+ Common::String filenameDisk1;
+
+ if (!diskImageExistsInFSList(fslist, booterDescription[i].md5Disk0, filenameDisk0))
+ continue;
+ if (!booterDescription[i].md5Disk1.empty())
+ if (!diskImageExistsInFSList(fslist, booterDescription[i].md5Disk1, filenameDisk1))
+ continue;
+
+ g_fallbackDesc.gameID = booterDescription[i].gameID;
+ g_fallbackDesc.gameType = booterDescription[i].gameType;
+ g_fallbackDesc.features = booterDescription[i].features;
+ g_fallbackDesc.version = booterDescription[i].version;
+
+ g_fallbackDesc.desc.gameid = booterDescription[i].id.c_str();
+ g_fallbackDesc.desc.extra = booterDescription[i].extra.c_str();
+
+ return (const ADGameDescription *)&g_fallbackDesc;
}
}
@@ -508,6 +500,66 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
namespace Agi {
+bool isDiskImage(Common::SeekableReadStream *stream, Common::String filename, Common::String md5) {
+ if (!(filename.hasSuffix(".dsk") || filename.hasSuffix(".img")))
+ return false;
+
+ if (stream->size() == 368640 && computeStreamMD5AsString(*stream, 5000) == md5)
+ return true;
+
+ return false;
+}
+
+bool diskImageExistsInFSList(const Common::FSList &fslist, Common::String md5, Common::String &filename) {
+ for (Common::FSList::const_iterator x = fslist.begin(); x != fslist.end(); x++) {
+ if (x->isDirectory()) continue;
+
+ Common::SeekableReadStream *stream = x->createReadStream();
+ if (isDiskImage(stream, x->getName(), md5)) {
+ filename = x->getName();
+ delete stream;
+ return true;
+ }
+ delete stream;
+ }
+
+ return false;
+}
+
+bool diskImageExists(Common::String md5, Common::String &filename) {
+ Common::ArchiveMemberList files;
+ SearchMan.listMembers(files);
+
+ Common::File file;
+ for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); x++) {
+ file.open((*x)->getName());
+ if (isDiskImage(&file, (*x)->getName(), md5)) {
+ filename = (*x)->getName();
+ file.close();
+ return true;
+ }
+ file.close();
+ }
+
+ return false;
+}
+
+bool getBooterMD5Sums(AgiGameID gid, Common::String &md5Disk0, Common::String &md5Disk1) {
+ AGIBooterDescription *booter = NULL;
+ int i = 0;
+ while (!booterDescription[i].md5Disk0.empty()) {
+ if (booterDescription[i].gameID == gid)
+ booter = &booterDescription[i];
+ i++;
+ }
+ if (booter == NULL)
+ return false;
+
+ md5Disk0 = booter->md5Disk0;
+ md5Disk1 = booter->md5Disk1;
+ return true;
+}
+
bool AgiBase::canLoadGameStateCurrently() {
return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork) && !_noSaveLoadAllowed);
}
@@ -525,7 +577,7 @@ int AgiEngine::agiDetectGame() {
assert(_gameDescription != NULL);
if (getVersion() <= 0x2001) {
- _loader = new AgiLoader_v1(this, _gameDescription->dsk0Name, _gameDescription->dsk1Name);
+ _loader = new AgiLoader_v1(this);
} else if (getVersion() <= 0x2999) {
_loader = new AgiLoader_v2(this);
} else {
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index ade45243f7..c535744ebe 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -37,9 +37,7 @@ using Common::GUIO_NONE;
gid, \
interp, \
features, \
- ver, \
- "", \
- "" \
+ ver \
}
#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \
@@ -55,9 +53,7 @@ using Common::GUIO_NONE;
gid, \
interp, \
features, \
- ver, \
- "", \
- "" \
+ 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)
@@ -200,9 +196,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_GOLDRUSH,
GType_V3,
GF_MACGOLDRUSH,
- 0x3149,
- "",
- ""
+ 0x3149
},
@@ -520,9 +514,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_SQ2,
GType_V2,
0,
- 0x2936,
- "",
- ""
+ 0x2936
},
@@ -667,9 +659,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_FANMADE,
GType_V2,
GF_AGDS,
- 0x2440,
- "",
- ""
+ 0x2440
},
{
@@ -686,9 +676,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_GETOUTTASQ,
GType_V2,
0,
- 0x2440,
- "",
- ""
+ 0x2440
},
FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE),
@@ -843,9 +831,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_FANMADE,
GType_V3,
GF_FANMADE,
- 0x3149,
- "",
- "",
+ 0x3149
},
FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3),
@@ -853,7 +839,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 }
};
/**
@@ -873,25 +859,16 @@ static AGIGameDescription g_fallbackDesc = {
GID_FANMADE,
GType_V2,
GF_FANMADE,
- 0x2917,
- "",
- ""
+ 0x2917
};
/**
- * Detection table for booter games.
+ * Descriptor 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 },
+#define BOOTER_V2(id, extra, md50, md51, gid) { md50, md51, id, extra, gid, GType_V2, ADGF_NO_FLAGS, 0x2001 },
+
+static AGIBooterDescription booterDescription[] = {
+ BOOTER_V2("ddp", "booter", "f323f10abf8140ffb2668b09af2e7b87", "", GID_DDP)
{ "", "", "", "", 0, 0, 0, 0 }
};
diff --git a/engines/agi/loader_v1.cpp b/engines/agi/loader_v1.cpp
index 40f797286f..90655ec735 100644
--- a/engines/agi/loader_v1.cpp
+++ b/engines/agi/loader_v1.cpp
@@ -21,6 +21,7 @@
*/
#include "agi/agi.h"
+#include "common/md5.h"
#define offsetTHS(track,head,sector) (512 * ((((track) * 2 + (head)) * 9) + (sector)))
#define offset(sector) offsetTHS(sector / 18, (sector % 18) / 9, (sector % 18) % 9)
@@ -41,6 +42,18 @@
namespace Agi {
+
+AgiLoader_v1::AgiLoader_v1(AgiEngine *vm) {
+ _vm = vm;
+
+ // Find filenames for the disk images
+ Common::String md5Disk0, md5Disk1;
+ getBooterMD5Sums((AgiGameID)_vm->getGameID(), md5Disk0, md5Disk1);
+ diskImageExists(md5Disk0, _filenameDisk0);
+ if (!md5Disk1.empty())
+ diskImageExists(md5Disk1, _filenameDisk1);
+}
+
int AgiLoader_v1::detectGame() {
return _vm->setupV2Game(_vm->getVersion());
}
@@ -48,7 +61,7 @@ int AgiLoader_v1::detectGame() {
int AgiLoader_v1::loadDir(AgiDir *agid, int offset, int num) {
Common::File fp;
- if (!fp.open(_dsk0Name))
+ if (!fp.open(_filenameDisk0))
return errBadFileOpen;
// Cleanup
@@ -108,7 +121,7 @@ uint8 *AgiLoader_v1::loadVolRes(struct AgiDir *agid) {
int sec = agid->offset >> 16;
int off = agid->offset & 0xFFFF;
- fp.open(_dsk0Name);
+ fp.open(_filenameDisk0);
fp.seek(offset(sec) + off, SEEK_SET);
int signature = fp.readUint16BE();