aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
authorMax Horn2006-04-23 17:33:16 +0000
committerMax Horn2006-04-23 17:33:16 +0000
commit0d67640a58b044ade0605319e091df9b2f666e4a (patch)
treefcec3906ad2abb5ea28072663193a7cce9282e83 /engines/scumm
parentd11f5724f96107a07d462be2410d93f55bd1fba2 (diff)
downloadscummvm-rg350-0d67640a58b044ade0605319e091df9b2f666e4a.tar.gz
scummvm-rg350-0d67640a58b044ade0605319e091df9b2f666e4a.tar.bz2
scummvm-rg350-0d67640a58b044ade0605319e091df9b2f666e4a.zip
Behold, the new SCUMM detector finally has arrived. Unified detection & engine instantiation, reduced code duplication, more powerful detection in case MD5 is not known / can't be computed, and many other nifty improvements.
svn-id: r22110
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/cursor.cpp4
-rw-r--r--engines/scumm/debugger.cpp2
-rw-r--r--engines/scumm/he/intern_he.h16
-rw-r--r--engines/scumm/he/resource_he.cpp45
-rw-r--r--engines/scumm/he/resource_he.h2
-rw-r--r--engines/scumm/he/sound_he.cpp18
-rw-r--r--engines/scumm/intern.h18
-rw-r--r--engines/scumm/plugin.cpp1484
-rw-r--r--engines/scumm/plugin.h37
-rw-r--r--engines/scumm/resource.cpp111
-rw-r--r--engines/scumm/scumm-md5.h78
-rw-r--r--engines/scumm/scumm.cpp145
-rw-r--r--engines/scumm/scumm.h16
-rw-r--r--engines/scumm/sound.cpp30
14 files changed, 652 insertions, 1354 deletions
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index 6e86ad5644..fd0d2a90f4 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -93,8 +93,8 @@ static const byte default_v6_cursor[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x0F,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
-ScummEngine_v5::ScummEngine_v5(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine(syst, gs, md5sum, subst) {
+ScummEngine_v5::ScummEngine_v5(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine(syst, dr) {
for (int i = 0; i < 4; i++) {
memcpy(_cursorImages[i], default_cursor_images[i], 32);
diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp
index 0f37947467..c064405b15 100644
--- a/engines/scumm/debugger.cpp
+++ b/engines/scumm/debugger.cpp
@@ -83,7 +83,7 @@ ScummDebugger::ScummDebugger(ScummEngine *s)
DVar_Register("scumm_vars", &_vm->_scummVars, DVAR_INTARRAY, _vm->_numVariables);
// DVar_Register("scumm_gamename", &_vm->_targetName, DVAR_STRING, 0);
- DVar_Register("scumm_exename", &_vm->_baseName, DVAR_STRING, 0);
+// DVar_Register("scumm_exename", &_vm->_baseName, DVAR_STRING, 0);
DVar_Register("scumm_gameid", &_vm->_game.id, DVAR_BYTE, 0);
// Register commands
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 5524b2a21e..dc906a654c 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -51,7 +51,7 @@ protected:
Common::File _hFileTable[17];
public:
- ScummEngine_v60he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst) : ScummEngine_v6(syst, gs, md5sum, subst) {}
+ ScummEngine_v60he(OSystem *syst, const DetectorResult &dr) : ScummEngine_v6(syst, dr) {}
virtual void scummInit();
@@ -116,7 +116,7 @@ protected:
bool _skipProcessActors;
public:
- ScummEngine_v70he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v70he(OSystem *syst, const DetectorResult &dr);
~ScummEngine_v70he();
Wiz *_wiz;
@@ -181,7 +181,7 @@ protected:
class ScummEngine_v71he : public ScummEngine_v70he {
public:
- ScummEngine_v71he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v71he(OSystem *syst, const DetectorResult &dr);
protected:
virtual void saveOrLoad(Serializer *s);
@@ -236,7 +236,7 @@ protected:
WizParameters _wizParams;
public:
- ScummEngine_v72he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v72he(OSystem *syst, const DetectorResult &dr);
virtual void scummInit();
@@ -347,7 +347,7 @@ protected:
int32 _heSndResId, _curSndId, _sndPtrOffs, _sndTmrOffs;
public:
- ScummEngine_v80he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v80he(OSystem *syst, const DetectorResult &dr);
protected:
virtual void setupOpcodes();
@@ -420,7 +420,7 @@ protected:
int32 _curSpriteGroupId;
public:
- ScummEngine_v90he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v90he(OSystem *syst, const DetectorResult &dr);
~ScummEngine_v90he();
virtual void scummInit();
@@ -517,7 +517,7 @@ protected:
class ScummEngine_v99he : public ScummEngine_v90he {
public:
- ScummEngine_v99he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst) : ScummEngine_v90he(syst, gs, md5sum, subst) {}
+ ScummEngine_v99he(OSystem *syst, const DetectorResult &dr) : ScummEngine_v90he(syst, dr) {}
virtual void scummInit();
@@ -548,7 +548,7 @@ protected:
const OpcodeEntryV100he *_opcodesV100he;
public:
- ScummEngine_v100he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst) : ScummEngine_v99he(syst, gs, md5sum, subst) {}
+ ScummEngine_v100he(OSystem *syst, const DetectorResult &dr) : ScummEngine_v99he(syst, dr) {}
protected:
virtual void setupOpcodes();
diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp
index c4b81f8516..13d78c5517 100644
--- a/engines/scumm/he/resource_he.cpp
+++ b/engines/scumm/he/resource_he.cpp
@@ -42,7 +42,6 @@ namespace Scumm {
ResExtractor::ResExtractor(ScummEngine_v70he *scumm)
: _vm(scumm) {
- _fileName[0] = 0;
memset(_cursorCache, 0, sizeof(_cursorCache));
}
@@ -159,21 +158,15 @@ int Win32ResExtractor::extractResource_(const char *resType, char *resName, byte
fi.memory = NULL;
fi.file = new Common::File;
- if (!_fileName[0]) { // We are running for the first time
- snprintf(_fileName, 256, "%s.he3", _vm->getBaseName());
-
- if (_vm->_substResFileName.almostGameID != 0) {
- char buf1[128];
- _vm->generateSubstResFileName(_fileName, buf1, sizeof(buf1));
- strcpy(_fileName, buf1);
- }
+ if (_fileName.empty()) { // We are running for the first time
+ _fileName = _vm->generateFilename(3);
}
/* get file size */
fi.file->open(_fileName);
if (!fi.file->isOpen()) {
- error("Cannot open file %s", _fileName);
+ error("Cannot open file %s", _fileName.c_str());
}
fi.total_size = fi.file->size();
@@ -1288,38 +1281,36 @@ int MacResExtractor::extractResource(int id, byte **buf) {
Common::File in;
int size;
- if (!_fileName[0]) // We are running for the first time
- if (_vm->_substResFileName.almostGameID != 0) {
- char buf1[128];
+ if (_fileName.empty()) { // We are running for the first time
+ _fileName = _vm->generateFilename(3);
- snprintf(buf1, 128, "%s.he3", _vm->getBaseName());
- _vm->generateSubstResFileName(buf1, _fileName, sizeof(buf1));
+ // Some programs write it as .bin. Try that too
+ if (!in.exists(_fileName)) {
+ Common::String tmp(_fileName);
+
+ _fileName += ".bin";
- // Some programs write it as .bin. Try that too
if (!in.exists(_fileName)) {
- strcpy(buf1, _fileName);
- snprintf(_fileName, 128, "%s.bin", buf1);
-
+ // And finally check if we have dumped resource fork
+ _fileName = tmp;
+ _fileName += ".bin";
if (!in.exists(_fileName)) {
- // And finally check if we have dumped resource fork
- snprintf(_fileName, 128, "%s.rsrc", buf1);
- if (!in.exists(_fileName)) {
- error("Cannot open file any of files '%s', '%s.bin', '%s.rsrc",
- buf1, buf1, buf1);
- }
+ error("Cannot open file any of files '%s', '%s.bin', '%s.rsrc",
+ tmp.c_str(), tmp.c_str(), tmp.c_str());
}
}
}
+ }
in.open(_fileName);
if (!in.isOpen()) {
- error("Cannot open file %s", _fileName);
+ error("Cannot open file %s", _fileName.c_str());
}
// we haven't calculated it
if (_resOffset == -1) {
if (!init(in))
- error("Resource fork is missing in file '%s'", _fileName);
+ error("Resource fork is missing in file '%s'", _fileName.c_str());
in.close();
in.open(_fileName);
}
diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h
index 20ad0a1110..976511a974 100644
--- a/engines/scumm/he/resource_he.h
+++ b/engines/scumm/he/resource_he.h
@@ -150,7 +150,7 @@ public:
ResExtractor::CachedCursor *getCachedCursorSlot();
bool _arg_raw;
- char _fileName[256];
+ Common::String _fileName;
CachedCursor _cursorCache[MAX_CACHED_CURSORS];
typedef Common::MemoryReadStream MemoryReadStream;
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index 57a03ed129..86221aea88 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -161,15 +161,9 @@ void Sound::setOverrideFreq(int freq) {
void Sound::setupHEMusicFile() {
int i, total_size;
- char buf[32], buf1[128];
Common::File musicFile;
+ Common::String buf(_vm->generateFilename(4));
- sprintf(buf, "%s.he4", _vm->getBaseName());
-
- if (_vm->_substResFileName.almostGameID != 0) {
- _vm->generateSubstResFileName(buf, buf1, sizeof(buf1));
- strcpy(buf, buf1);
- }
if (musicFile.open(buf) == true) {
musicFile.seek(4, SEEK_SET);
total_size = musicFile.readUint32BE();
@@ -360,17 +354,11 @@ void Sound::playHESound(int soundID, int heOffset, int heChannel, int heFlags) {
if (soundID > _vm->_numSounds) {
int music_offs;
- char buf[32], buf1[128];
Common::File musicFile;
+ Common::String buf(_vm->generateFilename(4));
- sprintf(buf, "%s.he4", _vm->getBaseName());
-
- if (_vm->_substResFileName.almostGameID != 0) {
- _vm->generateSubstResFileName(buf, buf1, sizeof(buf1));
- strcpy(buf, buf1);
- }
if (musicFile.open(buf) == false) {
- warning("playHESound: Can't open music file %s", buf);
+ warning("playHESound: Can't open music file %s", buf.c_str());
return;
}
if (!getHEMusicDetails(soundID, music_offs, size)) {
diff --git a/engines/scumm/intern.h b/engines/scumm/intern.h
index 530f3a36ed..58bca67183 100644
--- a/engines/scumm/intern.h
+++ b/engines/scumm/intern.h
@@ -50,7 +50,7 @@ protected:
byte _cursorHotspots[2 * 4];
public:
- ScummEngine_v5(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v5(OSystem *syst, const DetectorResult &dr);
protected:
virtual void setupOpcodes();
@@ -193,7 +193,7 @@ protected:
*/
class ScummEngine_v4 : public ScummEngine_v5 {
public:
- ScummEngine_v4(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v4(OSystem *syst, const DetectorResult &dr);
virtual void scummInit();
@@ -212,7 +212,7 @@ protected:
*/
class ScummEngine_v3 : public ScummEngine_v4 {
public:
- ScummEngine_v3(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v3(OSystem *syst, const DetectorResult &dr);
protected:
virtual void readRoomsOffsets();
@@ -224,7 +224,7 @@ protected:
*/
class ScummEngine_v3old : public ScummEngine_v3 {
public:
- ScummEngine_v3old(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v3old(OSystem *syst, const DetectorResult &dr);
protected:
virtual void readResTypeList(int id, const char *name);
@@ -257,7 +257,7 @@ protected:
int8 _mouseOverBoxV2;
public:
- ScummEngine_v2(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v2(OSystem *syst, const DetectorResult &dr);
virtual void scummInit();
@@ -403,7 +403,7 @@ protected:
int _currentMode;
public:
- ScummEngine_c64(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_c64(OSystem *syst, const DetectorResult &dr);
virtual void scummInit();
@@ -555,7 +555,7 @@ protected:
public:
- ScummEngine_v6(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v6(OSystem *syst, const DetectorResult &dr);
virtual void scummInit();
@@ -784,7 +784,7 @@ protected:
#ifndef DISABLE_SCUMM_7_8
class ScummEngine_v7 : public ScummEngine_v6 {
public:
- ScummEngine_v7(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v7(OSystem *syst, const DetectorResult &dr);
~ScummEngine_v7();
struct LangIndexNode {
@@ -865,7 +865,7 @@ protected:
ObjectNameId *_objectIDMap;
public:
- ScummEngine_v8(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine_v8(OSystem *syst, const DetectorResult &dr);
~ScummEngine_v8();
protected:
diff --git a/engines/scumm/plugin.cpp b/engines/scumm/plugin.cpp
index 69fcf553ba..c92b908846 100644
--- a/engines/scumm/plugin.cpp
+++ b/engines/scumm/plugin.cpp
@@ -186,25 +186,34 @@ static const ObsoleteGameID obsoleteGameIDsTable[] = {
{NULL, NULL, UNK}
};
-// The following table contains information about variants of our various games.
-// We index into it with help of md5table (from scumm-md5.h), to find the correct
-// GameSettings for a given game variant.
+// The following table contains information about variants of our various
+// games. We index into it with help of md5table (from scumm-md5.h), to find
+// the correct GameSettings for a given game variant.
//
// The first listed variant is assumed to be the 'default' variant -- i.e. the
// variant that gets used when no explicit variant code has been specified.
//
-// Note: Only set 'platform' to a value different from UNK if that game variant
-// really *only* exists for that given platform. In all other cases, the correct
-// platform will be determined via the MD5 table or derived from the filename.
+// Note #1: Only set 'platform' to a value different from UNK if that game
+// variant really *only* exists for that given platform. In all other cases,
+// the correct platform will be determined via the MD5 table or derived from
+// the filename.
+//
+// Note #2: Make sure that all variants for a given gameid are in sequence with
+// no gaps. Some code may rely on this and stop searching the table early as
+// soon as the gameid changes.
+//
+// Note #3: Use 0 (zero) for the variant field *if and only if* the game has
+// only a single unique variant. This is used to help the detector quickly
+// decide whether it has to worry about distinguishing multiple variants or not.
static const GameSettings gameVariantsTable[] = {
- // The C64 version of MM is detected via the platform field and hence has no seperate entry in this list
- {"maniac", "V2", GID_MANIAC, 2, 0, MDT_PCSPK, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, UNK},
- {"maniac", "NES", GID_MANIAC, 1, 0, MDT_NONE, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, Common::kPlatformNES},
- {"maniac", "V1", GID_MANIAC, 1, 0, MDT_PCSPK, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, Common::kPlatformPC},
+ {"maniac", "C64", GID_MANIAC, 0, 0, MDT_PCSPK, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, Common::kPlatformC64},
+ {"maniac", "V1", GID_MANIAC, 1, 0, MDT_PCSPK, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, Common::kPlatformPC},
+ {"maniac", "NES", GID_MANIAC, 1, 0, MDT_NONE, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, Common::kPlatformNES},
+ {"maniac", "V2", GID_MANIAC, 2, 0, MDT_PCSPK, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, UNK},
+ {"maniac", "Demo", GID_MANIAC, 2, 0, MDT_PCSPK, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE | GF_DEMO, Common::kPlatformPC},
- // The C64 version of Zak is detected via the platform field and hence has no seperate entry in this list
+ {"zak", "V1", GID_ZAK, 1, 0, MDT_PCSPK, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, UNK},
{"zak", "V2", GID_ZAK, 2, 0, MDT_PCSPK, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, UNK},
- {"zak", "V1", GID_ZAK, 1, 0, MDT_PCSPK, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, Common::kPlatformPC},
{"zak", "FM-TOWNS", GID_ZAK, 3, 0, MDT_TOWNS, GF_SMALL_HEADER | GF_NO_SCALING | GF_OLD256 | GF_AUDIOTRACKS, Common::kPlatformFMTowns},
{"indy3", "EGA", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, GF_SMALL_HEADER | GF_NO_SCALING | GF_16COLOR | GF_USE_KEY | GF_OLD_BUNDLE, UNK},
@@ -259,58 +268,58 @@ static const GameSettings gameVariantsTable[] = {
{"fbear", "HE 70", GID_FBEAR, 6, 70, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, Common::kPlatformWindows},
#ifndef DISABLE_HE
- {"activity", "", GID_HEGAME, 6, 70, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"activity", 0, GID_HEGAME, 6, 70, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
// Humongous Entertainment Scumm Version 7.1
// The first version to use 640x480 resolution
// There are also 7.1 versions of freddemo, airdemo and farmdemo
- {"catalog", "", GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"freddi", "", GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"catalog", 0, GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"freddi", 0, GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
// Humongous Entertainment Scumm Version 7.2
- {"airport", "", GID_HEGAME, 6, 72, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"puttzoo", "", GID_HEGAME, 6, 72, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"airport", 0, GID_HEGAME, 6, 72, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"puttzoo", 0, GID_HEGAME, 6, 72, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
// Changed o_getResourceSize to cover all resource types
- {"farm", "", GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"jungle", "", GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"farm", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"jungle", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
// Humongous Entertainment Scumm Version 8.0 ? Scummsrc.80
- {"freddi2", "", GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"pajama", "", GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"putttime", "", GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"freddi2", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"pajama", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"putttime", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"balloon", "", GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"dog", "", GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"maze", "", GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"socks", "", GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"balloon", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"dog", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"maze", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"socks", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
{"water", "", GID_WATER, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
{"water", "HE 80", GID_WATER, 6, 80, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
{"water", "HE 99", GID_WATER, 6, 99, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
// Humongous Entertainment Scumm Version 9.0 ? Scummsys.90
- {"baseball", "", GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"thinkerk", "", GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"thinker1", "", GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"freddi3", "", GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"spyfox", "", GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"baseball", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"thinkerk", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"thinker1", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"freddi3", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"spyfox", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
// Humongous Entertainment Scumm Version 9.5 ? Scummsys.95
- {"pajama2", "", GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"chase", "", GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"pajama2", 0, GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"chase", 0, GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
// Humongous Entertainment Scumm Version 9.8 ? Scummsys.98
// these and later games can easily be identified by the .(a) file instead of a .he1
// and INIB chunk in the .he0
- {"lost", "", GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"lost", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
{"puttrace", "HE 98", GID_PUTTRACE, 6, 98, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
{"puttrace", "HE 98.5", GID_PUTTRACE, 6, 98, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES | GF_HE_985, UNK},
{"puttrace", "HE 99", GID_PUTTRACE, 6, 99, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"bluesabctime", "", GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
- {"soccer", "", GID_SOCCER, 6, 98, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"bluesabctime", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
+ {"soccer", 0, GID_SOCCER, 6, 98, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES, UNK},
// Global scripts increased to 2048
{"freddi4", "", GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_NEW_COSTUMES | GF_HE_985, UNK},
@@ -369,256 +378,6 @@ static const GameSettings gameVariantsTable[] = {
{NULL, NULL, 0, 0, MDT_NONE, 0, 0, UNK}
};
-static const SubstResFileNames substResFileNameTable[] = {
- // The first few entries for 00.LFL/01.LFL files are here for two reasons:
- // 1) For the detector to detect these games
- // 2) Because the ScummEngine constructor distinguishes between extracted
- // and non-extracted variants of these C64/NES games by the presence
- // or absence of a SubstResFileNames record.
- // Use 1 will go away with the new detector code. Use 2 needs some more
- // attention, but most likely should be solved by passing the name of the
- // "detect file" to the contructor.
- { "00.LFL", "Maniac Mansion (E).prg", kGenAsIs },
- { "00.LFL", "Maniac Mansion (F).prg", kGenAsIs },
- { "00.LFL", "Maniac Mansion (SW).prg", kGenAsIs },
- { "00.LFL", "Maniac Mansion (U).prg", kGenAsIs },
- { "00.LFL", "Maniac Mansion (G).prg", kGenAsIs },
- { "00.LFL", "maniac1.d64", kGenAsIs }, // Do not
- { "01.LFL", "maniac2.d64", kGenAsIs }, // swap
- { "00.LFL", "zak1.d64", kGenAsIs }, // these
- { "01.LFL", "zak2.d64", kGenAsIs }, // lines
-
- { "atlantis", "Fate of Atlantis Data", kGenAsIs },
- { "atlantis", "fate", kGenPC },
- { "atlantis", "playfate", kGenPC },
- { "atlantis", "indy4", kGenPC },
- { "atlantis", "indydemo", kGenPC },
- { "tentacle", "Day of the Tentacle Data", kGenAsIs },
- { "tentacle", "dottdemo", kGenPC },
- { "tentacle", "Day of the Tentacle Demo Data", kGenAsIs },
- { "monkey", "monkey1", kGenPC },
- { "monkey", "monkeyk", kGenPC }, // FM-TOWNS Jap
- { "monkey", "game", kGenPC }, // SegaCD
- { "monkey2", "mi2demo", kGenPC },
- { "samnmax", "Sam & Max Data", kGenAsIs },
- { "samnmax", "Sam & Max Demo Data", kGenAsIs },
- { "samnmax", "ramnmax", kGenPC }, // Used in some releases of Russian Sam'n'Max
- { "samnmax", "samdemo", kGenPC },
- { "samnmax", "snmdemo", kGenPC },
- { "samnmax", "snmidemo", kGenPC },
- { "samnmax", "sdemo", kGenPC },
-#ifndef DISABLE_SCUMM_7_8
- { "dig", "The Dig Data", kGenAsIs },
- { "dig", "The Dig Demo Data", kGenAsIs },
- { "ft", "Full Throttle Data", kGenAsIs },
- { "ft", "Full Throttle Demo Data", kGenAsIs },
- { "ft", "Vollgas Data", kGenAsIs },
- { "ft", "Vollgas Demo Data", kGenAsIs },
- { "ft", "ftdemo", kGenPC },
-#endif
- { "fbear", "fbdemo", kGenPC },
- { "fbear", "Fatty Bear Demo", kGenMacNoParens },
- { "fbear", "Fatty Bear", kGenMacNoParens },
- { "puttmoon", "moondemo", kGenPC },
- { "puttmoon", "Putt-Putt Moon Demo", kGenMacNoParens },
- { "puttmoon", "Putt-Putt Moon", kGenMacNoParens },
- { "puttputt", "puttdemo", kGenPC },
- { "puttputt", "Putt-Putt's Demo", kGenMacNoParens },
- { "puttputt", "Putt-Putt Parade", kGenMacNoParens },
-#ifndef DISABLE_HE
- { "airport", "airdemo", kGenPC },
- { "airport", "Airport Demo", kGenMac },
- { "airport", "The AirPort", kGenMac },
- { "balloon", "Balloon-O-Rama", kGenMac },
- { "baseball", "BaseBall", kGenMac },
- { "baseball2001", "bb2demo", kGenPC },
- { "baseball2001", "Baseball 2001 Demo", kGenMac },
- { "baseball2001", "Baseball 2001", kGenMac },
- { "baseball2001", "baseball 2001", kGenPC },
- { "Baseball2003", "Baseball 2003", kGenMac },
- { "basketball", "Basketball", kGenMac },
- { "bluesabctime", "BluesABCTimeDemo", kGenPC },
- { "bluesabctime", "BluesABCTimeDemo", kGenMac },
- { "catalog", "catalog2", kGenPC },
- { "chase", "Cheese Chase", kGenMac },
- { "dog", "Dog on a Stick", kGenMac },
- { "farm", "farmdemo", kGenPC },
- { "farm", "Farm Demo", kGenMac },
- { "football", "FootBall", kGenMac },
- { "football", "FootBall Demo", kGenMac },
- { "football", "FootBall2002", kGenPC },
- { "football", "footdemo", kGenPC },
- { "freddi", "freddemo", kGenPC },
- { "freddi", "Freddi Demo", kGenMac },
- { "freddi", "Freddi Fish", kGenMac },
- { "freddi", "FreddiD", kGenPC },
- { "freddi2", "ff2-demo", kGenPC },
- { "freddi2", "FFHSDemo", kGenMac },
- { "freddi2", "FFHSDemo", kGenPC },
- { "freddi2", "Freddi Fish 2 Demo", kGenMac },
- { "freddi2", "Freddi Fish 2", kGenMac },
- { "freddi2", "FreddiCHSH", kGenPC },
- { "freddi2", "Fritzi Fisch 2", kGenMac },
- { "freddi3", "F3-mdemo", kGenMac },
- { "freddi3", "F3-Mdemo", kGenMac },
- { "freddi3", "f3-mdemo", kGenPC },
- { "freddi3", "FF3-DEMO", kGenPC },
- { "freddi3", "Freddi Fish 3", kGenMac },
- { "freddi3", "FreddiFGT", kGenPC },
- { "freddi3", "FreddiFGT", kGenMac },
- { "freddi3", "FreddiSCS", kGenPC },
- { "freddi3", "Fritzi3demo", kGenMac },
- { "freddi3", "Fritzi3demo", kGenPC },
- { "freddi3", "MM3-DEMO", kGenPC },
- { "freddi3", "MM3-Demo", kGenMac }, // FR Mac demo
- { "freddi4", "f4-demo", kGenPC },
- { "freddi4", "ff4demo", kGenPC },
- { "freddi4", "Ff4demo", kGenMac },
- { "freddi4", "Freddi 4", kGenMac },
- { "freddi4", "Freddi 4 Demo", kGenMac },
- { "freddi4", "FreddiGS", kGenPC },
- { "freddi4", "FreddiGS", kGenMac },
- { "freddi4", "FreddiHRBG", kGenPC },
- { "freddicove", "FreddiCCC", kGenPC },
- { "freddicove", "FreddiCove", kGenMac },
- { "freddicove", "FreddiDZZ", kGenPC },
- { "freddicove", "ff5demo", kGenPC },
- { "freddicove", "FFCoveDemo", kGenPC },
- { "freddicove", "FreddiCoveDemo", kGenMac },
- { "freddicove", "FF5Demo", kGenMac }, // NL Mac demo
- { "FreddisFunShop", "Freddi's FunShop", kGenMac },
- { "jungle", "The Jungle", kGenMac },
- { "lost", "Lost and Found", kGenMac },
- { "lost", "smaller", kGenPC },
- { "maze", "Maze Madness", kGenMac},
- { "mustard", "Mustard", kGenMac },
- { "pajama", "Pyjama Pit", kGenMac },
- { "pajama", "Pajama Sam", kGenMac },
- { "pajama", "PajamaNHD", kGenPC },
- { "pajama", "PJS-DEMO", kGenPC },
- { "pajama", "PYJAMA", kGenPC },
- { "pajama", "SAMDEMO", kGenPC },
- { "pajama", "SAMDEMO", kGenMac }, // FR Mac demo
- { "pajama2", "Pajama Sam 2", kGenMac },
- { "pajama2", "PajamaTAL", kGenPC },
- { "pajama2", "PyjamaDBMN", kGenPC },
- { "pajama2", "PyjamaDBMN", kGenMac },
- { "pajama2", "Pyjama Pit 2 Demo", kGenMac },
- { "pajama2", "PJP2DEMO", kGenPC },
- { "pajama2", "PJ2Demo", kGenMac },
- { "pajama2", "pj2demo", kGenPC },
- { "pajama2", "Pjs2demo", kGenPC },
- { "pajama2", "PJ2 Demo", kGenMac }, // NL Mac demo
- { "pajama3", "GPJ3Demo", kGenPC },
- { "pajama3", "Pajama Sam 3", kGenMac },
- { "pajama3", "Pajama Sam 3-Demo", kGenMac },
- { "pajama3", "pj3-demo", kGenPC },
- { "pajama3", "pj3demo", kGenPC },
- { "pajama3", "PJ3Demo", kGenMac },
- { "pajama3", "Pajama Sam Demo", kGenMac },
- { "pajama3", "PjSamDemo", kGenMac },
- { "pajama3", "PjSamDemo", kGenPC },
- { "pajama3", "PyjamaSKS", kGenPC },
- { "pajama3", "PyjamaSKS", kGenMac },
- { "pajama3", "UKPajamaEAT", kGenPC }, // Russian
- { "pjgames", "PJGames", kGenMac },
- { "puttcircus", "circdemo", kGenPC },
- { "puttcircus", "Putt Circus Demo", kGenMac },
- { "puttcircus", "Putt Circus", kGenMac },
- { "puttrace", "500demo", kGenPC },
- { "puttrace", "racedemo", kGenPC },
- { "puttrace", "RaceDemo", kGenMac },
- { "puttrace", "Rennen", kGenPC },
- { "puttrace", "Putt500 demo", kGenMac }, // NL Mac demo
- { "puttrace", "Putt Race", kGenMac },
- { "puttrace", "ToffRennen", kGenPC },
- { "puttrace", "ToffRennen", kGenMac },
- { "puttrace", "UKPuttRace", kGenPC }, // Russian
- { "PuttsFunShop", "Putt's FunShop", kGenMac },
- { "putttime", "PuttPuttTTT", kGenPC },
- { "putttime", "PuttPuttTTT", kGenMac },
- { "putttime", "PuttTijd", kGenPC },
- { "putttime", "Putt Time", kGenMac },
- { "putttime", "PuttTTT", kGenMac },
- { "putttime", "PuttTTT", kGenPC },
- { "putttime", "TIJDDEMO", kGenPC },
- { "putttime", "timedemo", kGenPC },
- { "putttime", "TimeDemo", kGenMac },
- { "putttime", "TEMPDEMO", kGenPC },
- { "putttime", "Tempdemo", kGenMac }, // FR Mac demo
- { "putttime", "toffzeit", kGenPC }, // German Toeff-Toeff: Reist durch die Zeit
- { "putttime", "toffzeit", kGenMac }, // German Toeff-Toeff: Reist durch die Zeit
- { "putttime", "ZeitDemo", kGenMac },
- { "putttime", "ZEITDEMO", kGenPC },
- { "puttzoo", "Puttzoo Demo", kGenMac },
- { "puttzoo", "PuttZoo", kGenMac },
-
- { "puttzoo", "T\xC3\xB6""ff-T\xC3\xB6""ff\xE2\x84\xA2 Zoo Demo", kGenMac }, // German Toeff-Toeff, UTF-8 encoding
- { "puttzoo", "T\xF6""ff-T""\xF6""ff\x99 Zoo Demo", kGenMac }, // German Toeff-Toeff, Windows encoding
-
- { "puttzoo", "zoodemo", kGenPC },
- { "puttzoo", "Zoo Demo", kGenMac },
- { "SamsFunShop", "Sam's FunShop", kGenMac },
- { "soccer", "Soccer", kGenMac },
- { "Soccer2004", "Soccer 2004", kGenMac },
- { "socks", "SockWorks", kGenMac },
- { "spyfox", "Fuchsdem", kGenMac },
- { "spyfox", "FUCHSDEM", kGenPC},
- { "spyfox", "FoxDemo", kGenMac },
- { "spyfox", "foxdemo", kGenPC},
- { "spyfox", "JAMESDEM", kGenPC },
- { "spyfox", "Spydemo", kGenMac},
- { "spyfox", "Spydemo", kGenPC},
- { "spyfox", "SPYFox", kGenMac },
- { "spyfox", "SPYFoxDC", kGenPC },
- { "spyfox", "SPYFoxDC", kGenMac },
- { "spyfox", "SpyFoxDMK", kGenPC },
- { "spyfox", "SpyFoxDMK", kGenMac },
- { "spyfox", "Spy Fox Demo", kGenMac }, // NL Mac demo
- { "spyfox", "JR-Demo", kGenMac }, // FR Mac demo
- { "spyfox2", "sf2-demo", kGenPC },
- { "spyfox2", "sf2demo", kGenPC },
- { "spyfox2", "Sf2demo", kGenMac },
- { "spyfox2", "Spy Fox 2 - Demo", kGenMac },
- { "spyfox2", "Spy Fox 2", kGenMac },
- { "spyfox2", "SpyFoxOR", kGenPC },
- { "spyfox2", "SpyFoxOR", kGenMac },
- { "spyfox2", "spyfoxsr", kGenPC },
- { "spyozon", "sf3-demo", kGenPC },
- { "spyozon", "Spy Ozone Demo", kGenMac },
- { "spyozon", "SPYFoxOZU", kGenPC },
- { "spyozon", "SpyOzon", kGenMac },
- { "thinker1", "1grademo", kGenPC },
- { "thinker1", "Thinker1", kGenMac },
- { "thinkerk", "kinddemo", kGenPC },
- { "thinkerk", "KindDemo", kGenMac },
- { "thinkerk", "ThinkerK", kGenMac },
- { "water", "Water Worries", kGenMac },
-#endif
- { NULL, NULL, kGenAsIs }
-};
-
-
-#if 0
-
-enum FilenameGenMethod {
- kGenDiskNum,
- kGenRoomNum,
- kGenHEMac,
- kGenHEMacNoParens,
- kGenHEPC,
- kGenUnchanged
-};
-
-struct GameFilenamePattern {
- const char *gameid;
- const char *pattern;
- FilenameGenMethod genMethod;
- Common::Language language;
- Common::Platform platform;
- const char *variant;
-};
-
using Common::UNK_LANG;
// The following describes how Fingolfin thinks this table might be used one day;
@@ -635,68 +394,68 @@ using Common::UNK_LANG;
// Note: Setting variant to 0 means "don't care", while setting it to ""
// (i.e. an empty string) means "use the default variant".
static const GameFilenamePattern gameFilenamesTable[] = {
- { "maniac", "%.2d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "maniac", "%.2d.MAN", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "maniac", "maniac1.d64", kGenUnchanged, UNK_LANG, Common::kPlatformC64, 0 }, // ... and maniac2.d64
+ { "maniac", "%02d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "maniac", "%02d.MAN", kGenRoomNum, UNK_LANG, UNK, "Demo" },
+ { "maniac", "maniac1.d64", kGenUnchanged, UNK_LANG, Common::kPlatformC64, "C64" }, // ... and maniac2.d64
{ "maniac", "Maniac Mansion (E).prg", kGenUnchanged, Common::EN_GRB, Common::kPlatformNES, "NES" },
{ "maniac", "Maniac Mansion (F).prg", kGenUnchanged, Common::FR_FRA, Common::kPlatformNES, "NES" },
{ "maniac", "Maniac Mansion (SW).prg", kGenUnchanged, Common::SE_SWE, Common::kPlatformNES, "NES" },
{ "maniac", "Maniac Mansion (U).prg", kGenUnchanged, Common::EN_USA, Common::kPlatformNES, "NES" },
{ "maniac", "Maniac Mansion (G).prg", kGenUnchanged, Common::DE_DEU, Common::kPlatformNES, "NES" },
- { "zak", "%.2d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "zak", "%02d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
{ "zak", "zak1.d64", kGenUnchanged, UNK_LANG, Common::kPlatformC64, 0 }, // ... and zak2.d64
- { "indy3", "%.2d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "indy3", "%02d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "loom", "%.2d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "loom", "%.3d.LFL", kGenRoomNum, UNK_LANG, UNK, "VGA" }, // Loom CD
+ { "loom", "%02d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "loom", "%03d.LFL", kGenRoomNum, UNK_LANG, UNK, "VGA" }, // Loom CD
- { "pass", "%.3d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "pass", "%03d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "monkey", "%.3d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 }, // EGA & VGA versions
- { "monkey", "monkey.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "monkey", "monkey1.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "monkey", "monkeyk.%.3d", kGenRoomNum, Common::JA_JPN, Common::kPlatformFMTowns, "FM-TOWNS" }, // FM-TOWNS Jap
- { "monkey", "game.%.3d", kGenRoomNum, UNK_LANG, Common::kPlatformSegaCD, "SEGA" }, // SegaCD
+ { "monkey", "%03d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 }, // EGA & VGA versions
+ { "monkey", "monkey.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "monkey", "monkey1.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "monkey", "monkeyk.%03d", kGenDiskNum, Common::JA_JPN, Common::kPlatformFMTowns, "FM-TOWNS" }, // FM-TOWNS Jap
+ { "monkey", "game.%03d", kGenDiskNum, UNK_LANG, Common::kPlatformSegaCD, "SEGA" }, // SegaCD
- { "monkey2", "monkey2.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "monkey2", "mi2demo.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "monkey2", "monkey2.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "monkey2", "mi2demo.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
- { "atlantis", "atlantis.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "atlantis", "fate.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "atlantis", "playfate.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "atlantis", "indy4.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "atlantis", "indydemo.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "atlantis", "atlantis.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "atlantis", "fate.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "atlantis", "playfate.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "atlantis", "indy4.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "atlantis", "indydemo.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
{ "atlantis", "Fate of Atlantis Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
- { "tentacle", "tentacle.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "tentacle", "dottdemo.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "tentacle", "tentacle.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "tentacle", "dottdemo.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
{ "tentacle", "Day of the Tentacle Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "tentacle", "Day of the Tentacle Demo Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
- { "samnmax", "samnmax.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "samnmax", "samnmax.sm%d", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "samnmax", "samnmax.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "samnmax", "samnmax.sm%d", kGenDiskNum, UNK_LANG, UNK, 0 },
{ "samnmax", "Sam & Max Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "samnmax", "Sam & Max Demo Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
- { "samnmax", "ramnmax.%.3d", kGenRoomNum, Common::RU_RUS, UNK, 0 }, // Used in some releases of Russian Sam'n'Max
- { "samnmax", "samdemo.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "samnmax", "snmdemo.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "samnmax", "snmidemo.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
- { "samnmax", "sdemo.%.3d", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "samnmax", "ramnmax.%03d", kGenDiskNum, Common::RU_RUS, UNK, 0 }, // Used in some releases of Russian Sam'n'Max
+ { "samnmax", "samdemo.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "samnmax", "snmdemo.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "samnmax", "snmidemo.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "samnmax", "sdemo.sm%d", kGenDiskNum, UNK_LANG, UNK, 0 },
#ifndef DISABLE_SCUMM_7_8
{ "dig", "dig.la%d", kGenDiskNum, UNK_LANG, UNK, 0 },
{ "dig", "The Dig Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
- { "dig", "The Dig Demo Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
+ { "dig", "The Dig Demo Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, "Demo" },
{ "ft", "ft.la%d", kGenDiskNum, UNK_LANG, UNK, 0 },
- { "ft", "ft.%.3d", kGenDiskNum, UNK_LANG, UNK, 0 }, // Used by PC version of Full Throttle demo
- { "ft", "ftdemo.la%d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "ft", "ft.%03d", kGenDiskNum, UNK_LANG, UNK, "Demo" }, // Used by PC version of Full Throttle demo
+ { "ft", "ftdemo.la%d", kGenDiskNum, UNK_LANG, UNK, "Demo" },
{ "ft", "Full Throttle Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
- { "ft", "Full Throttle Demo Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
+ { "ft", "Full Throttle Demo Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, "Demo" },
{ "ft", "Vollgas Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
- { "ft", "Vollgas Demo Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
+ { "ft", "Vollgas Demo Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, "Demo" },
{ "comi", "comi.la%d", kGenDiskNum, UNK_LANG, UNK, 0 },
#endif
@@ -968,8 +727,6 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ NULL, NULL, kGenUnchanged, UNK_LANG, UNK, 0 }
};
-#endif
-
#pragma mark -
#pragma mark --- Miscellaneous ---
@@ -1002,29 +759,26 @@ const MD5Table *findInMD5Table(const char *md5) {
return (const MD5Table *)bsearch(md5, md5table, arraySize, sizeof(MD5Table), compareMD5Table);
}
-#if 0
Common::String ScummEngine::generateFilename(const int room) const {
- // HACK to drive test compiles; of course _substEntry would be a member var of ScummEngine
- const GameFilenamePattern _substEntry = { "maniac", "%.2d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 };
const int diskNumber = room ? res.roomno[rtRoom][room] : 0;
char buf[128];
if (_game.version == 4) {
if (room == 0 || room >= 900) {
- snprintf(buf, sizeof(buf), "%.3d.lfl", room);
+ snprintf(buf, sizeof(buf), "%03d.lfl", room);
} else {
- snprintf(buf, sizeof(buf), "disk%.2d.lec", diskNumber);
+ snprintf(buf, sizeof(buf), "disk%02d.lec", diskNumber);
}
} else {
char id = 0;
- switch (_substEntry.genMethod) {
+ switch (_filenamePattern.genMethod) {
case kGenDiskNum:
- snprintf(buf, sizeof(buf), _substEntry.pattern, diskNumber);
+ snprintf(buf, sizeof(buf), _filenamePattern.pattern, diskNumber);
break;
case kGenRoomNum:
- snprintf(buf, sizeof(buf), _substEntry.pattern, room);
+ snprintf(buf, sizeof(buf), _filenamePattern.pattern, room);
break;
case kGenHEMac:
@@ -1039,15 +793,15 @@ Common::String ScummEngine::generateFilename(const int room) const {
switch(disk) {
case 2:
id = 'b';
- snprintf(buf, sizeof(buf), "%s.(b)", _substEntry.pattern);
+ snprintf(buf, sizeof(buf), "%s.(b)", _filenamePattern.pattern);
break;
case 1:
id = 'a';
- snprintf(buf, sizeof(buf), "%s.(a)", _substEntry.pattern);
+ snprintf(buf, sizeof(buf), "%s.(a)", _filenamePattern.pattern);
break;
default:
id = '0';
- snprintf(buf, sizeof(buf), "%s.he0", _substEntry.pattern);
+ snprintf(buf, sizeof(buf), "%s.he0", _filenamePattern.pattern);
}
} else if (_game.heversion >= 70) {
id = (room == 0) ? '0' : '1';
@@ -1055,24 +809,28 @@ Common::String ScummEngine::generateFilename(const int room) const {
id = diskNumber + '0';
}
- if (_substEntry.genMethod == kGenHEPC) {
+ if (_filenamePattern.genMethod == kGenHEPC) {
// For HE >= 98, we already called snprintf above.
if (_game.heversion < 98)
- snprintf(buf, sizeof(buf), "%s.he%c", _substEntry.pattern, id);
+ snprintf(buf, sizeof(buf), "%s.he%c", _filenamePattern.pattern, id);
} else {
if (id == '3') { // special case for cursors
// For mac they're stored in game binary
- strncpy(buf, _substEntry.pattern, sizeof(buf));
+ strncpy(buf, _filenamePattern.pattern, sizeof(buf));
} else {
- if (_substEntry.genMethod == kGenHEMac)
- snprintf(buf, sizeof(buf), "%s (%c)", _substEntry.pattern, id);
+ if (_filenamePattern.genMethod == kGenHEMac)
+ snprintf(buf, sizeof(buf), "%s (%c)", _filenamePattern.pattern, id);
else
- snprintf(buf, sizeof(buf), "%s %c", _substEntry.pattern, id);
+ snprintf(buf, sizeof(buf), "%s %c", _filenamePattern.pattern, id);
}
}
break;
+ case kGenUnchanged:
+ strncpy(buf, _filenamePattern.pattern, sizeof(buf));
+ break;
+
default:
error("generateFilename: Unsupported genMethod");
}
@@ -1080,9 +838,7 @@ Common::String ScummEngine::generateFilename(const int room) const {
return buf;
}
-#endif
-#if 0
Common::String generateFilenameForDetection(const GameFilenamePattern &gfp) {
char buf[128];
@@ -1104,6 +860,10 @@ Common::String generateFilenameForDetection(const GameFilenamePattern &gfp) {
snprintf(buf, sizeof(buf), "%s 0", gfp.pattern);
break;
+ case kGenUnchanged:
+ strncpy(buf, gfp.pattern, sizeof(buf));
+ break;
+
default:
error("generateFilenameForDetection: Unsupported genMethod");
}
@@ -1114,19 +874,15 @@ Common::String generateFilenameForDetection(const GameFilenamePattern &gfp) {
struct DetectorDesc {
Common::String path;
Common::String md5;
+ uint8 md5sum[16];
const MD5Table *md5Entry; // Entry of the md5 table corresponding to this file, if any.
};
-
-struct DetectorResult {
- const GameFilenamePattern *gfp;
- GameSettings game;
-};
-
-void detectGames(const char *gameid_XXX, const FSList &fslist, Common::List<DetectorResult> &results) {
- typedef Common::HashMap<Common::String, DetectorDesc> DescMap;
+void detectGames(const FSList &fslist, Common::List<DetectorResult> &results, const char *gameid_XXX) {
+ typedef Common::HashMap<Common::String, DetectorDesc, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> DescMap;
DescMap fileMD5Map;
const GameSettings *g;
+ DetectorResult dr;
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (!file->isDirectory()) {
@@ -1150,8 +906,32 @@ void detectGames(const char *gameid_XXX, const FSList &fslist, Common::List<Dete
Common::String file(generateFilenameForDetection(*gfp));
if (!fileMD5Map.contains(file))
continue;
+
+ // Reset the DetectorResult variable
+ dr.fp.pattern = gfp->pattern;
+ dr.fp.genMethod = gfp->genMethod;
+ dr.game.gameid = 0;
+ dr.language = gfp->language;
+ dr.md5.clear();
+ memset(dr.md5sum, 0, 16);
+ dr.extra = 0;
- // OK, the file is present. Compute the MD5, if it hasn't been done yet.
+ // ____ _ _
+ // | _ \ __ _ _ __| |_ / |
+ // | |_) / _` | '__| __| | |
+ // | __/ (_| | | | |_ | |
+ // |_| \__,_|_| \__| |_|
+ //
+ // PART 1: Trying to find an exact match using MD5.
+ //
+ //
+ // Background: We found a valid detection file. Check if its MD5
+ // checksum occurs in our MD5 table. If it does, try to use that
+ // to find an exact match.
+ //
+ // We only do that if the MD5 hadn't already been computed (since
+ // we may look at some detection files multiple times).
+ //
DetectorDesc &d = fileMD5Map[file];
if (d.md5.empty()) {
uint8 md5sum[16];
@@ -1162,37 +942,33 @@ void detectGames(const char *gameid_XXX, const FSList &fslist, Common::List<Dete
}
d.md5 = md5str;
+ memcpy(d.md5sum, md5sum, 16);
d.md5Entry = findInMD5Table(md5str);
+ dr.md5 = d.md5;
+ memcpy(dr.md5sum, d.md5sum, 16);
+
if (d.md5Entry) {
// Exact match found
-
- // Sanity check: Make sure the gameids match!
- if (scumm_stricmp(d.md5Entry->gameid, gfp->gameid)) {
- error("SCUMM detectGames: MD5 %s implies gameid '%s', but gameid '%s' was expected",
- md5str, d.md5Entry->gameid, gfp->gameid);
- }
-
- DetectorResult dr;
- dr.game.gameid = 0;
- dr.gfp = gfp;
+ dr.language = d.md5Entry->language;
+ dr.extra = d.md5Entry->extra;
// Compute the precise game settings using gameVariantsTable.
for (g = gameVariantsTable; g->gameid; ++g) {
if (g->gameid[0] == 0 || !scumm_stricmp(d.md5Entry->gameid, g->gameid)) {
// The gameid either matches, or is empty (the latter indicates
- // a generic entry, used currently for generic HE specifies.
-
+ // a generic entry, currently used for some generic HE settings.
if (g->variant == 0 || !scumm_stricmp(d.md5Entry->variant, g->variant)) {
// Perfect match found, use it and stop the loop
dr.game = *g;
- dr.game.gameid = gfp->gameid;
- if (d.md5Entry->platform != Common::kPlatformUnknown) {
- if (dr.game.platform != Common::kPlatformUnknown && dr.game.platform != d.md5Entry->platform)
- warning("SCUMM detectGames: Platform values differ for MD5 '%s': %d vs %d (please report to Fingolfin)",
+ dr.game.gameid = d.md5Entry->gameid;
+
+ // Sanity check
+ if (dr.game.platform != Common::kPlatformUnknown && dr.game.platform != d.md5Entry->platform)
+ warning("SCUMM detectGames: Platform values differ for MD5 '%s': %d vs %d (please report to Fingolfin)",
md5str, dr.game.platform, d.md5Entry->platform);
- dr.game.platform = d.md5Entry->platform;
- }
+ dr.game.platform = d.md5Entry->platform;
+
results.push_back(dr);
break;
}
@@ -1208,255 +984,242 @@ void detectGames(const char *gameid_XXX, const FSList &fslist, Common::List<Dete
// If an exact match for this file has already been found, don't bother
// looking at it anymore.
- if (d.md5Entry != 0)
+ if (d.md5Entry)
continue;
- // At this point, the MD5 sum has been computed but is not known. We
- // still do our best to identify the game & variant correctly.
-
- // First step is to determine the correct gameid. Luckily, in most
- // cases the filename alone implies the gameid. Currently the only
- // exceptions are 00.LFL and 000.LFL, for which we add special cases
- // below.
+
+
+ // ____ _ ____
+ // | _ \ __ _ _ __| |_ |___ \ *
+ // | |_) / _` | '__| __| __) |
+ // | __/ (_| | | | |_ / __/
+ // |_| \__,_|_| \__| |_____|
+ //
+ // PART 2: Fuzzy matching for files with unknown MD5.
+ //
- // After that, we may take a peek at the file contents to further
- // narrow down the list of variants.
- // TODO: Should we do some sort of caching on the data we read? Like,
- // keep a copy of the first N bytes ?
+ // We loop over the game variants matching the gameid associated to
+ // the gfp record. We then try to decide for each whether it could be
+ // appropriate or not.
+ dr.md5 = d.md5;
+ memcpy(dr.md5sum, d.md5sum, 16);
+ for (g = gameVariantsTable; g->gameid; ++g) {
+ // Skip over entries with a different gameid.
+ if (g->gameid[0] == 0 || scumm_stricmp(gfp->gameid, g->gameid))
+ continue;
- Common::File tmp;
- if (!tmp.open(d.path.c_str())) {
- warning("SCUMM detectGames: failed to open '%s' for read access", d.path.c_str());
- continue;
- }
- byte buf[6];
- tmp.read(buf, 6);
-
- if (file == "00.LFL") {
- // Used in V1, V2, V3 games.
+ dr.game = *g;
+ dr.extra = g->variant; // FIXME: We (ab)use 'variant' for the 'extra' description for now.
+ if (gfp->platform != Common::kPlatformUnknown)
+ dr.game.platform = gfp->platform;
+
+
+ // If a variant has been specified, use that!
+ if (gfp->variant) {
+ if (!scumm_stricmp(gfp->variant, g->variant)) {
+ // perfect match found
+ results.push_back(dr);
+ break;
+ }
+ continue;
+ }
- if (buf[0] == 0xbc && buf[1] == 0xb9) {
- // The NES version of MM
- // TODO
- } else if (buf[0] == 0xCE && buf[1] == 0xF5) {
- // Looks like V1.
-
- // Candidates: maniac classic, zak classic
-
- // TODO: Maybe we can use the filesize to distinguish these two?
- // English V1 Zak: 1896 bytes
- // English V1 MM: 1972 bytes
-
- // Since it seems unlikely that there are other (official)
- // variants of these two games around, it should be safe to use
- // the filesize for detection. In case of an unknown size,
- // we just generate a warning and skip the file.
- } else if (buf[0] == 0xFF && buf[1] == 0xFE) {
- // GF_OLD_BUNDLE: could be V2 or old V3.
- // Candidates: maniac enhanced, zak enhanced, indy3ega, loom
- /*
- TODO: Might be possible to distinguish those by the script count.
- Specifically, my versions of these games have this in their headers:
-
- Loom (en; de; en demo; en MAC):
- _numGlobalObjects 1000
- _numRooms 100
- _numCostumes 200
- _numScripts 200
- _numSounds 80
-
- Indy3EGA (en PC; en Mac; en demo):
- _numGlobalObjects 1000
- _numRooms 99
- _numCostumes 129
- _numScripts 139
- _numSounds 84
-
- MM (en; de):
- _numGlobalObjects 780
- _numRooms 61
- _numCostumes 40
- _numScripts 179
- _numSounds 120
-
- Zak (de; en demo):
- _numGlobalObjects 780
- _numRooms 61
- _numCostumes 40
- _numScripts 155
- _numSounds 120
+ // Next possibility: There exists only a single variant of this
+ // gameid anyway (we know this is the case if g->variant is 0).
+ // Then of course we have no further work to do.
+ if (g->variant == 0) {
+ results.push_back(dr);
+ break;
+ }
+
+ // At this point, we know that the gameid matches, but no variant
+ // was specified, yet there are multiple ones. So we try our best
+ // to distinguish between the variants.
+ // To do this, we take a close look at the detection file and
+ // try to filter out some cases.
+
+ Common::File tmp;
+ if (!tmp.open(d.path.c_str())) {
+ warning("SCUMM detectGames: failed to open '%s' for read access", d.path.c_str());
+ continue;
+ }
+
+ if (file == "00.LFL") {
+ // Used in V1, V2, V3 games.
+ if (g->version > 3)
+ continue;
+
+ // Read a few bytes to narrow down the game.
+ byte buf[6];
+ tmp.read(buf, 6);
+
+ if (buf[0] == 0xbc && buf[1] == 0xb9) {
+ // The NES version of MM
+ if (g->id == GID_MANIAC && g->platform == Common::kPlatformNES) {
+ // perfect match
+ results.push_back(dr);
+ break;
+ }
+ } else if (buf[0] == 0xCE && buf[1] == 0xF5) {
+ // Looks like V1.
+ // Candidates: maniac classic, zak classic
+
+ if (g->version != 1)
+ continue;
+
+ // TODO: Maybe we can use the filesize to distinguish these two?
+ // English V1 Zak: 1896 bytes
+ // English V1 MM: 1972 bytes
- So, they all have a different number of scripts.
- */
- } else if (buf[4] == '0' && buf[5] == 'R') {
- // newer V3 game
- // Candidates: indy3, indy3Towns, zakTowns, loomTowns
+ // Since it seems unlikely that there are other (official)
+ // variants of these two games around, it should be safe to use
+ // the filesize for detection. In case of an unknown size,
+ // we just generate a warning and skip the file.
+ } else if (buf[0] == 0xFF && buf[1] == 0xFE) {
+ // GF_OLD_BUNDLE: could be V2 or old V3.
+ // Candidates: maniac enhanced, zak enhanced, indy3ega, loom
+
+ if (g->version != 2 && g->version != 3 || !(g->features & GF_OLD_BUNDLE))
+ continue;
+
+ /*
+ TODO: Might be possible to distinguish those by the script count.
+ Specifically, my versions of these games have this in their headers:
+
+ Loom (en; de; en demo; en MAC):
+ _numGlobalObjects 1000
+ _numRooms 100
+ _numCostumes 200
+ _numScripts 200
+ _numSounds 80
+
+ Indy3EGA (en PC; en Mac; en demo):
+ _numGlobalObjects 1000
+ _numRooms 99
+ _numCostumes 129
+ _numScripts 139
+ _numSounds 84
+
+ MM (en; de):
+ _numGlobalObjects 780
+ _numRooms 61
+ _numCostumes 40
+ _numScripts 179
+ _numSounds 120
+
+ Zak (de; en demo):
+ _numGlobalObjects 780
+ _numRooms 61
+ _numCostumes 40
+ _numScripts 155
+ _numSounds 120
+
+ So, they all have a different number of scripts.
+ */
+
+ /* Alternate approach: Distinguish by the presence/absence
+ of certain files. In the following, '+' means the file
+ present, '-' means the file is absent.
+
+ maniac: -58.LFL, -85.LFL, -86.LFL
+ zak: +58.LFL, -85.LFL, -86.LFL
+ indy3: +58.LFL, +85.LFL, +86.LFL
+ loom: +58.LFL, -85.LFL, +86.LFL
+ */
+
+ } else if (buf[4] == '0' && buf[5] == 'R') {
+ // newer V3 game
+ // Candidates: indy3, indy3Towns, zakTowns, loomTowns
+
+ if (g->version != 3 || (g->features & GF_OLD_BUNDLE))
+ continue;
+
+ /*
+ Considering that we know about *all* TOWNS versions,
+ and know their MD5s, we could simply rely on this and
+ if we find something which has an unknown MD5, assume
+ that it is an (so far unknown) version of Indy3.
+
+ We can combine this with a look at the resource headers:
+
+ Indy3:
+ _numGlobalObjects 1000
+ _numRooms 99
+ _numCostumes 129
+ _numScripts 139
+ _numSounds 84
+
+ Indy3Towns, ZakTowns, ZakLoom demo:
+ _numGlobalObjects 1000
+ _numRooms 99
+ _numCostumes 199
+ _numScripts 199
+ _numSounds 199
+
+ Assuming that all the town variants look like the latter, we can
+ do the check like this:
+ if (numScripts == 139)
+ assume Indy3
+ else if (numScripts == 199)
+ assume towns game
+ else
+ unknown, do not accept it
+ */
+ } else {
+ // TODO: Unknown file header, deal with it. Maybe an unencrypted
+ // variant...
+ // Anyway, we don't know to deal with the file, so we
+ // just skip it.
+ }
+ } else if (file == "000.LFL") {
+ // Used in V4
+ // Candidates: monkeyEGA, pass, monkeyVGA, loomcd
+
+ if (g->version != 4)
+ continue;
+
/*
- Considering that we know about *all* TOWNS versions,
- and know their MD5s, we could simply rely on this and
- if we find something which has an unknown MD5, assume
- that it is an (so far unknown) version of Indy3.
-
- We can combine this with a look at the resource headers:
-
- Indy3:
- _numGlobalObjects 1000
- _numRooms 99
- _numCostumes 129
- _numScripts 139
- _numSounds 84
-
- Indy3Towns, ZakTowns, ZakLoom demo:
+ For all of them, we have:
_numGlobalObjects 1000
_numRooms 99
_numCostumes 199
_numScripts 199
_numSounds 199
-
- Assuming that all the town variants look like the latter, we can
- do the check like this:
- if (numScripts == 139)
- assume Indy3
- else if (numScripts == 199)
- assume towns game
- else
- unknown, do not accept it
+
+ Any good ideas to distinguish those? Maybe by the presence / absence
+ of some files?
+ At least PASS and the monkeyEGA demo differ by 903.LFL missing...
+ And the count of DISK??.LEC files differs depending on what version
+ you have (4 or 8 floppy versions).
+ loomcd of course shipped on only one "disc".
+
+ pass: 000.LFL, 901.LFL, 902.LFL, 904.LFL, disk01.lec
+ monkeyEGA: 000.LFL, 901-904.LFL, DISK01-09.LEC
+ monkeyEGA DEMO: 000.LFL, 901.LFL, 902.LFL, 904.LFL, disk01.lec
+ monkeyVGA: 000.LFL, 901-904.LFL, DISK01-04.LEC
+ loomcd: 000.LFL, 901-904.LFL, DISK01.LEC
*/
} else {
- // TODO: Unknown file header, deal with it. Maybe an unencrypted
- // variant...
- // Anyway, we don't know to deal with the file, so we
- // just skip it.
+ // So at this point the gameid is determined, but not necessarily
+ // the variant!
+
+ // TODO: Add code that handles this, at least for the non-HE games.
+ // Note sure how realistic it is to correctly detect HE-game
+ // variants, would require me to look at a sufficiently large
+ // sample collection of HE games (assuming I had the time :).
+
+
+ // TODO: For Mac versions in container file, we can sometimes
+ // distinguish the demo from the regular version by looking
+ // at the content of the container file and then looking for
+ // the *.000 file in there.
}
- } else if (file == "000.LFL") {
- // Used in V4
- // Candidates: monkeyEGA, pass, monkeyVGA, loomcd
- /*
- For all of them, we have:
- _numGlobalObjects 1000
- _numRooms 99
- _numCostumes 199
- _numScripts 199
- _numSounds 199
-
- Any good ideas to distinguish those? Maybe by the presence / absence
- of some files?
- At least PASS and the monkeyEGA demo differ by 903.LFL missing...
- And the count of DISK??.LEC files differs depending on what version
- you have (4 or 8 floppy versions).
- loomcd of course shipped on only one "disc".
- pass: 000.LFL, 901.LFL, 902.LFL, 904.LFL, disk01.lec
- monkeyEGA: 000.LFL, 901-904.LFL, DISK01-09.LEC
- monkeyEGA DEMO: 000.LFL, 901.LFL, 902.LFL, 904.LFL, disk01.lec
- monkeyVGA: 000.LFL, 901-904.LFL, DISK01-04.LEC
- loomcd: 000.LFL, 901-904.LFL, DISK01.LEC
- */
- } else {
- // So at this point the gameid is determined, but not necessarily
- // the variant!
-
- // TODO: Add code that does this, at least for the non-HE games.
- // Note sure how realistic it is to correctly detect HE-game
- // variants, would require me to look at a sufficiently large
- // sample collection of HE games (assuming I had the time :).
-
- }
- }
-}
-
-#endif
-
-
-#pragma mark -
-#pragma mark --- Filename substitution ---
-#pragma mark -
-
-
-static void applySubstResFileName(const SubstResFileNames &subst, char *buf, int bufsize, const char *ext, char num) {
- switch (subst.genMethod) {
- case kGenMac:
- case kGenMacNoParens:
- if (num == '3') { // special case for cursors
- // For mac they're stored in game binary
- strncpy(buf, subst.expandedName, bufsize);
- } else {
- if (subst.genMethod == kGenMac)
- snprintf(buf, bufsize, "%s (%c)", subst.expandedName, num);
- else
- snprintf(buf, bufsize, "%s %c", subst.expandedName, num);
- }
- break;
-
- case kGenPC:
- if (ext)
- snprintf(buf, bufsize, "%s%s", subst.expandedName, ext);
- else
- strncpy(buf, subst.expandedName, bufsize);
- break;
-
- case kGenAsIs:
- strncpy(buf, subst.expandedName, bufsize);
- break;
-
- default:
- *buf = 0;
- break;
- }
-}
-
-bool applySubstResFileName(const SubstResFileNames &subst, const char *filename, char *buf, int bufsize) {
- if (subst.almostGameID == 0)
- return false;
-
- size_t len = strlen(filename);
- assert(len > 0);
-
- char num = filename[len - 1];
-
- // In some cases we have .(a) and .(b) extensions
- if (num == ')')
- num = filename[len - 2];
-
- const char *ext = strrchr(filename, '.');
- if (ext)
- len = ext - filename;
-
- if (!scumm_strnicmp(filename, subst.almostGameID, len)) {
- applySubstResFileName(subst, buf, bufsize, ext, num);
- return true;
- }
-
- return false;
-}
-
-int findSubstResFileName(SubstResFileNames &subst, const char *filename, int index) {
- if (index < 0)
- return -1;
-
- size_t len = strlen(filename);
- assert(len > 0);
-
- char num = filename[len - 1];
-
- // In some cases we have .(a) and .(b) extensions
- if (num == ')')
- num = filename[len - 2];
-
- const char *ext = strrchr(filename, '.');
- if (ext)
- len = ext - filename;
-
- int i;
- for (i = index; substResFileNameTable[i].almostGameID; i++) {
- if (!scumm_strnicmp(filename, substResFileNameTable[i].almostGameID, len)) {
- subst = substResFileNameTable[i];
- return i+1;
+ // Add the file to the candidate list
+ results.push_back(dr);
}
}
- subst = substResFileNameTable[i];
- return -1;
}
} // End of namespace Scumm
@@ -1504,308 +1267,18 @@ GameDescriptor Engine_SCUMM_findGameID(const char *gameid) {
}
-enum {
- kDetectNameMethodsCount = 8
-};
-
-static bool generateDetectName(const GameSettings &g, int method, char *detectName) {
- detectName[0] = '\0';
-
- switch (method) {
- case 0:
- if (g.version <= 3)
- strcpy(detectName, "00.LFL");
- break;
- case 1:
- // FIXME: The following would normally only allow for V4 games. But
- // for loom, there is both a v3 and a v4 version, but due to the way
- // the detector works at this time, we'll only ever see the v3 variant
- // here.
- if (g.version == 3 || g.version == 4)
- strcpy(detectName, "000.LFL");
- break;
- case 2:
- if (g.version < 4 || g.version > 7)
- return false;
- strcpy(detectName, g.gameid);
- strcat(detectName, ".000");
- break;
- case 3:
- if (g.version >= 7) {
- strcpy(detectName, g.gameid);
- strcat(detectName, ".la0");
- }
- break;
- case 4:
- if (g.heversion != 0) {
- strcpy(detectName, g.gameid);
- strcat(detectName, ".he0");
- }
- break;
- case 5:
- // FIXME: Fingolfin asks: For which games is this case used?
- // Please document this. Also: Why was this case missing in
- // Engine_SCUMM_create ?
- strcpy(detectName, g.gameid);
- break;
- case 6:
- if (g.id == GID_SAMNMAX) {
- strcpy(detectName, g.gameid);
- strcat(detectName, ".sm0");
- }
- break;
- case 7:
- if (g.id == GID_MANIAC)
- strcpy(detectName, "00.MAN");
- break;
- default:
- return false;
- }
-
- if (!detectName[0])
- return false;
-
- return true;
-}
-
DetectedGameList Engine_SCUMM_detectGames(const FSList &fslist) {
DetectedGameList detectedGames;
- const GameSettings *g;
- char detectName[128];
- char tempName[128];
- SubstResFileNames subst = { 0, 0, kGenAsIs };
-
- typedef Common::HashMap<Common::String, bool> StringSet;
- StringSet fileSet;
+ Common::List<DetectorResult> results;
- const char *lastGameid = "";
-
- for (g = gameVariantsTable; g->gameid; ++g) {
- // HACK: For now we only consider the first ("default") variant for
- // gameids that have multiple variants. In a future version of the
- // detector code, this may change.
- if (0 == strcmp(lastGameid, g->gameid) || *(g->gameid) == 0)
- continue;
- lastGameid = g->gameid;
+ detectGames(fslist, results, 0);
- // Determine the 'detectname' for this game, that is, the name of a
- // file that *must* be presented if the directory contains the data
- // for this game. For example, FOA requires atlantis.000
-
- // TODO: we need to add cache here
- for (int method = 0; method < kDetectNameMethodsCount; method++) {
- if (!generateDetectName(*g, method, detectName))
- continue;
-
- strcpy(tempName, detectName);
-
- int substLastIndex = 0;
-
- do {
- // Iterate over all files in the given directory
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (!file->isDirectory()) {
- const char *name = file->displayName().c_str();
-
- if (0 == scumm_stricmp(detectName, name)) {
- byte buf[6];
-
- if (g->version < 4) {
- // We take a look at the file now, to narrow
- // down the list of possible candidates a bit further.
- // E.g. it's trivial to distinguish V1 from V3 games.
- Common::File tmp;
- if (!tmp.open(file->path().c_str()))
- break;
- tmp.read(buf, 6);
-
- if (buf[0] == 0xCE && buf[1] == 0xF5) {
- // Looks like V1. However, we currently do not distinguish between V1 and V2
- // in the scumm_settings list.
- if (g->version != 1 && g->version != 2)
- break;
-
- // Candidates: maniac clasic, zak classic
-
- // TODO: Maybe we can use the filesize to distinguish these two?
- // English V1 Zak: 1896 bytes
- // English V1 MM: 1972 bytes
- // It would be interesting if those sizes are the same for other language
- // variants of these games, or for demos?
- } else if (buf[0] == 0xFF && buf[1] == 0xFE) {
- // GF_OLD_BUNDLE: could be V2 or old V3.
- if (!(g->features & GF_OLD_BUNDLE) || (g->version != 2 && g->version != 3))
- break;
- // Candidates: maniac enhanced, zak enhanced, indy3ega, loom
- /*
- TODO: Might be possible to distinguish those by the script count.
- Specifically, my versions of these games have this in their headers:
-
- Loom (en; de; en demo; en MAC):
- _numGlobalObjects 1000
- _numRooms 100
- _numCostumes 200
- _numScripts 200
- _numSounds 80
-
- Indy3EGA (en PC; en Mac; en demo):
- _numGlobalObjects 1000
- _numRooms 99
- _numCostumes 129
- _numScripts 139
- _numSounds 84
-
- MM (en; de):
- _numGlobalObjects 780
- _numRooms 61
- _numCostumes 40
- _numScripts 179
- _numSounds 120
-
- Zak (de; en demo):
- _numGlobalObjects 780
- _numRooms 61
- _numCostumes 40
- _numScripts 155
- _numSounds 120
-
- So, they all have a different number of scripts.
- */
- } else if (buf[4] == '0' && buf[5] == 'R') {
- // newer V3 game
- if (g->version != 3)
- break;
- // Candidates: indy3, indy3Towns, zakTowns, loomTowns
- /*
- Considering that we know about *all* TOWNS versions,
- and know their MD5s, we could simply rely on this and
- if we find something which has an unknown MD5, assume
- that it is an (so far unknown) version of Indy3.
-
- We can combine this with a look at the resource headers:
-
- Indy3:
- _numGlobalObjects 1000
- _numRooms 99
- _numCostumes 129
- _numScripts 139
- _numSounds 84
-
- Indy3Towns, ZakTowns, ZakLoom demo:
- _numGlobalObjects 1000
- _numRooms 99
- _numCostumes 199
- _numScripts 199
- _numSounds 199
-
- Assuming that all the town variants look like the latter, we can
- do the check like this:
- if (numScripts == 139)
- assume Indy3
- else if (numScripts == 199)
- assume towns game
- else
- unknown, do not accept it
- */
- } else if (buf[4] == 'R' && buf[5] == 'N') {
- // V4 game
- if (g->version != 4)
- break;
- // Candidates: monkeyEGA, pass, monkeyVGA, loomcd
- /*
- For all of them, we have:
- _numGlobalObjects 1000
- _numRooms 99
- _numCostumes 199
- _numScripts 199
- _numSounds 199
- */
- } else if (buf[0] == 0xa0 && buf[1] == 0x07 && buf[2] == 0xa5 &&
- buf[3] == 0xbc) {
- // MM NES .prg
- if (g->id != GID_MANIAC)
- break;
- } else if (buf[0] == 0xbc && buf[1] == 0xb9) {
- // MM NES 00.LFL
- if (g->id != GID_MANIAC)
- break;
- } else if (buf[0] == 0x31 && buf[1] == 0x0a) {
- // C64 MM & Zak disk1
- if (g->version != 2)
- break;
- } else if (buf[0] == 0xcd && buf[1] == 0xfe) {
- // C64 MM & Zak 00.LFL
- if (g->version != 2)
- break;
- } else {
- // This is not a V1-V4 game
- break;
- }
- }
-
- // Match found, add to list of candidates, then abort inner loop.
- DetectedGame dg(g->gameid, findDescriptionFromGameID(g->gameid));
- if (substLastIndex > 0 && // HE Mac versions.
- (subst.genMethod == kGenMac ||
- subst.genMethod == kGenMacNoParens)) {
- dg.platform = Common::kPlatformMacintosh;
- fileSet[file->path()] = true;
- } else if (substLastIndex == 0 && g->id == GID_MANIAC &&
- (buf[0] == 0xbc || buf[0] == 0xa0)) {
- dg.platform = Common::kPlatformNES;
- } else if ((g->id == GID_MANIAC || g->id == GID_ZAK) &&
- ((buf[0] == 0x31 && buf[1] == 0x0a) ||
- (buf[0] == 0xcd && buf[1] == 0xfe))) {
- dg.platform = Common::kPlatformC64;
- } else {
- fileSet[file->path()] = false;
- }
-
- dg.updateDesc(); // Append the platform, if set, to the description.
-
- detectedGames.push_back(dg);
- break;
- }
- }
- }
-
- substLastIndex = findSubstResFileName(subst, tempName, substLastIndex);
- applySubstResFileName(subst, tempName, detectName, sizeof(detectName));
- } while (subst.almostGameID != 0);
- }
- }
-
- // Now, we check the MD5 sums of the 'candidate' files. If we have an exact match,
- // only return that.
- bool exactMatch = false;
- for (StringSet::const_iterator iter = fileSet.begin(); iter != fileSet.end(); ++iter) {
- uint8 md5sum[16];
- const char *name = iter->_key.c_str();
-
- if (Common::md5_file(name, md5sum, kMD5FileSizeLimit)) {
- char md5str[32+1];
- for (int j = 0; j < 16; j++) {
- sprintf(md5str + j*2, "%02x", (int)md5sum[j]);
- }
-
- const MD5Table *elem = findInMD5Table(md5str);
- if (elem) {
- if (!exactMatch)
- detectedGames.clear(); // Clear all the non-exact candidates
-
- DetectedGame dg(elem->gameid, findDescriptionFromGameID(elem->gameid), elem->language);
- if (iter->_value == true) // This was HE Mac game
- dg.platform = Common::kPlatformMacintosh;
- else
- dg.platform = elem->platform;
- dg.updateDesc(elem->extra); // Append extra information to the description.
-
- // Insert the 'enhanced' game data into the candidate list
- detectedGames.push_back(dg);
-
- exactMatch = true;
- }
- }
+
+ for (Common::List<DetectorResult>::iterator x = results.begin(); x != results.end(); ++x) {
+ DetectedGame dg(x->game.gameid, findDescriptionFromGameID(x->game.gameid),
+ x->language, x->game.platform);
+ dg.updateDesc(x->extra); // Append additional information, if set, to the description.
+ detectedGames.push_back(dg);
}
return detectedGames;
@@ -1838,236 +1311,131 @@ Engine *Engine_SCUMM_create(OSystem *syst) {
}
}
- // Lookup the game ID in our database. If this lookup fails, then
- // the game ID is unknown, and we have to abort.
- const GameSettings *g = gameVariantsTable;
- while (g->gameid) {
- if (!scumm_stricmp(gameid, g->gameid))
- break;
- g++;
- }
- if (!g->gameid) {
- return 0;
- }
-
- // We now want to calculate the MD5 of the games detection file, so that we
- // can store it in savegames etc..
- gameid = g->gameid;
- char detectName[256], tempName[256];
- uint8 md5sum[16];
- SubstResFileNames subst = { 0, 0, kGenAsIs };
- bool found = false;
-
- GameSettings game = *g;
-
- // To this end, we first have to figure out what the proper detection file
- // is (00.LFL, 000.LFL, ...). So we iterate over all possible names,
- // and once we find a matching file, we assume that's it.
- for (int method = 0; method < kDetectNameMethodsCount && !found; method++) {
- if (!generateDetectName(game, method, detectName))
- continue;
- strcpy(tempName, detectName);
- int substLastIndex = 0;
- do {
- // FIXME: Repeatedly calling File::exists like this is a bad idea.
- // Instead, use the fs.h code to get a list of all files in that
- // directory and simply check whether that filename is contained
- // in it.
- if (Common::File::exists(detectName)) {
- found = true;
- break;
- }
+ FilesystemNode dir;
+ if (ConfMan.hasKey("path") )
+ dir = FilesystemNode(ConfMan.get("path"));
+ FSList fslist = dir.listDir(FilesystemNode::kListFilesOnly);
+ Common::List<DetectorResult> results;
- substLastIndex = findSubstResFileName(subst, tempName, substLastIndex);
- applySubstResFileName(subst, tempName, detectName, sizeof(detectName));
- } while (subst.almostGameID != 0);
-
- if (found) {
- if (subst.almostGameID != 0)
- debug(5, "Generated filename substitute: %s -> %s", tempName, detectName);
- break;
- }
- }
+ // Invoke the detector, but fixed to the specified gameid.
+ detectGames(fslist, results, gameid);
// Unable to locate game data
- if (!found) {
+ if (results.empty())
return 0;
- }
- // Force game to have Mac platform if needed
- if (subst.almostGameID) {
- if (subst.genMethod == kGenMac ||
- subst.genMethod == kGenMacNoParens)
- game.platform = Common::kPlatformMacintosh;
- }
-
- // Determine a MD5 checksum which then is used to narrow down the choice
- // of game variants.
- const char *md5 = NULL;
- char md5buf[33];
+ DetectorResult res(*(results.begin()));
- // First, check if the MD5 was overridden with a config file entry.
- if (ConfMan.hasKey("target_md5")) {
- assert(ConfMan.get("target_md5").size() == 32);
- md5 = ConfMan.get("target_md5").c_str();
- } else {
- // Next, check if the MD5 was overridden via a target_md5.txt file.
- Common::File target_md5F;
- target_md5F.open("target_md5.txt");
-
- if (target_md5F.isOpen()) {
- bool valid = true;
-
- target_md5F.readLine(md5buf, 33);
- for (int j = 0; j < 32 && valid; ++j)
- if (!((md5buf[j] >= '0' && md5buf[j] <= '9') ||
- (md5buf[j] >= 'A' && md5buf[j] <= 'F') ||
- (md5buf[j] >= 'a' && md5buf[j] <= 'f')))
- valid = false;
-
- if (valid)
- md5 = md5buf;
- }
- }
-
- // Finally, if no MD5 value has been determined so far, compute it from the
- // detect file.
- if (!md5) {
- // Compute the MD5 of the file, and (if we succeeded) store a hex version
- // of it in gameMD5 (useful to print it to the user in messages).
- if (Common::md5_file(detectName, md5sum, kMD5FileSizeLimit)) {
- for (int j = 0; j < 16; j++) {
- sprintf(md5buf + j*2, "%02x", (int)md5sum[j]);
- }
+/*
+ // No unique match found. If a platform override is present, try to
+ // narrow down the list a bit more.
+ if (results.size() > 1 && ConfMan.hasKey("platform")) {
+ Common::Platform platform = Common::parsePlatform(ConfMan.get("platform"));
+ for (Common::List<DetectorResult>::iterator x = results.begin(); x != results.end(); ) {
+ if (x->game.platform != platform)
+ x = results.erase(x);
+ else
+ ++x;
}
- md5 = md5buf;
}
+*/
-
-
- // Now look up the MD5 in our lookup table (md5table).
- const MD5Table *elem = findInMD5Table(md5);
-
-
- // If a match was found, we use the information obtained from the md5table
- // to walk through the gameVariantsTable array and find a match there.
- // Otherwise, we print a warning about the MD5 being unknwon.
- if (elem) {
- // The MD5 is known and was found in our md5table.
- debug(5, "Using MD5 '%s'", md5);
-
- // Sanity check: Make sure the gameids match!
- if (scumm_stricmp(elem->gameid, gameid)) {
- error("MD5 %s implies gameid '%s', but gameid '%s' was used",
- md5, elem->gameid, gameid);
- }
-
- // Compute the precise game settings using gameVariantsTable.
- for (g = gameVariantsTable; g->gameid; ++g) {
- if (g->gameid[0] == 0 || !scumm_stricmp(elem->gameid, g->gameid)) {
- // The gameid either matches, or is empty (the latter indicates
- // a generic entry, used currently for generic HE specifies.
-
- if (g->variant == 0 || !scumm_stricmp(elem->variant, g->variant)) {
- // Perfect match found, use it and stop the loop
- game = *g;
- game.gameid = gameid;
- if (elem->platform != Common::kPlatformUnknown) {
- if (game.platform != Common::kPlatformUnknown && game.platform != elem->platform)
- warning("Platform values differ for MD5 '%s': %d vs %d (please report to Fingolfin)",
- md5, game.platform, elem->platform);
- game.platform = elem->platform;
- }
- break;
- }
- }
- }
- } else {
- printf("Unknown MD5 (%s)! Please report the details (language, platform, etc.) of this game to the ScummVM team\n", md5);
+ // Still no unique match found -> we just use the first one
+ if (results.size() > 1) {
+ warning("Engine_SCUMM_create: No unique game candidate found, using first one");
}
+
+
+ // TODO: Do we really still need / want the platform override ?
// Check for a user override of the platform. We allow the user to override
// the platform, to make it possible to add games which are not yet in
// our MD5 database but require a specific platform setting.
if (ConfMan.hasKey("platform"))
- game.platform = Common::parsePlatform(ConfMan.get("platform"));
+ res.game.platform = Common::parsePlatform(ConfMan.get("platform"));
+
+
+ // Language override
+ if (ConfMan.hasKey("language"))
+ res.language = Common::parseLanguage(ConfMan.get("language"));
// V3 FM-TOWNS games *always* should use the corresponding music driver,
// anything else makes no sense for them.
- if (game.platform == Common::kPlatformFMTowns && game.version == 3) {
- game.midi = MDT_TOWNS;
+ // TODO: Maybe allow the null driver, too?
+ if (res.game.platform == Common::kPlatformFMTowns && res.game.version == 3) {
+ res.game.midi = MDT_TOWNS;
}
// Finally, we have massaged the GameDescriptor to our satisfaction, and can
// instantiate the appropriate game engine. Hooray!
- switch (game.version) {
+ switch (res.game.version) {
+ case 0:
+ engine = new ScummEngine_c64(syst, res);
+ break;
case 1:
case 2:
- if (game.id == GID_MANIAC && game.platform == Common::kPlatformC64)
- engine = new ScummEngine_c64(syst, game, md5sum, subst);
- else
- engine = new ScummEngine_v2(syst, game, md5sum, subst);
+ engine = new ScummEngine_v2(syst, res);
break;
case 3:
- if (game.features & GF_OLD_BUNDLE)
- engine = new ScummEngine_v3old(syst, game, md5sum, subst);
+ if (res.game.features & GF_OLD_BUNDLE)
+ engine = new ScummEngine_v3old(syst, res);
else
- engine = new ScummEngine_v3(syst, game, md5sum, subst);
+ engine = new ScummEngine_v3(syst, res);
break;
case 4:
- engine = new ScummEngine_v4(syst, game, md5sum, subst);
+ engine = new ScummEngine_v4(syst, res);
break;
case 5:
- engine = new ScummEngine_v5(syst, game, md5sum, subst);
+ engine = new ScummEngine_v5(syst, res);
break;
case 6:
- switch (game.heversion) {
+ switch (res.game.heversion) {
#ifndef DISABLE_HE
case 100:
- engine = new ScummEngine_v100he(syst, game, md5sum, subst);
+ engine = new ScummEngine_v100he(syst, res);
break;
case 99:
- engine = new ScummEngine_v99he(syst, game, md5sum, subst);
+ engine = new ScummEngine_v99he(syst, res);
break;
case 98:
case 95:
case 90:
- engine = new ScummEngine_v90he(syst, game, md5sum, subst);
+ engine = new ScummEngine_v90he(syst, res);
break;
case 80:
- engine = new ScummEngine_v80he(syst, game, md5sum, subst);
+ engine = new ScummEngine_v80he(syst, res);
break;
case 73:
case 72:
- engine = new ScummEngine_v72he(syst, game, md5sum, subst);
+ engine = new ScummEngine_v72he(syst, res);
break;
case 71:
- engine = new ScummEngine_v71he(syst, game, md5sum, subst);
+ engine = new ScummEngine_v71he(syst, res);
break;
case 70:
- engine = new ScummEngine_v70he(syst, game, md5sum, subst);
+ engine = new ScummEngine_v70he(syst, res);
break;
#endif
#ifndef PALMOS_68K
case 61:
- engine = new ScummEngine_v60he(syst, game, md5sum, subst);
+ engine = new ScummEngine_v60he(syst, res);
break;
#endif
default:
- engine = new ScummEngine_v6(syst, game, md5sum, subst);
+ engine = new ScummEngine_v6(syst, res);
}
break;
#ifndef DISABLE_SCUMM_7_8
case 7:
- engine = new ScummEngine_v7(syst, game, md5sum, subst);
+ engine = new ScummEngine_v7(syst, res);
break;
case 8:
- engine = new ScummEngine_v8(syst, game, md5sum, subst);
+ engine = new ScummEngine_v8(syst, res);
break;
#endif
default:
diff --git a/engines/scumm/plugin.h b/engines/scumm/plugin.h
index a302cde6c6..e0d8f32afe 100644
--- a/engines/scumm/plugin.h
+++ b/engines/scumm/plugin.h
@@ -42,22 +42,37 @@ struct GameSettings {
};
-enum GenMethods {
- kGenMac,
- kGenMacNoParens,
- kGenPC,
- kGenAsIs
+enum FilenameGenMethod {
+ kGenDiskNum,
+ kGenRoomNum,
+ kGenHEMac,
+ kGenHEMacNoParens,
+ kGenHEPC,
+ kGenUnchanged
};
-struct SubstResFileNames {
- const char *almostGameID;
- const char *expandedName;
- GenMethods genMethod;
+struct FilenamePattern {
+ const char *pattern;
+ FilenameGenMethod genMethod;
};
+struct GameFilenamePattern {
+ const char *gameid;
+ const char *pattern;
+ FilenameGenMethod genMethod;
+ Common::Language language;
+ Common::Platform platform;
+ const char *variant;
+};
-bool applySubstResFileName(const SubstResFileNames &subst, const char *filename, char *buf, int bufsize);
-int findSubstResFileName(SubstResFileNames &subst, const char *filename, int index);
+struct DetectorResult {
+ FilenamePattern fp;
+ GameSettings game;
+ Common::Language language;
+ Common::String md5;
+ uint8 md5sum[16];
+ const char *extra;
+};
} // End of namespace Scumm
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index b5fb6fb8e7..6ee4820f07 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -65,8 +65,6 @@ static bool checkTryMedia(BaseScummFile *handle);
/* Open a room */
void ScummEngine::openRoom(const int room) {
bool result;
- char buf[128];
- char buf2[128] = "";
byte encByte = 0;
debugC(DEBUG_GENERAL, "openRoom(%d)", room);
@@ -90,57 +88,19 @@ void ScummEngine::openRoom(const int room) {
const int diskNumber = room ? res.roomno[rtRoom][room] : 0;
const int room_offs = room ? res.roomoffs[rtRoom][room] : 0;
+ // FIXME: Since room_offs is const, clearly the following loop either
+ // is never entered, or loops forever (if it wasn't for the return/error
+ // statements in it, that is). -> This should be cleaned up!
while (room_offs != -1) {
if (room_offs != 0 && room != 0 && _game.heversion < 98) {
_fileOffset = res.roomoffs[rtRoom][room];
return;
}
-
- /* Either xxx.lfl or monkey.xxx file name */
- if (_game.version <= 3) {
- sprintf(buf, "%.2d.lfl", room);
- // Maniac Mansion demo has .man instead of .lfl
- if (_game.id == GID_MANIAC)
- sprintf(buf2, "%.2d.man", room);
- } else if (_game.version == 4) {
- if (room == 0 || room >= 900) {
- sprintf(buf, "%.3d.lfl", room);
- } else {
- sprintf(buf, "disk%.2d.lec", diskNumber);
- }
- } else if (_game.heversion >= 98) {
- int disk = 0;
- if (_heV7DiskOffsets)
- disk = _heV7DiskOffsets[room];
-
- switch(disk) {
- case 2:
- sprintf(buf, "%s.(b)", _baseName.c_str());
- break;
- case 1:
- sprintf(buf, "%s.(a)", _baseName.c_str());
- break;
- default:
- sprintf(buf, "%s.he0", _baseName.c_str());
- }
- } else if (_game.heversion >= 70) {
- sprintf(buf, "%s.he%d", _baseName.c_str(), room == 0 ? 0 : 1);
- } else if (_game.heversion >= 60) {
- sprintf(buf, "%s.he%d", _baseName.c_str(), diskNumber);
-
- } else if (_game.version >= 7) {
- sprintf(buf, "%s.la%d", _baseName.c_str(), diskNumber);
-
- // Used by PC version of Full Throttle demo
- if (_game.id == GID_FT && (_game.features & GF_DEMO) && _game.platform == Common::kPlatformPC)
- sprintf(buf2, "%s.%.3d", _baseName.c_str(), diskNumber);
- } else {
- sprintf(buf, "%s.%.3d", _baseName.c_str(), diskNumber);
- if (_game.id == GID_SAMNMAX)
- sprintf(buf2, "%s.sm%d", _baseName.c_str(), diskNumber);
- }
+ Common::String filename(generateFilename(room));
+
+ // Determine the encryption, if any.
if (_game.features & GF_USE_KEY) {
if (_game.version <= 3)
encByte = 0xFF;
@@ -154,26 +114,8 @@ void ScummEngine::openRoom(const int room) {
if (room > 0 && (_game.version == 8))
VAR(VAR_CURRENTDISK) = diskNumber;
- // If we have substitute
- if (_substResFileName.almostGameID != 0 && !(_game.platform == Common::kPlatformNES || _game.platform == Common::kPlatformC64)) {
- char tmpBuf[128];
- generateSubstResFileName(buf, tmpBuf, sizeof(tmpBuf));
- strcpy(buf, tmpBuf);
- if (buf2[0]) {
- generateSubstResFileName(buf2, tmpBuf, sizeof(tmpBuf));
- strcpy(buf2, tmpBuf);
- }
- }
-
- // Try to open the file with name 'buf'. If that fails, try buf2 (if
- // specified).
- result = openResourceFile(buf, encByte);
- if (!result && buf2[0]) {
- result = openResourceFile(buf2, encByte);
- // We have .man files so set demo mode
- if (_game.id == GID_MANIAC)
- _game.features |= GF_DEMO;
- }
+ // Try to open the file
+ result = openResourceFile(filename.c_str(), encByte);
if (result) {
if (room == 0)
@@ -185,14 +127,15 @@ void ScummEngine::openRoom(const int room) {
if (_fileOffset != 8)
return;
- error("Room %d not in %s", room, buf);
+ error("Room %d not in %s", room, filename.c_str());
return;
}
- askForDisk(buf, diskNumber);
+ askForDisk(filename.c_str(), diskNumber);
}
do {
- sprintf(buf, "%.3d.lfl", room);
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%.3d.lfl", room);
encByte = 0;
if (openResourceFile(buf, encByte))
break;
@@ -246,39 +189,11 @@ bool ScummEngine::openFile(BaseScummFile &file, const char *filename, bool resou
bool result = false;
if (!_containerFile.empty()) {
- char name[128];
-
file.close();
file.open(_containerFile);
assert(file.isOpen());
- strncpy(name, filename, 128);
-
- // Some Mac demos (i.e. DOTT) have bundled file names different
- // from target name. dottdemo.000 vs tentacle.000. So we should
- // substitute those names too
- if (resourceFile == true) {
- if (_substResFileNameBundle.almostGameID == 0) {
- int substLastIndex = 0;
-
- do {
- if (file.openSubFile(name))
- break;
-
- substLastIndex = findSubstResFileName(_substResFileNameBundle, filename, substLastIndex);
- applySubstResFileName(_substResFileNameBundle, filename, name, sizeof(name));
- } while (_substResFileNameBundle.almostGameID != 0);
-
- if (_substResFileNameBundle.almostGameID != 0) {
- debug(5, "Generated substitute in Mac bundle: [%s -> %s]", filename, _substResFileNameBundle.almostGameID);
- }
- }
-
- if (_substResFileNameBundle.almostGameID != 0)
- applySubstResFileName(_substResFileNameBundle, filename, name, sizeof(name));
- }
-
- result = file.openSubFile(name);
+ result = file.openSubFile(filename);
}
if (!result) {
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index d605bb51c5..cef4f2fd72 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Sun Apr 23 13:24:24 2006
+ This file was generated by the md5table tool on Sun Apr 23 13:52:04 2006
DO NOT EDIT MANUALLY!
*/
@@ -36,7 +36,7 @@ static const MD5Table md5table[] = {
{ "0b3222aaa7efcf283eb621e0cefd26cc", "puttputt", "HE 60", "", Common::RU_RUS, Common::kPlatformPC },
{ "0c45eb4baff0c12c3d9dfa889c8070ab", "pajama3", "", "Demo", Common::DE_DEU, Common::kPlatformUnknown },
{ "0cccfa5223099a60e76cfcca57a1a141", "freddi3", "", "", Common::NL_NLD, Common::kPlatformWindows },
- { "0d1b69471605201ef2fa9cec1f5f02d2", "maniac", "", "V2", Common::ES_ESP, Common::kPlatformPC },
+ { "0d1b69471605201ef2fa9cec1f5f02d2", "maniac", "V2", "V2", Common::ES_ESP, Common::kPlatformPC },
{ "0e4c5d54a0ad4b26132e78b5ea76642a", "samnmax", "", "Demo", Common::EN_ANY, Common::kPlatformPC },
{ "0e9b01430e31d9fcd94071d433bbc6bf", "loom", "No Adlib", "EGA", Common::FR_FRA, Common::kPlatformAtariST },
{ "0f5935bd5e88ba6f09e558d64459746d", "thinker1", "", "Demo", Common::EN_ANY, Common::kPlatformWindows },
@@ -44,14 +44,14 @@ static const MD5Table md5table[] = {
{ "0f9c7a76657f0840b8f7ccb5bffeb9f4", "indy3", "No Adlib", "EGA", Common::FR_FRA, Common::kPlatformAtariST },
{ "0fb73eddfcf584c02ba097984df131ba", "samnmax", "", "CD", Common::DE_DEU, Common::kPlatformUnknown },
{ "1005456bfe351c1b679e1ff2dc2849e9", "puttzoo", "", "", Common::UNK_LANG, Common::kPlatformWindows },
- { "114acdc2659a273c220f86ee9edb24c1", "maniac", "", "V2", Common::FR_FRA, Common::kPlatformPC },
+ { "114acdc2659a273c220f86ee9edb24c1", "maniac", "V2", "V2", Common::FR_FRA, Common::kPlatformPC },
{ "11ddf1fde76e3156eb3a38da213f484e", "monkey2", "", "", Common::IT_ITA, Common::kPlatformAmiga },
{ "11e6e244078ff09b0f3832e35420e0a7", "catalog", "", "Demo", Common::EN_ANY, Common::kPlatformWindows },
{ "132bff65e6367c09cc69318ce1b59333", "monkey2", "", "", Common::EN_ANY, Common::kPlatformAmiga },
{ "145bd3373574feb668cc2eea2ec6cf86", "balloon", "HE 80", "", Common::RU_RUS, Common::kPlatformWindows },
{ "14d48c95b43ddeb983254cf6c43851f1", "freddi4", "", "", Common::NL_NLD, Common::kPlatformWindows },
{ "151071053a1d0021198216713939521d", "freddi2", "HE 80", "", Common::EN_ANY, Common::kPlatformWindows },
- { "15240c59d3681ed53f714f8d925cb2d6", "maniac", "", "V2", Common::ES_ESP, Common::kPlatformAtariST },
+ { "15240c59d3681ed53f714f8d925cb2d6", "maniac", "V2", "V2", Common::ES_ESP, Common::kPlatformAtariST },
{ "157367c3c21e0d03a0cba44361b4cf65", "indy3", "No Adlib", "EGA", Common::EN_ANY, Common::kPlatformAtariST },
{ "15e03ffbfeddb9c2aebc13dcb2a4a8f4", "monkey", "VGA", "VGA", Common::EN_ANY, Common::kPlatformPC },
{ "15f588e887e857e8c56fe6ade4956168", "atlantis", "", "Floppy", Common::ES_ESP, Common::kPlatformAmiga },
@@ -63,10 +63,10 @@ static const MD5Table md5table[] = {
{ "17f7296f63c78642724f057fd8e736a7", "maniac", "NES", "extracted", Common::EN_USA, Common::kPlatformNES },
{ "17fa250eb72dae2dad511ba79c0b6b0a", "tentacle", "", "Demo", Common::FR_FRA, Common::kPlatformPC },
{ "182344899c2e2998fca0bebcd82aa81a", "atlantis", "", "CD", Common::EN_ANY, Common::kPlatformPC },
- { "183d7464902d40d00800e8ee1f04117c", "maniac", "", "V2", Common::DE_DEU, Common::kPlatformPC },
+ { "183d7464902d40d00800e8ee1f04117c", "maniac", "V2", "V2", Common::DE_DEU, Common::kPlatformPC },
{ "1875b90fade138c9253a8e967007031a", "indy3", "VGA", "VGA", Common::EN_ANY, Common::kPlatformPC },
{ "187d315f6b5168f68680dfe8c3d76a3e", "loom", "EGA", "EGA", Common::HB_ISR, Common::kPlatformPC },
- { "1900e501a52fbf55bde6e4196f6d2aa6", "zak", "", "V2", Common::IT_ITA, Common::kPlatformPC },
+ { "1900e501a52fbf55bde6e4196f6d2aa6", "zak", "V2", "V2", Common::IT_ITA, Common::kPlatformPC },
{ "19263586f749a560c1adf8b3393a9593", "socks", "HE 80", "", Common::RU_RUS, Common::kPlatformWindows },
{ "19bf6938a94698296bcb0c99c31c91a7", "spyfox2", "", "Demo", Common::EN_GRB, Common::kPlatformWindows },
{ "1a6e5ae2777a6a33f06ffc0226210934", "atlantis", "", "CD", Common::EN_ANY, Common::kPlatformMacintosh },
@@ -90,7 +90,7 @@ static const MD5Table md5table[] = {
{ "22f4ea88a09da12df9308ba30bcb7d0f", "loom", "EGA", "EGA", Common::EN_ANY, Common::kPlatformPC },
{ "257f8c14d8c584f7ddd601bcb00920c7", "maniac", "NES", "", Common::DE_DEU, Common::kPlatformNES },
{ "2723fea3dae0cb47768c424b145ae0e7", "tentacle", "", "Floppy", Common::EN_ANY, Common::kPlatformPC },
- { "27b3a4224ad63d5b04627595c1c1a025", "zak", "", "V2", Common::IT_ITA, Common::kPlatformAmiga },
+ { "27b3a4224ad63d5b04627595c1c1a025", "zak", "V2", "V2", Common::IT_ITA, Common::kPlatformAmiga },
{ "28d24a33448fab6795850bc9f159a4a2", "atlantis", "", "Demo", Common::JA_JPN, Common::kPlatformFMTowns },
{ "28ef68ee3ed76d7e2ee8ee13c15fbd5b", "loom", "EGA", "EGA", Common::EN_ANY, Common::kPlatformPC },
{ "2a208ffbcd0e83e86f4356e6f64aa6e1", "loom", "EGA", "EGA", Common::ES_ESP, Common::kPlatformPC },
@@ -138,7 +138,7 @@ static const MD5Table md5table[] = {
{ "3de99ef0523f8ca7958faa3afccd035a", "spyfox", "HE 100", "", Common::EN_ANY, Common::kPlatformUnknown },
{ "3df6ead57930488bc61e6e41901d0e97", "fbear", "HE 61", "", Common::EN_ANY, Common::kPlatformMacintosh },
{ "3e48298920fab9b7aec5a971e1bd1fab", "pajama3", "", "Demo", Common::EN_GRB, Common::kPlatformWindows },
- { "40564ec47da48a67787d1f9bd043902a", "maniac", "", "Demo", Common::EN_ANY, Common::kPlatformPC },
+ { "40564ec47da48a67787d1f9bd043902a", "maniac", "Demo", "Demo", Common::EN_ANY, Common::kPlatformPC },
{ "4167a92a1d46baa4f4127d918d561f88", "tentacle", "", "CD", Common::EN_ANY, Common::kPlatformUnknown },
{ "425205754fa749f4f0b0dd9d09fa45fd", "football", "", "Demo", Common::EN_ANY, Common::kPlatformUnknown },
{ "430bc518017b6fac046f58bab6baad5d", "monkey2", "", "", Common::JA_JPN, Common::kPlatformFMTowns },
@@ -151,7 +151,7 @@ static const MD5Table md5table[] = {
{ "47e75b1bdcb44c78cb94883d1731ccf8", "fbear", "HE 61", "Demo", Common::EN_ANY, Common::kPlatformPC },
{ "48b9f04b348bc5013327753f0d12a144", "loom", "EGA", "EGA", Common::ES_ESP, Common::kPlatformAmiga },
{ "49210e124e4c2b30f1290a9ef6306301", "monkey", "EGA", "EGA", Common::EN_ANY, Common::kPlatformPC },
- { "4973bbc3899e3826dbf316e1d7271ec7", "zak", "", "", Common::DE_DEU, Common::kPlatformC64 },
+ { "4973bbc3899e3826dbf316e1d7271ec7", "zak", "V1", "", Common::DE_DEU, Common::kPlatformC64 },
{ "499c958affc394f2a3868f1eb568c3ee", "freddi4", "HE 99", "Demo", Common::NL_NLD, Common::kPlatformWindows },
{ "4af4a6b248103c1fe9edef619677f540", "puttmoon", "", "Demo", Common::EN_ANY, Common::kPlatformMacintosh },
{ "4ba37f835be11a59d969f90f272f575b", "water", "HE 80", "", Common::EN_ANY, Common::kPlatformUnknown },
@@ -174,11 +174,11 @@ static const MD5Table md5table[] = {
{ "50fcdc982a25063b78ad46bf389b8e8d", "tentacle", "", "Floppy", Common::IT_ITA, Common::kPlatformPC },
{ "51305e929e330e24a75a0351c8f9975e", "freddi2", "HE 99", "Updated", Common::EN_ANY, Common::kPlatformUnknown },
{ "5262a27afcaee04e5c4900220bd463e7", "PuttsFunShop", "", "", Common::EN_ANY, Common::kPlatformUnknown },
- { "52a4bae0746a11d7b1e8554e91a6645c", "zak", "", "V2", Common::FR_FRA, Common::kPlatformPC },
+ { "52a4bae0746a11d7b1e8554e91a6645c", "zak", "V2", "V2", Common::FR_FRA, Common::kPlatformPC },
{ "53e94115b55dd51d4b8ff0871aa1df1e", "spyfox", "", "Demo", Common::EN_ANY, Common::kPlatformUnknown },
{ "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", Common::EN_ANY, Common::kPlatformAmiga },
{ "55518cd73cf9c6d23ea29c51ee06bdfe", "ft", "", "", Common::IT_ITA, Common::kPlatformUnknown },
- { "55d3987641bf229c83bc729210173383", "zak", "", "", Common::EN_ANY, Common::kPlatformC64 },
+ { "55d3987641bf229c83bc729210173383", "zak", "V1", "", Common::EN_ANY, Common::kPlatformC64 },
{ "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "", Common::RU_RUS, Common::kPlatformUnknown },
{ "566165a7338fa11029e7c14d94fa70d0", "freddi", "HE 73", "Demo", Common::EN_ANY, Common::kPlatformWindows },
{ "5798972220cd458be2626d54c80f71d7", "atlantis", "", "Floppy", Common::IT_ITA, Common::kPlatformAmiga },
@@ -196,11 +196,11 @@ static const MD5Table md5table[] = {
{ "5e8fb66971a60e523e5afbc4c129c0e8", "socks", "HE 80", "", Common::EN_ANY, Common::kPlatformUnknown },
{ "5fbe557049892eb4b709d90916ec97ca", "indy3", "EGA", "EGA", Common::EN_ANY, Common::kPlatformPC },
{ "600abd3e9f47e63e670188b7e4e86ac7", "spyozon", "", "", Common::EN_ANY, Common::kPlatformUnknown },
- { "6027e9ca9c35746d95dee2068cec17e5", "zak", "", "V2", Common::DE_DEU, Common::kPlatformAmiga },
+ { "6027e9ca9c35746d95dee2068cec17e5", "zak", "V2", "V2", Common::DE_DEU, Common::kPlatformAmiga },
{ "60ba818dc3bede86d40357e3913f8505", "ft", "", "Version B", Common::EN_ANY, Common::kPlatformUnknown },
- { "613f64f78ea26c7353b2a5940eb61d6a", "zak", "", "V2", Common::FR_FRA, Common::kPlatformAtariST },
+ { "613f64f78ea26c7353b2a5940eb61d6a", "zak", "V2", "V2", Common::FR_FRA, Common::kPlatformAtariST },
{ "62050da376483d8edcbd98cd26b6cb57", "puttrace", "HE 99", "", Common::RU_RUS, Common::kPlatformWindows },
- { "624cdb93654667c869d204a64af7e57f", "maniac", "", "V2", Common::EN_ANY, Common::kPlatformPC },
+ { "624cdb93654667c869d204a64af7e57f", "maniac", "V2", "V2", Common::EN_ANY, Common::kPlatformPC },
{ "6271130f440066830eca9056c1d7926f", "water", "HE 80", "", Common::RU_RUS, Common::kPlatformWindows },
{ "62b8c16b6db226ba95aaa8be73f9885c", "indy3", "EGA", "EGA", Common::ES_ESP, Common::kPlatformAmiga },
{ "63fdcdc95cdeea00060883aed38e5504", "PuttTime", "HE 80", "", Common::EN_ANY, Common::kPlatformWindows },
@@ -210,7 +210,7 @@ static const MD5Table md5table[] = {
{ "663743c03ae0c007f3d665cf631c0e6b", "puttrace", "HE 99", "Demo", Common::DE_DEU, Common::kPlatformUnknown },
{ "66fd5ff9a810dfeb6d6bdada18221140", "monkey", "VGA", "VGA", Common::IT_ITA, Common::kPlatformPC },
{ "672dec94b82f7f0877ebb5b5cf7f4bc1", "pajama", "", "", Common::EN_ANY, Common::kPlatformUnknown },
- { "675d71151e9b5a968c8ce46d9fbf4cbf", "zak", "", "V2", Common::EN_ANY, Common::kPlatformPC },
+ { "675d71151e9b5a968c8ce46d9fbf4cbf", "zak", "V2", "V2", Common::EN_ANY, Common::kPlatformPC },
{ "68155a6bf082221525f431c2cbdac8ab", "SamsFunShop", "", "", Common::EN_ANY, Common::kPlatformUnknown },
{ "684732efb5799c0f78804c99d8de9aba", "puttputt", "HE 61", "", Common::EN_ANY, Common::kPlatformMacintosh },
{ "688328c5bdc4c8ec4145688dfa077bf2", "freddi4", "HE 99", "Demo", Common::DE_DEU, Common::kPlatformUnknown },
@@ -244,7 +244,7 @@ static const MD5Table md5table[] = {
{ "73e5ab7dbb9a8061cc6d25df02dbd1e7", "loom", "EGA", "EGA", Common::EN_ANY, Common::kPlatformPC },
{ "746e88c172a5b7a1ae89ac0ee3ee681a", "freddi", "HE 90", "Updated", Common::RU_RUS, Common::kPlatformWindows },
{ "754feb59d3bf86b8a00840df74fd7b26", "freddi3", "", "Demo", Common::NL_NLD, Common::kPlatformWindows },
- { "75ba23fff4fd63fa446c02864f2a5a4b", "zak", "", "V2", Common::IT_ITA, Common::kPlatformPC },
+ { "75ba23fff4fd63fa446c02864f2a5a4b", "zak", "V2", "V2", Common::IT_ITA, Common::kPlatformPC },
{ "75bff95816b84672b877d22a911ab811", "freddi3", "HE 99", "", Common::RU_RUS, Common::kPlatformWindows },
{ "771bc18ec6f93837b839c992b211904b", "monkey", "Demo", "EGA Demo", Common::DE_DEU, Common::kPlatformPC },
{ "77f5c9cc0986eb729c1a6b4c8823bbae", "zak", "FM-TOWNS", "", Common::EN_ANY, Common::kPlatformFMTowns },
@@ -264,15 +264,15 @@ static const MD5Table md5table[] = {
{ "7fc6cdb46b4c9d384c52327f4bca6416", "football", "", "", Common::EN_ANY, Common::kPlatformUnknown },
{ "810a9da887aefa597b0cf3c77d262897", "BluesABCTime", "", "Demo", Common::EN_ANY, Common::kPlatformUnknown },
{ "81bbfa181184cb494e7a81dcfa94fbd9", "maniac", "NES", "", Common::FR_FRA, Common::kPlatformNES },
- { "8299d9b8a1b0e7b881bae7a9971dc5e2", "zak", "", "Demo", Common::EN_ANY, Common::kPlatformAtariST },
+ { "8299d9b8a1b0e7b881bae7a9971dc5e2", "zak", "V2", "Demo", Common::EN_ANY, Common::kPlatformAtariST },
{ "8368f552b1e3eba559f8d559bcc4cadb", "freddi3", "", "", Common::UNK_LANG, Common::kPlatformUnknown },
{ "83cedbe26aa8b58988e984e3d34cac8e", "freddi3", "HE 99", "", Common::DE_DEU, Common::kPlatformUnknown },
{ "84e3c23a49ded8a6f9197735c8eb3de7", "PuttTime", "HE 80", "", Common::DE_DEU, Common::kPlatformWindows },
- { "861e59ed72a1cd0e6d454f7ee7e2bf3d", "comi", "", "", Common::RU_RUS, Common::kPlatformUnknown },
+ { "861e59ed72a1cd0e6d454f7ee7e2bf3d", "comi", "", "", Common::RU_RUS, Common::kPlatformWindows },
{ "86be8ada36371d4fdc35659d0e912a26", "indy3", "EGA", "EGA", Common::ES_ESP, Common::kPlatformPC },
{ "86c9902b7bec1a17926d4dae85beaa45", "airport", "HE 71", "Demo", Common::EN_ANY, Common::kPlatformWindows },
{ "870d1e3c86bc50846d808d14a36b4e08", "monkey", "VGA", "VGA", Common::ES_ESP, Common::kPlatformAmiga },
- { "87f6e8037b7cc996e13474b491a7a98e", "maniac", "", "V2", Common::IT_ITA, Common::kPlatformPC },
+ { "87f6e8037b7cc996e13474b491a7a98e", "maniac", "V2", "V2", Common::IT_ITA, Common::kPlatformPC },
{ "8801fb4a1200b347f7a38523339526dd", "jungle", "", "", Common::EN_ANY, Common::kPlatformWindows },
{ "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "", "CD", Common::ES_ESP, Common::kPlatformUnknown },
{ "898ce8eb1234a955ef75e87141902bb3", "freddi3", "", "", Common::RU_RUS, Common::kPlatformWindows },
@@ -288,12 +288,12 @@ static const MD5Table md5table[] = {
{ "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", Common::EN_ANY, Common::kPlatformFMTowns },
{ "8ee63cafb1fe9d62aa0d5a23117e70e7", "freddi2", "HE 100", "Updated", Common::EN_ANY, Common::kPlatformUnknown },
{ "8f3758ff98c9c5d78e5d635222cad026", "atlantis", "", "Floppy", Common::IT_ITA, Common::kPlatformPC },
- { "8fec68383202d38c0d25e9e3b757c5df", "comi", "Demo", "Demo", Common::UNK_LANG, Common::kPlatformUnknown },
+ { "8fec68383202d38c0d25e9e3b757c5df", "comi", "Demo", "Demo", Common::UNK_LANG, Common::kPlatformWindows },
{ "8ffd618a776a4c0d8922bb28b09f8ce8", "airport", "", "Demo", Common::EN_ANY, Common::kPlatformWindows },
{ "90a329d8ad5b7ce0690429e98cfbb32f", "funpack", "", "", Common::HB_ISR, Common::kPlatformPC },
{ "90c755e1c9b9b8a4129d37b2259d0655", "chase", "HE 100", "Updated", Common::EN_ANY, Common::kPlatformUnknown },
{ "910e31cffb28226bd68c569668a0d6b4", "monkey", "EGA", "EGA", Common::ES_ESP, Common::kPlatformPC },
- { "91469353f7be1b122fa88d23480a1320", "zak", "", "V2", Common::FR_FRA, Common::kPlatformAmiga },
+ { "91469353f7be1b122fa88d23480a1320", "zak", "V2", "V2", Common::FR_FRA, Common::kPlatformAmiga },
{ "91d5db93187fab54d823f73bd6441cb6", "maniac", "NES", "extracted", Common::EN_GRB, Common::kPlatformNES },
{ "927a764615c7fcdd72f591355e089d8c", "monkey", "No Adlib", "EGA", Common::DE_DEU, Common::kPlatformAtariST },
{ "92b078d9d6d9d751da9c26b8b3075779", "tentacle", "", "Floppy", Common::FR_FRA, Common::kPlatformPC },
@@ -305,10 +305,10 @@ static const MD5Table md5table[] = {
{ "9708cf716ed8bcc9ff3fcfc69413b746", "puttputt", "HE 61", "", Common::EN_ANY, Common::kPlatformPC },
{ "981e1e1891f2be7e25a01f50ae55a5af", "puttrace", "HE 98", "", Common::EN_ANY, Common::kPlatformUnknown },
{ "98744fe66ff730e8c2b3b1f58803ab0b", "atlantis", "", "Demo", Common::EN_ANY, Common::kPlatformPC },
- { "99a3699f80b8f776efae592b44b9b991", "maniac", "", "V2", Common::FR_FRA, Common::kPlatformPC },
+ { "99a3699f80b8f776efae592b44b9b991", "maniac", "V2", "V2", Common::FR_FRA, Common::kPlatformPC },
{ "99b6f822b0b2612415407865438697d6", "atlantis", "", "Demo", Common::EN_ANY, Common::kPlatformPC },
{ "9b7452b5cd6d3ffb2b2f5118010af84f", "ft", "Demo", "Demo", Common::EN_ANY, Common::kPlatformMacintosh },
- { "9bc548e179cdb0767009401c094d0895", "maniac", "", "V2", Common::DE_DEU, Common::kPlatformAmiga },
+ { "9bc548e179cdb0767009401c094d0895", "maniac", "V2", "V2", Common::DE_DEU, Common::kPlatformAmiga },
{ "9bd2a8f72613e715c199246dd511e10f", "atlantis", "", "Floppy", Common::ES_ESP, Common::kPlatformPC },
{ "9bda5fee51d2fda5253d02c642016bf4", "spyfox", "HE 98.5", "", Common::NL_NLD, Common::kPlatformWindows },
{ "9c0fee288ad564a7d25ec3e841810d79", "indy3", "EGA", "EGA", Common::EN_ANY, Common::kPlatformAmiga },
@@ -328,7 +328,7 @@ static const MD5Table md5table[] = {
{ "a3036878840720fbefa41e6965fa4a0a", "samnmax", "", "Floppy", Common::EN_ANY, Common::kPlatformPC },
{ "a525c1753c1db5011c00417da37887ef", "PuttTime", "HE 100", "", Common::EN_USA, Common::kPlatformUnknown },
{ "a561d2e2413cc1c71d5a1bf87bf493ea", "lost", "HE 100", "Updated", Common::EN_ANY, Common::kPlatformUnknown },
- { "a570381b028972d891052ee1e51dc011", "maniac", "", "V2", Common::EN_ANY, Common::kPlatformAtariST },
+ { "a570381b028972d891052ee1e51dc011", "maniac", "V2", "V2", Common::EN_ANY, Common::kPlatformAtariST },
{ "a654fb60c3b67d6317a7894ffd9f25c5", "pajama3", "", "Demo", Common::EN_USA, Common::kPlatformUnknown },
{ "a7cacad9c40c4dc9e1812abf6c8af9d5", "puttcircus", "", "Demo", Common::EN_ANY, Common::kPlatformUnknown },
{ "a85856675429fe88051744f755b72f93", "farm", "", "", Common::EN_ANY, Common::kPlatformWindows },
@@ -345,7 +345,7 @@ static const MD5Table md5table[] = {
{ "acad97ab1c6fc2a5b2d98abf6db4a190", "tentacle", "", "Floppy", Common::EN_ANY, Common::kPlatformUnknown },
{ "ae94f110a14ce71fc515d5b648827a8f", "tentacle", "", "Floppy", Common::ES_ESP, Common::kPlatformPC },
{ "b23f7cd7c304d7dff08e92a96120d5b4", "zak", "V1", "V1", Common::EN_ANY, Common::kPlatformPC },
- { "b250d0f9cc83f80ced56fe11a4fb057c", "maniac", "", "V2", Common::EN_ANY, Common::kPlatformPC },
+ { "b250d0f9cc83f80ced56fe11a4fb057c", "maniac", "V2", "V2", Common::EN_ANY, Common::kPlatformPC },
{ "b289a2a8cbedbf45786e0b4ad2f510f1", "samnmax", "", "Floppy", Common::IT_ITA, Common::kPlatformPC },
{ "b5298a5c15ffbe8b381d51ea4e26d35c", "freddi4", "HE 99", "", Common::DE_DEU, Common::kPlatformUnknown },
{ "b597e0403cc0002f69170e6caba7edd9", "indy3", "EGA", "EGA Demo", Common::EN_ANY, Common::kPlatformPC },
@@ -358,7 +358,7 @@ static const MD5Table md5table[] = {
{ "bc4700bc0e12879f6d25d14d6be6cfdd", "spyfox2", "", "", Common::DE_DEU, Common::kPlatformUnknown },
{ "bd126753de619a495f9f22adc951c8d5", "monkey2", "", "", Common::IT_ITA, Common::kPlatformPC },
{ "be39a5d4db60e8aa736b9086778cb45c", "spyozon", "", "", Common::EN_ANY, Common::kPlatformWindows },
- { "be83e882b44f2767bc08d4f766ebc347", "maniac", "", "V2", Common::DE_DEU, Common::kPlatformAtariST },
+ { "be83e882b44f2767bc08d4f766ebc347", "maniac", "V2", "V2", Common::DE_DEU, Common::kPlatformAtariST },
{ "bf8b52fdd9a69c67f34e8e9fec72661c", "farm", "HE 71", "Demo", Common::EN_ANY, Common::kPlatformWindows },
{ "bfdf584b01503f0762baded581f6a0a2", "SoccerMLS", "", "", Common::EN_ANY, Common::kPlatformWindows },
{ "c0039ad982999c92d0de81910d640fa0", "freddi", "HE 71", "", Common::NL_NLD, Common::kPlatformWindows },
@@ -369,8 +369,8 @@ static const MD5Table md5table[] = {
{ "c3196c5349e53e387aaff1533d95e53a", "samnmax", "", "Demo", Common::EN_ANY, Common::kPlatformPC },
{ "c3b22fa4654bb580b20325ebf4174841", "puttzoo", "", "", Common::NL_NLD, Common::kPlatformWindows },
{ "c3df37df9d3b481b45f75283a9907c47", "loom", "EGA", "EGA", Common::IT_ITA, Common::kPlatformPC },
- { "c4787c3e8b5e2dfda90850ee800af00f", "zak", "", "V2", Common::FR_FRA, Common::kPlatformPC },
- { "c4a7f7398ac9ae588940f9912ea5fd8f", "maniac", "", "", Common::DE_DEU, Common::kPlatformC64 },
+ { "c4787c3e8b5e2dfda90850ee800af00f", "zak", "V2", "V2", Common::FR_FRA, Common::kPlatformPC },
+ { "c4a7f7398ac9ae588940f9912ea5fd8f", "maniac", "C64", "", Common::DE_DEU, Common::kPlatformC64 },
{ "c4ffae9fac495475d6bc3343ccc8faf9", "Soccer2004", "", "", Common::EN_ANY, Common::kPlatformUnknown },
{ "c5d10e190d4b4d59114b824f2fdbd00e", "loom", "FM-TOWNS", "", Common::EN_ANY, Common::kPlatformFMTowns },
{ "c63ee46143ba65f9ce14cf539ca51bd7", "atlantis", "", "Floppy", Common::EN_ANY, Common::kPlatformPC },
@@ -384,16 +384,16 @@ static const MD5Table md5table[] = {
{ "cc04a076779379524ed4d9c5ee3c6fb1", "tentacle", "", "CD", Common::EN_ANY, Common::kPlatformMacintosh },
{ "cc8ba2b0df2f9c450bcf055fe2711979", "samnmax", "", "Demo", Common::DE_DEU, Common::kPlatformPC },
{ "cd9c05e755d7bf8e9b9590ad1ebe273e", "dig", "Demo", "Demo", Common::EN_ANY, Common::kPlatformMacintosh },
- { "cdd760228cf1010c2903f37e788ea31c", "zak", "", "V2", Common::DE_DEU, Common::kPlatformPC },
+ { "cdd760228cf1010c2903f37e788ea31c", "zak", "V2", "V2", Common::DE_DEU, Common::kPlatformPC },
{ "ce6a4cef315b20fef58a95bc40a2d8d3", "monkey", "EGA", "EGA", Common::FR_FRA, Common::kPlatformPC },
- { "ce7733f185b838e248927c7ba1a04204", "maniac", "", "V2", Common::FR_FRA, Common::kPlatformAmiga },
+ { "ce7733f185b838e248927c7ba1a04204", "maniac", "V2", "V2", Common::FR_FRA, Common::kPlatformAmiga },
{ "ce7fd0c382389a6791fc3e199c117ef4", "indy3", "EGA", "EGA", Common::ES_ESP, Common::kPlatformPC },
{ "cea91e3dd47f2518ea418e41611aa77f", "spyfox2", "", "", Common::RU_RUS, Common::kPlatformUnknown },
{ "cf4ef315214c7d8cdab6302cdb7e50db", "freddi", "HE 73", "Demo", Common::DE_DEU, Common::kPlatformWindows },
{ "cf8d13446ec6cb6222287a925fd47c1d", "baseball", "", "", Common::EN_ANY, Common::kPlatformUnknown },
{ "cf8ef3a1fb483c5c4b1c584d1167b2c4", "freddi", "HE 73", "", Common::DE_DEU, Common::kPlatformWindows },
{ "cf90b4db5486ef798db78fe6fbf897e5", "pajama3", "", "Demo", Common::EN_USA, Common::kPlatformWindows },
- { "d06fbe28818fef7bfc45c2cdf0c0849d", "zak", "", "V2", Common::DE_DEU, Common::kPlatformPC },
+ { "d06fbe28818fef7bfc45c2cdf0c0849d", "zak", "V2", "V2", Common::DE_DEU, Common::kPlatformPC },
{ "d0b531227a27c6662018d2bd05aac52a", "monkey", "VGA", "VGA", Common::DE_DEU, Common::kPlatformPC },
{ "d220d154aafbfa12bd6f3ab1b2dae420", "puttzoo", "", "Demo", Common::DE_DEU, Common::kPlatformMacintosh },
{ "d37c55388294b66e53e7ced3af88fa68", "freddi2", "HE 100", "Updated Demo", Common::EN_ANY, Common::kPlatformUnknown },
@@ -402,14 +402,14 @@ static const MD5Table md5table[] = {
{ "d4b8ee426b1afd3e53bc0cf020418cf6", "dog", "HE 99", "", Common::EN_ANY, Common::kPlatformWindows },
{ "d4cccb5af88f3e77f370896e9ba8c5f9", "freddi", "HE 71", "", Common::UNK_LANG, Common::kPlatformWindows },
{ "d4e79c3d8645b8266cd78c325bc35154", "pajama2", "", "", Common::EN_ANY, Common::kPlatformUnknown },
- { "d55eff37c2100f5065cde9de428621fa", "zak", "", "V2", Common::EN_ANY, Common::kPlatformAtariST },
+ { "d55eff37c2100f5065cde9de428621fa", "zak", "V2", "V2", Common::EN_ANY, Common::kPlatformAtariST },
{ "d62047a6729349ab36f7ee065bf26509", "dig", "", "", Common::RU_RUS, Common::kPlatformUnknown },
{ "d62d248c3df6ec177405e2cb23d923b2", "indy3", "EGA", "EGA", Common::IT_ITA, Common::kPlatformPC },
{ "d6334a5a9b61afe18c368540fdf522ca", "airport", "", "", Common::EN_ANY, Common::kPlatformMacintosh },
{ "d6dd0646404768a63e963891a96daadd", "atlantis", "", "Floppy", Common::EN_ANY, Common::kPlatformMacintosh },
{ "d7ab7cd6105546016e6a0d46fb36b964", "pajama", "HE 100", "Demo", Common::EN_ANY, Common::kPlatformUnknown },
{ "d7b247c26bf1f01f8f7daf142be84de3", "balloon", "HE 99", "Updated", Common::EN_ANY, Common::kPlatformWindows },
- { "d831f7c048574dd9d5d85db2a1468099", "maniac", "", "", Common::EN_ANY, Common::kPlatformC64 },
+ { "d831f7c048574dd9d5d85db2a1468099", "maniac", "C64", "", Common::EN_ANY, Common::kPlatformC64 },
{ "d8323015ecb8b10bf53474f6e6b0ae33", "dig", "", "", Common::UNK_LANG, Common::kPlatformUnknown },
{ "d8d07efcb88f396bee0b402b10c3b1c9", "maniac", "NES", "", Common::EN_USA, Common::kPlatformNES },
{ "d917f311a448e3cc7239c31bddb00dd2", "samnmax", "", "CD", Common::EN_ANY, Common::kPlatformUnknown },
@@ -417,9 +417,9 @@ static const MD5Table md5table[] = {
{ "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "", "", Common::EN_ANY, Common::kPlatformFMTowns },
{ "da6269b18fcb08189c0aa9c95533cce2", "monkey", "CD", "CD", Common::IT_ITA, Common::kPlatformPC },
{ "da669b20271b85182e9c17a2a37ea02e", "monkey2", "", "", Common::DE_DEU, Common::kPlatformAmiga },
- { "dd30a53035393baa5a5e222e716559af", "maniac", "", "V2", Common::FR_FRA, Common::kPlatformAtariST },
+ { "dd30a53035393baa5a5e222e716559af", "maniac", "V2", "V2", Common::FR_FRA, Common::kPlatformAtariST },
{ "de4efb910210736813c9a1185384bace", "puttzoo", "", "Demo", Common::EN_ANY, Common::kPlatformWindows },
- { "debe337f73d660e951ece7c1f1c81add", "zak", "", "V2", Common::EN_ANY, Common::kPlatformPC },
+ { "debe337f73d660e951ece7c1f1c81add", "zak", "V2", "V2", Common::EN_ANY, Common::kPlatformPC },
{ "defb8cb9ec4b0f91acfb6b61c6129ad9", "PuttTime", "HE 99", "", Common::RU_RUS, Common::kPlatformWindows },
{ "df03ee021aa9b81d90cab9c26da07614", "indy3", "EGA", "EGA", Common::IT_ITA, Common::kPlatformAmiga },
{ "df047cc4792150f601290357566d36a6", "freddi", "HE 90", "Updated", Common::EN_ANY, Common::kPlatformUnknown },
@@ -435,8 +435,8 @@ static const MD5Table md5table[] = {
{ "e689bdf67f98b1d760ce4487ec0e8d06", "indy3", "EGA", "EGA", Common::FR_FRA, Common::kPlatformAmiga },
{ "e6cd81b25ab1453a8a6d3482118c391e", "pass", "", "", Common::EN_ANY, Common::kPlatformPC },
{ "e72bb4c2b613db2cf50f89ff6350e70a", "ft", "", "", Common::ES_ESP, Common::kPlatformUnknown },
- { "e781230da44a44e2f0770edb2b3b3633", "maniac", "", "V2", Common::EN_ANY, Common::kPlatformAmiga },
- { "e94c7cc3686fce406d3c91b5eae5a72d", "zak", "", "V2", Common::EN_ANY, Common::kPlatformAmiga },
+ { "e781230da44a44e2f0770edb2b3b3633", "maniac", "V2", "V2", Common::EN_ANY, Common::kPlatformAmiga },
+ { "e94c7cc3686fce406d3c91b5eae5a72d", "zak", "V2", "V2", Common::EN_ANY, Common::kPlatformAmiga },
{ "e98b982ceaf9d253d730bde8903233d6", "monkey", "EGA", "EGA", Common::DE_DEU, Common::kPlatformPC },
{ "eae95b2b3546d8ba86ae1d397c383253", "dog", "", "", Common::EN_ANY, Common::kPlatformUnknown },
{ "ebd0b2c8a387f18887282afe6cad894a", "spyozon", "", "Demo", Common::EN_ANY, Common::kPlatformUnknown },
@@ -469,7 +469,7 @@ static const MD5Table md5table[] = {
{ "fcb78ebecab2757264c590890c319cc5", "PuttTime", "HE 100", "", Common::NL_NLD, Common::kPlatformWindows },
{ "fce4b8010704b103acfeea9413788f32", "freddi2", "HE 80", "", Common::DE_DEU, Common::kPlatformUnknown },
{ "fe381e45117878b1e942cb876b050fd6", "ft", "", "", Common::EN_ANY, Common::kPlatformMacintosh },
- { "fe60d6b5ff51b0553ac59963123b5777", "comi", "", "", Common::UNK_LANG, Common::kPlatformUnknown },
- { "ff05c07990061d97647f059c48c1d05a", "zak", "", "V2", Common::DE_DEU, Common::kPlatformAtariST },
+ { "fe60d6b5ff51b0553ac59963123b5777", "comi", "", "", Common::UNK_LANG, Common::kPlatformWindows },
+ { "ff05c07990061d97647f059c48c1d05a", "zak", "V2", "V2", Common::DE_DEU, Common::kPlatformAtariST },
{ 0, 0, 0, 0, Common::UNK_LANG, Common::kPlatformUnknown }
};
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 957298b3a6..7715497ef6 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -78,10 +78,11 @@ namespace Scumm {
ScummEngine *g_scumm = 0;
-ScummEngine::ScummEngine(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
+ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
: Engine(syst),
- _game(gs),
- _substResFileName(subst),
+ _game(dr.game),
+ _filenamePattern(dr.fp),
+ _language(dr.language),
_debugger(0),
_currentScript(0xFF), // Let debug() work on init stage
gdi(this),
@@ -89,11 +90,8 @@ ScummEngine::ScummEngine(OSystem *syst, const GameSettings &gs, uint8 md5sum[16]
_pauseDialog(0), _mainMenuDialog(0), _versionDialog(0) {
// Copy MD5 checksum
- memcpy(_gameMD5, md5sum, 16);
+ memcpy(_gameMD5, dr.md5sum, 16);
- // Clean _substResFileNameBundle
- memset(&_substResFileNameBundle, 0, sizeof(_substResFileNameBundle));
-
// Add default file directories.
if (((_game.platform == Common::kPlatformAmiga) || (_game.platform == Common::kPlatformAtariST)) && (_game.version <= 4)) {
// This is for the Amiga version of Indy3/Loom/Maniac/Zak
@@ -146,14 +144,17 @@ ScummEngine::ScummEngine(OSystem *syst, const GameSettings &gs, uint8 md5sum[16]
// This is the case of the NES, C64 and Mac versions of certain games.
// Note: All of these can also occur in 'extracted' form, in which case they
// are treated like any other SCUMM game.
- if (_substResFileName.almostGameID && _substResFileName.genMethod == kGenAsIs) {
+ if (_filenamePattern.genMethod == kGenUnchanged) {
if (_game.platform == Common::kPlatformNES) {
// We read data directly from NES ROM instead of extracting it with
// external tool
assert(_game.id == GID_MANIAC);
_fileHandle = new ScummNESFile();
- _containerFile = _substResFileName.expandedName;
+ _containerFile = _filenamePattern.pattern;
+
+ _filenamePattern.pattern = "%.2d.LFL";
+ _filenamePattern.genMethod = kGenRoomNum;
} else if (_game.platform == Common::kPlatformC64) {
// Read data from C64 disk images.
const char *tmpBuf1, *tmpBuf2;
@@ -168,6 +169,9 @@ ScummEngine::ScummEngine(OSystem *syst, const GameSettings &gs, uint8 md5sum[16]
_fileHandle = new ScummC64File(tmpBuf1, tmpBuf2, _game.id == GID_MANIAC);
_containerFile = tmpBuf1;
+
+ _filenamePattern.pattern = "%.2d.LFL";
+ _filenamePattern.genMethod = kGenRoomNum;
} else if (_game.platform == Common::kPlatformMacintosh) {
// The mac versions of Indy4, Sam&Max, DOTT, FT and The Dig used a
// special meta (container) file format to store the actual SCUMM data
@@ -179,13 +183,53 @@ ScummEngine::ScummEngine(OSystem *syst, const GameSettings &gs, uint8 md5sum[16]
// handling).
assert(_game.version >= 5 && _game.heversion == 0);
_fileHandle = new ScummFile();
- _containerFile = _substResFileName.expandedName;
+ _containerFile = _filenamePattern.pattern;
+
+
+ // We now have to determine the correct _filenamePattern. To do this
+ // we simply hardcode the possibilites.
+ const char *p1 = 0, *p2 = 0;
+ switch (_game.id) {
+ case GID_INDY4:
+ p1 = "atlantis.%03d";
+ break;
+ case GID_TENTACLE:
+ p1 = "tentacle.%03d";
+ p2 = "dottdemo.%03d";
+ break;
+ case GID_SAMNMAX:
+ p1 = "samnmax.%03d";
+ p2 = "samdemo.%03d";
+ break;
+ case GID_FT:
+ p1 = "ft.la%d";
+ p2 = "ftdemo.la%d";
+ break;
+ case GID_DIG:
+ p1 = "dig.la%d";
+ break;
+ default:
+ break;
+ }
+
+ // Test which file name to use
+ _filenamePattern.genMethod = kGenDiskNum;
+ if (!_fileHandle->open(_containerFile))
+ error("Couldn't open container file '%s'", _containerFile.c_str());
+
+ if ((_filenamePattern.pattern = p1) && _fileHandle->openSubFile(generateFilename(0))) {
+ // Found regular version
+ } else if ((_filenamePattern.pattern = p2) && _fileHandle->openSubFile(generateFilename(0))) {
+ // Found demo
+ _game.features |= GF_DEMO;
+ } else
+ error("Couldn't find known subfile inside container file '%s'", _containerFile.c_str());
+
+ _fileHandle->close();
+
} else {
error("kGenAsIs used with unsupported platform");
}
-
- // If a container file is used, we can turn of file name substitution.
- _substResFileName.almostGameID = 0;
} else {
// Regular access, no container file involved
_fileHandle = new ScummFile();
@@ -537,11 +581,6 @@ ScummEngine::ScummEngine(OSystem *syst, const GameSettings &gs, uint8 md5sum[16]
if (_bootParam)
_debugMode = true;
- // Allow the user to override the game name with a custom string.
- // This allows some game versions to work which use filenames
- // differing from the regular version(s) of that game.
- _baseName = ConfMan.hasKey("basename") ? ConfMan.get("basename") : gs.gameid;
-
_copyProtection = ConfMan.getBool("copy_protection");
if (ConfMan.getBool("demo_mode"))
_game.features |= GF_DEMO;
@@ -673,22 +712,22 @@ ScummEngine::~ScummEngine() {
delete _debugger;
}
-ScummEngine_v4::ScummEngine_v4(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v5(syst, gs, md5sum, subst) {
+ScummEngine_v4::ScummEngine_v4(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v5(syst, dr) {
_resourceHeaderSize = 6;
}
-ScummEngine_v3::ScummEngine_v3(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v4(syst, gs, md5sum, subst) {
+ScummEngine_v3::ScummEngine_v3(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v4(syst, dr) {
}
-ScummEngine_v3old::ScummEngine_v3old(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v3(syst, gs, md5sum, subst) {
+ScummEngine_v3old::ScummEngine_v3old(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v3(syst, dr) {
_resourceHeaderSize = 4;
}
-ScummEngine_v2::ScummEngine_v2(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v3old(syst, gs, md5sum, subst) {
+ScummEngine_v2::ScummEngine_v2(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v3old(syst, dr) {
VAR_SENTENCE_VERB = 0xFF;
VAR_SENTENCE_OBJECT1 = 0xFF;
@@ -701,14 +740,14 @@ ScummEngine_v2::ScummEngine_v2(OSystem *syst, const GameSettings &gs, uint8 md5s
VAR_CLICK_OBJECT = 0xFF;
}
-ScummEngine_c64::ScummEngine_c64(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v2(syst, gs, md5sum, subst) {
+ScummEngine_c64::ScummEngine_c64(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v2(syst, dr) {
_currentMode = 0;
}
-ScummEngine_v6::ScummEngine_v6(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine(syst, gs, md5sum, subst) {
+ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine(syst, dr) {
_blastObjectQueuePos = 0;
memset(_blastObjectQueue, 0, sizeof(_blastObjectQueue));
_blastTextQueuePos = 0;
@@ -729,8 +768,8 @@ ScummEngine_v6::ScummEngine_v6(OSystem *syst, const GameSettings &gs, uint8 md5s
}
#ifndef DISABLE_HE
-ScummEngine_v70he::ScummEngine_v70he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v60he(syst, gs, md5sum, subst) {
+ScummEngine_v70he::ScummEngine_v70he(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v60he(syst, dr) {
if (_game.platform == Common::kPlatformMacintosh && (_game.heversion >= 72 && _game.heversion <= 73))
_resExtractor = new MacResExtractor(this);
else
@@ -761,16 +800,16 @@ ScummEngine_v70he::~ScummEngine_v70he() {
free(_storedFlObjects);
}
-ScummEngine_v71he::ScummEngine_v71he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v70he(syst, gs, md5sum, subst) {
+ScummEngine_v71he::ScummEngine_v71he(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v70he(syst, dr) {
_auxBlocksNum = 0;
memset(_auxBlocks, 0, sizeof(_auxBlocks));
_auxEntriesNum = 0;
memset(_auxEntries, 0, sizeof(_auxEntries));
}
-ScummEngine_v72he::ScummEngine_v72he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v71he(syst, gs, md5sum, subst) {
+ScummEngine_v72he::ScummEngine_v72he(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v71he(syst, dr) {
VAR_NUM_ROOMS = 0xFF;
VAR_NUM_SCRIPTS = 0xFF;
VAR_NUM_SOUNDS = 0xFF;
@@ -780,8 +819,8 @@ ScummEngine_v72he::ScummEngine_v72he(OSystem *syst, const GameSettings &gs, uint
VAR_POLYGONS_ONLY = 0xFF;
}
-ScummEngine_v80he::ScummEngine_v80he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v72he(syst, gs, md5sum, subst) {
+ScummEngine_v80he::ScummEngine_v80he(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v72he(syst, dr) {
_heSndResId = 0;
_curSndId = 0;
_sndPtrOffs = 0;
@@ -793,8 +832,8 @@ ScummEngine_v80he::ScummEngine_v80he(OSystem *syst, const GameSettings &gs, uint
VAR_COLOR_DEPTH = 0xFF;
}
-ScummEngine_v90he::ScummEngine_v90he(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v80he(syst, gs, md5sum, subst) {
+ScummEngine_v90he::ScummEngine_v90he(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v80he(syst, dr) {
_sprite = new Sprite(this);
VAR_NUM_SPRITE_GROUPS = 0xFF;
@@ -818,8 +857,8 @@ ScummEngine_v90he::~ScummEngine_v90he() {
#endif
#ifndef DISABLE_SCUMM_7_8
-ScummEngine_v7::ScummEngine_v7(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v6(syst, gs, md5sum, subst) {
+ScummEngine_v7::ScummEngine_v7(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v6(syst, dr) {
_verbCharset = 0;
_existLanguageFile = false;
_languageBuffer = NULL;
@@ -832,8 +871,8 @@ ScummEngine_v7::~ScummEngine_v7() {
free(_languageIndex);
}
-ScummEngine_v8::ScummEngine_v8(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst)
- : ScummEngine_v7(syst, gs, md5sum, subst) {
+ScummEngine_v8::ScummEngine_v8(OSystem *syst, const DetectorResult &dr)
+ : ScummEngine_v7(syst, dr) {
_objectIDMap = 0;
}
@@ -881,7 +920,6 @@ int ScummEngine::init() {
setupMusic(_game.midi);
// Load localization data, if present
- _language = Common::parseLanguage(ConfMan.get("language"));
loadLanguageBundle();
// Load CJK font, if present
@@ -1305,19 +1343,10 @@ void ScummEngine_v99he::scummInit() {
_hePalettes = (uint8 *)malloc((_numPalettes + 1) * 1024);
memset(_hePalettes, 0, (_numPalettes + 1) * 1024);
- byte basename[256];
- char buf1[128];
-
- strcpy((char *)basename, _baseName.c_str());
- if (_substResFileName.almostGameID != 0) {
- generateSubstResFileName((char *)basename, buf1, sizeof(buf1));
- strcpy((char *)basename, buf1);
- }
-
// Array 129 is set to base name
- int len = resStrLen(basename);
+ int len = strlen(_filenamePattern.pattern);
ArrayHeader *ah = defineArray(129, kStringArray, 0, 0, 0, len);
- memcpy(ah->data, basename, len);
+ memcpy(ah->data, _filenamePattern.pattern, len);
}
#endif
@@ -2015,9 +2044,5 @@ void ScummEngine::errorString(const char *buf1, char *buf2) {
}
}
-void ScummEngine::generateSubstResFileName(const char *filename, char *buf, int bufsize) {
- applySubstResFileName(_substResFileName, filename, buf, bufsize);
-}
-
} // End of namespace Scumm
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index ad6c84c667..e9813d1333 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -444,7 +444,7 @@ protected:
public:
// Constructor / Destructor
- ScummEngine(OSystem *syst, const GameSettings &gs, uint8 md5sum[16], SubstResFileNames subst);
+ ScummEngine(OSystem *syst, const DetectorResult &dr);
virtual ~ScummEngine();
/** Startup function, main loop. */
@@ -473,7 +473,6 @@ public:
// Misc utility functions
uint32 _debugFlags;
- const char *getBaseName() const { return _baseName.c_str(); }
// Cursor/palette
void updateCursor();
@@ -587,9 +586,9 @@ public:
int _roomResource; // FIXME - should be protected but Sound::pauseSounds uses it
bool _egoPositioned; // Used by Actor::putActor, hence public
- void generateSubstResFileName(const char *filename, char *buf, int bufsize);
- SubstResFileNames _substResFileName;
- SubstResFileNames _substResFileNameBundle; // Used with Mac bundles
+ FilenamePattern _filenamePattern;
+
+ Common::String generateFilename(const int room) const;
protected:
int _keyPressed;
@@ -733,11 +732,10 @@ public:
/** The name of the (macintosh/rescumm style) container file, if any. */
Common::String _containerFile;
- bool openFile(BaseScummFile &file, const char *filename, bool resourceFile = false);
+ bool openFile(BaseScummFile &file, const char *filename, bool resourceFile = false); // TODO: Use Common::String
protected:
int _resourceHeaderSize;
- Common::String _baseName; // This is the name we use for opening resource files
byte _resourceMapper[128];
byte *_heV7DiskOffsets;
uint32 *_heV7RoomIntOffsets;
@@ -749,8 +747,8 @@ protected:
void closeRoom();
void deleteRoomOffsets();
virtual void readRoomsOffsets();
- void askForDisk(const char *filename, int disknum);
- bool openResourceFile(const char *filename, byte encByte);
+ void askForDisk(const char *filename, int disknum); // TODO: Use Common::String
+ bool openResourceFile(const char *filename, byte encByte); // TODO: Use Common::String
void loadPtrToResource(int type, int i, const byte *ptr);
virtual void readResTypeList(int id, const char *name);
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 2a94230ce6..9dfeecc80b 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -996,7 +996,6 @@ ScummFile *Sound::openSfxFile() {
};
char buf[256];
- char buf1[128];
ScummFile *file = new ScummFile();
_offsetTable = NULL;
@@ -1004,19 +1003,22 @@ ScummFile *Sound::openSfxFile() {
* That way, you can keep .sou files for multiple games in the
* same directory */
- const char *basename[4] = { 0, 0, 0, 0 };
- basename[0] = _vm->getBaseName();
- basename[1] = "monster";
+ Common::String basename[2];
- if (_vm->_substResFileName.almostGameID != 0) {
- _vm->generateSubstResFileName(basename[0], buf1, sizeof(buf1));
- basename[2] = buf1;
+ const char *ptr = strchr(_vm->_filenamePattern.pattern, '.');
+ if (ptr) {
+ basename[0] = Common::String(_vm->_filenamePattern.pattern, ptr - _vm->_filenamePattern.pattern + 1);
+ } else {
+ basename[0] = _vm->_filenamePattern.pattern;
+ basename[0] += '.';
}
+ basename[1] = "monster.";
- for (int j = 0; basename[j] && !file->isOpen(); ++j) {
+ for (uint j = 0; j < 2 && !file->isOpen(); ++j) {
for (int i = 0; extensions[i].ext; ++i) {
- sprintf(buf, "%s.%s", basename[j], extensions[i].ext);
- if (_vm->openFile(*file, buf)) {
+ Common::String tmp(basename[j]);
+ tmp += extensions[i].ext;
+ if (_vm->openFile(*file, tmp.c_str())) {
_soundMode = extensions[i].mode;
break;
}
@@ -1025,15 +1027,11 @@ ScummFile *Sound::openSfxFile() {
if (!file->isOpen()) {
if ((_vm->_game.heversion <= 61 && _vm->_game.platform == Common::kPlatformMacintosh) || (_vm->_game.heversion >= 70)) {
- sprintf(buf, "%s.he2", _vm->getBaseName());
+ strncpy(buf, _vm->generateFilename(2).c_str(), sizeof(buf));
} else {
- sprintf(buf, "%s.tlk", _vm->getBaseName());
+ sprintf(buf, "%s.tlk", _vm->_filenamePattern.pattern);
}
- if (_vm->_substResFileName.almostGameID != 0) {
- _vm->generateSubstResFileName(buf, buf1, sizeof(buf1));
- strcpy(buf, buf1);
- }
if (file->open(buf) && _vm->_game.heversion <= 73)
file->setEnc(0x69);
_soundMode = kVOCMode;