diff options
| -rw-r--r-- | engines/kyra/kyra_hof.cpp | 3 | ||||
| -rw-r--r-- | engines/kyra/resource.cpp | 27 | ||||
| -rw-r--r-- | engines/kyra/resource.h | 12 | ||||
| -rw-r--r-- | engines/kyra/resource_intern.cpp | 24 | ||||
| -rw-r--r-- | engines/kyra/resource_intern.h | 13 | ||||
| -rw-r--r-- | engines/kyra/staticres.cpp | 147 | 
6 files changed, 131 insertions, 95 deletions
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<Common::ArchiveMember> 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<Common::SearchSet> _protectedFiles;  	Common::ArchivePtr loadArchive(const Common::String &file); +	Common::ArchivePtr loadArchive(const Common::String &name, Common::SharedPtr<Common::ArchiveMember> 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<Common::ArchiveMember> 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<Common::ArchiveMember> 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<Common::ArchiveMember> memberFile, Common::SeekableReadStream &stream) const {  	Common::List<Common::String> 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<Common::ArchiveMember> 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<InputEntry> FileInputList; -	PlainArchive(Resource *owner, const Common::String &filename, const FileInputList &files); +	PlainArchive(Common::SharedPtr<Common::ArchiveMember> file, const FileInputList &files);  	bool hasFile(const Common::String &name);  	int listMembers(Common::ArchiveMemberList &list); @@ -60,8 +60,7 @@ private:  	typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap; -	Resource *_owner; -	Common::String _filename; +	Common::SharedPtr<Common::ArchiveMember> _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<Common::ArchiveMember> 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<Common::ArchiveMember> 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<Common::ArchiveMember> 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<Common::ArchiveMember> 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<Common::SeekableReadStream> 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;  | 
