aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/kyra_hof.cpp3
-rw-r--r--engines/kyra/resource.cpp27
-rw-r--r--engines/kyra/resource.h12
-rw-r--r--engines/kyra/resource_intern.cpp24
-rw-r--r--engines/kyra/resource_intern.h13
-rw-r--r--engines/kyra/staticres.cpp147
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;