diff options
author | Max Horn | 2006-04-23 17:33:16 +0000 |
---|---|---|
committer | Max Horn | 2006-04-23 17:33:16 +0000 |
commit | 0d67640a58b044ade0605319e091df9b2f666e4a (patch) | |
tree | fcec3906ad2abb5ea28072663193a7cce9282e83 | |
parent | d11f5724f96107a07d462be2410d93f55bd1fba2 (diff) | |
download | scummvm-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
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | engines/scumm/cursor.cpp | 4 | ||||
-rw-r--r-- | engines/scumm/debugger.cpp | 2 | ||||
-rw-r--r-- | engines/scumm/he/intern_he.h | 16 | ||||
-rw-r--r-- | engines/scumm/he/resource_he.cpp | 45 | ||||
-rw-r--r-- | engines/scumm/he/resource_he.h | 2 | ||||
-rw-r--r-- | engines/scumm/he/sound_he.cpp | 18 | ||||
-rw-r--r-- | engines/scumm/intern.h | 18 | ||||
-rw-r--r-- | engines/scumm/plugin.cpp | 1484 | ||||
-rw-r--r-- | engines/scumm/plugin.h | 37 | ||||
-rw-r--r-- | engines/scumm/resource.cpp | 111 | ||||
-rw-r--r-- | engines/scumm/scumm-md5.h | 78 | ||||
-rw-r--r-- | engines/scumm/scumm.cpp | 145 | ||||
-rw-r--r-- | engines/scumm/scumm.h | 16 | ||||
-rw-r--r-- | engines/scumm/sound.cpp | 30 | ||||
-rw-r--r-- | tools/scumm-md5.txt | 78 |
16 files changed, 691 insertions, 1394 deletions
@@ -1224,7 +1224,6 @@ An example config file looks as follows: The following keywords are recognized: - basename string path string The path to where a game's data files are read_only bool If true, ScummVM will never try to overwrite the configuration file. 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; diff --git a/tools/scumm-md5.txt b/tools/scumm-md5.txt index d8b9c74fa9..b95e3d3af5 100644 --- a/tools/scumm-md5.txt +++ b/tools/scumm-md5.txt @@ -24,8 +24,8 @@ # that their description in the launcher doesn't start with "Zak McKracken" # maniac Maniac Mansion - d831f7c048574dd9d5d85db2a1468099 en C64 - - - - c4a7f7398ac9ae588940f9912ea5fd8f de C64 - - - + d831f7c048574dd9d5d85db2a1468099 en C64 C64 - - + c4a7f7398ac9ae588940f9912ea5fd8f de C64 C64 - - 7f45ddd6dbfbf8f80c0c0efea4c295bc en DOS V1 V1 - d8d07efcb88f396bee0b402b10c3b1c9 us NES NES - - @@ -39,49 +39,49 @@ maniac Maniac Mansion 3a5ec90d556d4920976c5578bfbfaf79 de NES NES extracted - 6b5a3fef241e90d4b2e77f1e222773ee se NES NES extracted - - e781230da44a44e2f0770edb2b3b3633 en Amiga - V2 - dhewg, Andrea Petrucci - ce7733f185b838e248927c7ba1a04204 fr Amiga - V2 - Tobias Fleischer - 9bc548e179cdb0767009401c094d0895 de Amiga - V2 - Norbert Lange - a570381b028972d891052ee1e51dc011 en Atari - V2 - Andreas Bylund - dd30a53035393baa5a5e222e716559af fr Atari - V2 - Andreas Bylund - be83e882b44f2767bc08d4f766ebc347 de Atari - V2 - Joachim Eberhard - 15240c59d3681ed53f714f8d925cb2d6 es Atari - V2 - VooD - 624cdb93654667c869d204a64af7e57f en DOS - V2 - Kirben, Andrea Petrucci - b250d0f9cc83f80ced56fe11a4fb057c en DOS - V2 alt? Andrea Petrucci - 114acdc2659a273c220f86ee9edb24c1 fr DOS - V2 - Nicolas Sauzède - 99a3699f80b8f776efae592b44b9b991 fr DOS - V2 from DOTT Nicolas Sauzède, Andrea Petrucci - 183d7464902d40d00800e8ee1f04117c de DOS - V2 - - 87f6e8037b7cc996e13474b491a7a98e it DOS - V2 from DOTT Andrea Petrucci - 0d1b69471605201ef2fa9cec1f5f02d2 es DOS - V2 - abnog, Andrea Petrucci - - 40564ec47da48a67787d1f9bd043902a en DOS - Demo non-interactive + e781230da44a44e2f0770edb2b3b3633 en Amiga V2 V2 - dhewg, Andrea Petrucci + ce7733f185b838e248927c7ba1a04204 fr Amiga V2 V2 - Tobias Fleischer + 9bc548e179cdb0767009401c094d0895 de Amiga V2 V2 - Norbert Lange + a570381b028972d891052ee1e51dc011 en Atari V2 V2 - Andreas Bylund + dd30a53035393baa5a5e222e716559af fr Atari V2 V2 - Andreas Bylund + be83e882b44f2767bc08d4f766ebc347 de Atari V2 V2 - Joachim Eberhard + 15240c59d3681ed53f714f8d925cb2d6 es Atari V2 V2 - VooD + 624cdb93654667c869d204a64af7e57f en DOS V2 V2 - Kirben, Andrea Petrucci + b250d0f9cc83f80ced56fe11a4fb057c en DOS V2 V2 alt? Andrea Petrucci + 114acdc2659a273c220f86ee9edb24c1 fr DOS V2 V2 - Nicolas Sauzède + 99a3699f80b8f776efae592b44b9b991 fr DOS V2 V2 from DOTT Nicolas Sauzède, Andrea Petrucci + 183d7464902d40d00800e8ee1f04117c de DOS V2 V2 - + 87f6e8037b7cc996e13474b491a7a98e it DOS V2 V2 from DOTT Andrea Petrucci + 0d1b69471605201ef2fa9cec1f5f02d2 es DOS V2 V2 - abnog, Andrea Petrucci + + 40564ec47da48a67787d1f9bd043902a en DOS Demo Demo non-interactive zak Zak McKracken and the Alien Mindbenders - 55d3987641bf229c83bc729210173383 en C64 - - - - 4973bbc3899e3826dbf316e1d7271ec7 de C64 - - - + 55d3987641bf229c83bc729210173383 en C64 V1 - - + 4973bbc3899e3826dbf316e1d7271ec7 de C64 V1 - - 7020931d5a2be0a49d68e7a1882363e4 en DOS V1 V1 - b23f7cd7c304d7dff08e92a96120d5b4 en DOS V1 V1 alt? Andrea Petrucci - e94c7cc3686fce406d3c91b5eae5a72d en Amiga - V2 - dhweg - 91469353f7be1b122fa88d23480a1320 fr Amiga - V2 - Tobias Fleischer - 6027e9ca9c35746d95dee2068cec17e5 de Amiga - V2 - Norbert Lange - 27b3a4224ad63d5b04627595c1c1a025 it Amiga - V2 - Andrea Petrucci - d55eff37c2100f5065cde9de428621fa en Atari - V2 - - 613f64f78ea26c7353b2a5940eb61d6a fr Atari - V2 - Andreas Bylund - ff05c07990061d97647f059c48c1d05a de Atari - V2 - - 675d71151e9b5a968c8ce46d9fbf4cbf en DOS - V2 - Kirben - debe337f73d660e951ece7c1f1c81add en DOS - V2 alt? Andrea Petrucci - 52a4bae0746a11d7b1e8554e91a6645c fr DOS - V2 - Andrea Petrucci - c4787c3e8b5e2dfda90850ee800af00f fr DOS - V2 alt? Qvist - cdd760228cf1010c2903f37e788ea31c de DOS - V2 - Max Horn - d06fbe28818fef7bfc45c2cdf0c0849d de DOS - V2 from 5.25\" floppies Nicolas Sauzède, Andrea Petrucci - 1900e501a52fbf55bde6e4196f6d2aa6 it DOS - V2 - Andrea Petrucci - 75ba23fff4fd63fa446c02864f2a5a4b it DOS - V2 alt? Antti Leimi, Andrea Petrucci + e94c7cc3686fce406d3c91b5eae5a72d en Amiga V2 V2 - dhweg + 91469353f7be1b122fa88d23480a1320 fr Amiga V2 V2 - Tobias Fleischer + 6027e9ca9c35746d95dee2068cec17e5 de Amiga V2 V2 - Norbert Lange + 27b3a4224ad63d5b04627595c1c1a025 it Amiga V2 V2 - Andrea Petrucci + d55eff37c2100f5065cde9de428621fa en Atari V2 V2 - + 613f64f78ea26c7353b2a5940eb61d6a fr Atari V2 V2 - Andreas Bylund + ff05c07990061d97647f059c48c1d05a de Atari V2 V2 - + 675d71151e9b5a968c8ce46d9fbf4cbf en DOS V2 V2 - Kirben + debe337f73d660e951ece7c1f1c81add en DOS V2 V2 alt? Andrea Petrucci + 52a4bae0746a11d7b1e8554e91a6645c fr DOS V2 V2 - Andrea Petrucci + c4787c3e8b5e2dfda90850ee800af00f fr DOS V2 V2 alt? Qvist + cdd760228cf1010c2903f37e788ea31c de DOS V2 V2 - Max Horn + d06fbe28818fef7bfc45c2cdf0c0849d de DOS V2 V2 from 5.25\" floppies Nicolas Sauzède, Andrea Petrucci + 1900e501a52fbf55bde6e4196f6d2aa6 it DOS V2 V2 - Andrea Petrucci + 75ba23fff4fd63fa446c02864f2a5a4b it DOS V2 V2 alt? Antti Leimi, Andrea Petrucci 2d4536a56e01da4b02eb021e7770afa2 en FM-TOWNS FM-TOWNS - - 1ca86e2cf9aaa2068738a1e5ba477e60 jp FM-TOWNS FM-TOWNS - - Andrea Petrucci - 8299d9b8a1b0e7b881bae7a9971dc5e2 en Atari - Demo non-interactive + 8299d9b8a1b0e7b881bae7a9971dc5e2 en Atari V2 Demo non-interactive indy3 Indiana Jones and the Last Crusade 9c0fee288ad564a7d25ec3e841810d79 en Amiga EGA EGA - dhewg @@ -311,10 +311,10 @@ dig The Dig cd9c05e755d7bf8e9b9590ad1ebe273e en Mac Demo Demo Mac bundle fingolfin comi The Curse of Monkey Island - fe60d6b5ff51b0553ac59963123b5777 All All - - - - 861e59ed72a1cd0e6d454f7ee7e2bf3d ru All - - - + fe60d6b5ff51b0553ac59963123b5777 All Windows - - - + 861e59ed72a1cd0e6d454f7ee7e2bf3d ru Windows - - - - 8fec68383202d38c0d25e9e3b757c5df All All Demo Demo - + 8fec68383202d38c0d25e9e3b757c5df All Windows Demo Demo - baseball Backyard Baseball cf8d13446ec6cb6222287a925fd47c1d en All - - - sev |