From f3469eae94e196d84f828edb02972f1abc7e73fc Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 3 Oct 2008 18:18:42 +0000 Subject: Check all 'kyra.dat' files in setup paths instead of only the first one found. svn-id: r34735 --- engines/kyra/kyra_hof.cpp | 3 +- engines/kyra/resource.cpp | 27 ++++--- engines/kyra/resource.h | 12 +++- engines/kyra/resource_intern.cpp | 24 +++---- engines/kyra/resource_intern.h | 13 ++-- engines/kyra/staticres.cpp | 147 +++++++++++++++++++++++---------------- 6 files changed, 131 insertions(+), 95 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index e5043f0c4e..a0213c0be3 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -298,7 +298,8 @@ int KyraEngine_HoF::go() { if (_menuChoice != 4) { // load just the pak files needed for ingame - _res->loadPakFile(StaticResource::staticDataFilename()); + _staticres->loadStaticResourceFile(); + if (_flags.platform == Common::kPlatformPC && _flags.isTalkie) { if (!_res->loadFileList("FILEDATA.FDT")) error("couldn't load 'FILEDATA.FDT'"); diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 798290b16c..9d43d6976a 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -62,12 +62,6 @@ bool Resource::reset() { if (!dir.exists() || !dir.isDirectory()) error("invalid game path '%s'", dir.getPath().c_str()); - if (!loadPakFile(StaticResource::staticDataFilename()) || !StaticResource::checkKyraDat(this)) { - Common::String errorMessage = "You're missing the '" + StaticResource::staticDataFilename() + "' file or it got corrupted, (re)get it from the ScummVM website"; - GUIErrorMessage(errorMessage); - error(errorMessage.c_str()); - } - if (_vm->game() == GI_KYRA1) { // We only need kyra.dat for the demo. if (_vm->gameFlags().isDemo) @@ -276,16 +270,27 @@ Common::ArchivePtr Resource::loadArchive(const Common::String &file) { if (cachedArchive != _archiveCache.end()) return cachedArchive->_value; - Common::SeekableReadStream *stream = getFileStream(file); + Common::ArchiveMemberList list; + _files.listMatchingMembers(list, file); + + if (list.empty()) + return Common::ArchivePtr(); + + return loadArchive(file, *list.begin()); +} + +Common::ArchivePtr Resource::loadArchive(const Common::String &name, Common::SharedPtr member) { + Common::SeekableReadStream *stream = member->open(); + if (!stream) return Common::ArchivePtr(); Common::ArchivePtr archive; for (LoaderList::const_iterator i = _loaders.begin(); i != _loaders.end(); ++i) { - if ((*i)->checkFilename(file)) { - if ((*i)->isLoadable(file, *stream)) { + if ((*i)->checkFilename(name)) { + if ((*i)->isLoadable(name, *stream)) { stream->seek(0, SEEK_SET); - archive = Common::ArchivePtr((*i)->load(this, file, *stream)); + archive = Common::ArchivePtr((*i)->load(member, *stream)); break; } else { stream->seek(0, SEEK_SET); @@ -298,7 +303,7 @@ Common::ArchivePtr Resource::loadArchive(const Common::String &file) { if (!archive) return Common::ArchivePtr(); - _archiveCache[file] = archive; + _archiveCache[name] = archive; return archive; } diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 799068d158..81cf762d42 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -40,6 +40,10 @@ #include "kyra/kyra_v1.h" #include "kyra/kyra_hof.h" +namespace Common { +class ArchiveMember; +} // end of namespace Common + namespace Kyra { class Resource; @@ -47,6 +51,7 @@ class Resource; class ResArchiveLoader; class Resource { + friend class StaticResource; public: Resource(KyraEngine_v1 *vm); ~Resource(); @@ -77,6 +82,7 @@ protected: Common::SharedPtr _protectedFiles; Common::ArchivePtr loadArchive(const Common::String &file); + Common::ArchivePtr loadArchive(const Common::String &name, Common::SharedPtr member); Common::ArchivePtr loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset); void initializeLoaders(); @@ -207,12 +213,12 @@ struct Room; class StaticResource { public: - static const Common::String staticDataFilename() { return "kyra.dat"; } + static const Common::String staticDataFilename() { return "KYRA.DAT"; } StaticResource(KyraEngine_v1 *vm) : _vm(vm), _resList(), _fileLoader(0), _builtIn(0), _filenameTable(0) {} ~StaticResource() { deinit(); } - static bool checkKyraDat(Resource *res); + bool loadStaticResourceFile(); bool init(); void deinit(); @@ -233,7 +239,7 @@ public: bool prefetchId(int id); void unloadId(int id); private: - void outputError(const Common::String &error); + bool tryKyraDatLoad(); KyraEngine_v1 *_vm; diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp index 0bec5297ed..3525718f95 100644 --- a/engines/kyra/resource_intern.cpp +++ b/engines/kyra/resource_intern.cpp @@ -35,8 +35,8 @@ namespace Kyra { // -> PlainArchive implementation -PlainArchive::PlainArchive(Resource *owner, const Common::String &filename, const FileInputList &files) - : _owner(owner), _filename(filename), _files() { +PlainArchive::PlainArchive(Common::SharedPtr file, const FileInputList &files) + : _file(file), _files() { for (FileInputList::iterator i = files.begin(); i != files.end(); ++i) { Entry entry; @@ -67,7 +67,7 @@ Common::SeekableReadStream *PlainArchive::openFile(const Common::String &name) { if (fDesc == _files.end()) return 0; - Common::SeekableReadStream *parent = _owner->getFileStream(_filename); + Common::SeekableReadStream *parent = _file->open(); if (!parent) return 0; @@ -195,7 +195,7 @@ struct PlainArchiveListSearch { } // end of anonymous namespace -Common::Archive *ResLoaderPak::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const { +Common::Archive *ResLoaderPak::load(Common::SharedPtr memberFile, Common::SeekableReadStream &stream) const { int32 filesize = stream.size(); int32 startoffset = 0, endoffset = 0; @@ -214,7 +214,7 @@ Common::Archive *ResLoaderPak::load(Resource *owner, const Common::String &filen while (!stream.eos()) { // The start offset of a file should never be in the filelist if (startoffset < stream.pos() || startoffset > filesize) { - warning("PAK file '%s' is corrupted", filename.c_str()); + warning("PAK file '%s' is corrupted", memberFile->getName().c_str()); return false; } @@ -225,14 +225,14 @@ Common::Archive *ResLoaderPak::load(Resource *owner, const Common::String &filen file += c; if (stream.eos()) { - warning("PAK file '%s' is corrupted", filename.c_str()); + warning("PAK file '%s' is corrupted", memberFile->getName().c_str()); return false; } // Quit now if we encounter an empty string if (file.empty()) { if (firstFile) { - warning("PAK file '%s' is corrupted", filename.c_str()); + warning("PAK file '%s' is corrupted", memberFile->getName().c_str()); return false; } else { break; @@ -287,7 +287,7 @@ Common::Archive *ResLoaderPak::load(Resource *owner, const Common::String &filen } } - return new PlainArchive(owner, filename, files); + return new PlainArchive(memberFile, files); } // -> ResLoaderInsMalcolm implementation @@ -313,7 +313,7 @@ bool ResLoaderInsMalcolm::isLoadable(const Common::String &filename, Common::See return (buffer[0] == 0x0D && buffer[1] == 0x0A); } -Common::Archive *ResLoaderInsMalcolm::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const { +Common::Archive *ResLoaderInsMalcolm::load(Common::SharedPtr memberFile, Common::SeekableReadStream &stream) const { Common::List filenames; PlainArchive::FileInputList files; @@ -353,7 +353,7 @@ Common::Archive *ResLoaderInsMalcolm::load(Resource *owner, const Common::String files.push_back(entry); } - return new PlainArchive(owner, filename, files); + return new PlainArchive(memberFile, files); } bool ResLoaderTlk::checkFilename(Common::String filename) const { @@ -381,7 +381,7 @@ bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableRe return true; } -Common::Archive *ResLoaderTlk::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const { +Common::Archive *ResLoaderTlk::load(Common::SharedPtr file, Common::SeekableReadStream &stream) const { uint16 entries = stream.readUint16LE(); PlainArchive::FileInputList files; @@ -405,7 +405,7 @@ Common::Archive *ResLoaderTlk::load(Resource *owner, const Common::String &filen files.push_back(entry); } - return new PlainArchive(owner, filename, files); + return new PlainArchive(file, files); } // InstallerLoader implementation diff --git a/engines/kyra/resource_intern.h b/engines/kyra/resource_intern.h index a3fbe9f1f9..6347c538fc 100644 --- a/engines/kyra/resource_intern.h +++ b/engines/kyra/resource_intern.h @@ -47,7 +47,7 @@ public: typedef Common::List FileInputList; - PlainArchive(Resource *owner, const Common::String &filename, const FileInputList &files); + PlainArchive(Common::SharedPtr file, const FileInputList &files); bool hasFile(const Common::String &name); int listMembers(Common::ArchiveMemberList &list); @@ -60,8 +60,7 @@ private: typedef Common::HashMap FileMap; - Resource *_owner; - Common::String _filename; + Common::SharedPtr _file; FileMap _files; }; @@ -98,28 +97,28 @@ public: virtual ~ResArchiveLoader() {} virtual bool checkFilename(Common::String filename) const = 0; virtual bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const = 0; - virtual Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const = 0; + virtual Common::Archive *load(Common::SharedPtr file, Common::SeekableReadStream &stream) const = 0; }; class ResLoaderPak : public ResArchiveLoader { public: bool checkFilename(Common::String filename) const; bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; - Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const; + Common::Archive *load(Common::SharedPtr file, Common::SeekableReadStream &stream) const; }; class ResLoaderInsMalcolm : public ResArchiveLoader { public: bool checkFilename(Common::String filename) const; bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; - Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const; + Common::Archive *load(Common::SharedPtr file, Common::SeekableReadStream &stream) const; }; class ResLoaderTlk : public ResArchiveLoader { public: bool checkFilename(Common::String filename) const; bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; - Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const; + Common::Archive *load(Common::SharedPtr file, Common::SeekableReadStream &stream) const; }; class InstallerLoader { diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index ba8de9c57f..5cfd682b9c 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -45,20 +45,20 @@ namespace Kyra { #define RESFILE_VERSION 32 -bool StaticResource::checkKyraDat(Resource *res) { - Common::SharedPtr kyraDat(res->getFileStream(StaticResource::staticDataFilename())); - if (!kyraDat) +namespace { +bool checkKyraDat(Common::SeekableReadStream *file) { + if (!file) return false; - uint32 size = kyraDat->size() - 16; + uint32 size = file->size() - 16; uint8 digest[16]; - kyraDat->seek(size, SEEK_SET); - if (kyraDat->read(digest, 16) != 16) + file->seek(size, SEEK_SET); + if (file->read(digest, 16) != 16) return false; uint8 digestCalc[16]; - kyraDat->seek(0, SEEK_SET); - if (!Common::md5_file(*kyraDat, digestCalc, size)) + file->seek(0, SEEK_SET); + if (!Common::md5_file(*file, digestCalc, size)) return false; for (int i = 0; i < 16; ++i) @@ -66,6 +66,7 @@ bool StaticResource::checkKyraDat(Resource *res) { return false; return true; } +} // end of anonymous namespace // used for the KYRA.DAT file which still uses // the old flag system, we just convert it, which @@ -132,6 +133,81 @@ static const LanguageTypes languages[] = { { 0, 0 } }; +bool StaticResource::loadStaticResourceFile() { + Resource *res = _vm->resource(); + + if (res->_archiveCache.find(staticDataFilename()) != res->_archiveCache.end()) + return true; + + Common::ArchiveMemberList kyraDatFiles; + res->_files.listMatchingMembers(kyraDatFiles, staticDataFilename()); + + bool foundWorkingKyraDat = false; + for (Common::ArchiveMemberList::iterator i = kyraDatFiles.begin(); i != kyraDatFiles.end(); ++i) { + Common::SeekableReadStream *file = (*i)->open(); + if (checkKyraDat(file)) { + file->seek(0, SEEK_SET); + + Common::ArchivePtr archive = res->loadArchive(staticDataFilename(), *i); + if (archive) { + res->_archiveFiles->add(staticDataFilename(), archive, 0); + foundWorkingKyraDat = tryKyraDatLoad(); + } + } + + delete file; + + if (foundWorkingKyraDat) + break; + + res->_archiveCache.erase(staticDataFilename()); + res->_archiveFiles->remove(staticDataFilename()); + unloadId(-1); + } + + if (!foundWorkingKyraDat) { + Common::String errorMessage = "You're missing the '" + StaticResource::staticDataFilename() + "' file or it got corrupted, (re)get it from the ScummVM website"; + GUIErrorMessage(errorMessage); + error(errorMessage.c_str()); + } + + return true; +} + +bool StaticResource::tryKyraDatLoad() { + Common::SeekableReadStream *index = getFile("INDEX"); + if (!index) + return false; + + if (index->size() != 3*4) { + delete index; + return false; + } + + uint32 version = index->readUint32BE(); + uint32 gameID = index->readUint32BE(); + uint32 featuresValue = index->readUint32BE(); + + delete index; + index = 0; + + if (version != RESFILE_VERSION) + return false; + + if (gameID != _vm->game()) + return false; + + uint32 gameFeatures = createFeatures(_vm->gameFlags()); + if ((featuresValue & GAME_FLAGS) != gameFeatures) + return false; + + // load all tables for now + if (!prefetchId(-1)) + return false; + + return true; +} + bool StaticResource::init() { #define proc(x) &StaticResource::x static const FileType fileTypeTable[] = { @@ -307,65 +383,14 @@ bool StaticResource::init() { error("StaticResource: Unknown game ID"); } - char errorBuffer[100]; - Common::SeekableReadStream *index = getFile("INDEX"); - if (!index) { - snprintf(errorBuffer, sizeof(errorBuffer), "is missing an '%s' entry", getFilename("INDEX")); - outputError(errorBuffer); - return false; - } - - if (index->size() != 3*4) { - delete index; - - snprintf(errorBuffer, sizeof(errorBuffer), "has incorrect header size for entry '%s'", getFilename("INDEX")); - outputError(errorBuffer); - return false; - } - - uint32 version = index->readUint32BE(); - uint32 gameID = index->readUint32BE(); - uint32 featuresValue = index->readUint32BE(); - - delete index; - index = 0; - - if (version != RESFILE_VERSION) { - snprintf(errorBuffer, sizeof(errorBuffer), "has invalid version %d required, you got %d", RESFILE_VERSION, version); - outputError(errorBuffer); - return false; - } - - if (gameID != _vm->game()) { - outputError("does not include support for your game"); - return false; - } - - uint32 gameFeatures = createFeatures(_vm->gameFlags()); - if ((featuresValue & GAME_FLAGS) != gameFeatures) { - outputError("does not include support for your game version"); - return false; - } - - // load all tables for now - if (!prefetchId(-1)) { - outputError("is lacking entries for your game version"); - return false; - } - return true; + return loadStaticResourceFile(); } void StaticResource::deinit() { unloadId(-1); } -void StaticResource::outputError(const Common::String &error) { - Common::String errorMessage = "Your '" + StaticResource::staticDataFilename() + "' file " + error + ", reget a correct version from the ScummVM website"; - GUIErrorMessage(errorMessage); - ::error(errorMessage.c_str()); -} - -const char * const*StaticResource::loadStrings(int id, int &strings) { +const char * const *StaticResource::loadStrings(int id, int &strings) { const char * const*temp = (const char* const*)getData(id, kStringList, strings); if (temp) return temp; -- cgit v1.2.3