mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-25 05:34:27 +00:00
Check all 'kyra.dat' files in setup paths instead of only the first one found.
svn-id: r34735
This commit is contained in:
parent
e417471177
commit
f3469eae94
@ -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'");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user