mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-09 12:22:51 +00:00
Revised way of how archive files are mounted:
- file entries from protected archives do not get overwritten anymore - preload indicator of archives will be unflagged, if embedded file entries are overwritten by other archives svn-id: r30838
This commit is contained in:
parent
bacdc6eff0
commit
76182fbd59
@ -154,9 +154,41 @@ bool Resource::loadPakFile(const Common::String &filename) {
|
||||
|
||||
iter->_value.mounted = true;
|
||||
iter->_value.preload = true;
|
||||
loader->loadFile(filename, *stream, _map);
|
||||
ResArchiveLoader::FileList files;
|
||||
loader->loadFile(filename, *stream, files);
|
||||
delete stream;
|
||||
stream = 0;
|
||||
|
||||
for (ResArchiveLoader::FileList::iterator i = files.begin(); i != files.end(); ++i) {
|
||||
iter = _map.find(i->filename);
|
||||
if (iter == _map.end()) {
|
||||
_map[i->filename] = i->entry;
|
||||
} else if (!iter->_value.parent.empty()) {
|
||||
if (!iter->_value.parent.equalsIgnoreCase(filename)) {
|
||||
ResFileMap::iterator oldParent = _map.find(iter->_value.parent);
|
||||
if (oldParent != _map.end()) {
|
||||
// Protected files and their embedded files don't get overwritten!
|
||||
if (!oldParent->_value.prot) {
|
||||
// If it's not protected we mark the old parent as not preload anymore,
|
||||
// since not all of its embedded files are not in the filemap now anymore.
|
||||
oldParent->_value.preload = false;
|
||||
_map[i->filename] = i->entry;
|
||||
}
|
||||
} else {
|
||||
// Old parent not found? That's strange... But we just overwrite the old
|
||||
// entry.
|
||||
_map[i->filename] = i->entry;
|
||||
}
|
||||
} else {
|
||||
// The parent has the same filenames as we, but we are sure and overwrite the
|
||||
// old file entry.
|
||||
_map[i->filename] = i->entry;
|
||||
}
|
||||
}
|
||||
// 'else' case would mean here an existing fileentry in the map without parent.
|
||||
// We don't support that though, so one can overwrite files from archives by putting
|
||||
// them in the gamepath.
|
||||
}
|
||||
|
||||
detectFileTypes();
|
||||
return true;
|
||||
@ -322,7 +354,7 @@ Common::SeekableReadStream *Resource::getFileStream(const Common::String &file)
|
||||
const ResArchiveLoader *loader = getLoader(parentIter->_value.type);
|
||||
assert(loader);
|
||||
|
||||
return loader->loadFileFromArchive(file, parent, _map);
|
||||
return loader->loadFileFromArchive(file, parent, iter->_value);
|
||||
} else {
|
||||
Common::File *stream = new Common::File();
|
||||
if (!stream->open(file.c_str())) {
|
||||
@ -393,8 +425,8 @@ class ResLoaderPak : public ResArchiveLoader {
|
||||
public:
|
||||
bool checkFilename(Common::String filename) const;
|
||||
bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const;
|
||||
bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, ResFileMap &map) const;
|
||||
Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileMap &map) const;
|
||||
bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const;
|
||||
Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const;
|
||||
|
||||
ResFileEntry::kType getType() const {
|
||||
return ResFileEntry::kPak;
|
||||
@ -450,12 +482,9 @@ bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableRe
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, ResFileMap &map) const {
|
||||
bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const {
|
||||
uint32 filesize = stream.size();
|
||||
|
||||
Common::List<Common::String> filenames;
|
||||
Common::List<ResFileEntry> entries;
|
||||
|
||||
uint32 startoffset = 0, endoffset = 0;
|
||||
bool switchEndian = false;
|
||||
bool firstFile = true;
|
||||
@ -510,8 +539,7 @@ bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableRead
|
||||
entry.prot = false;
|
||||
entry.preload = false;
|
||||
|
||||
filenames.push_back(file);
|
||||
entries.push_back(entry);
|
||||
files.push_back(File(file, entry));
|
||||
}
|
||||
|
||||
if (endoffset == filesize)
|
||||
@ -520,26 +548,14 @@ bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableRead
|
||||
startoffset = endoffset;
|
||||
}
|
||||
|
||||
assert(filenames.size() == entries.size());
|
||||
|
||||
Common::List<ResFileEntry>::iterator entry = entries.begin();
|
||||
Common::List<Common::String>::iterator file = filenames.begin();
|
||||
|
||||
for (; entry != entries.end(); ++entry, ++file)
|
||||
map[*file] = *entry;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *ResLoaderPak::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileMap &map) const {
|
||||
Common::SeekableReadStream *ResLoaderPak::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const {
|
||||
assert(archive);
|
||||
|
||||
ResFileMap::const_iterator entry = map.find(file);
|
||||
if (entry == map.end())
|
||||
return 0;
|
||||
|
||||
archive->seek(entry->_value.offset, SEEK_SET);
|
||||
Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry->_value.offset, entry->_value.offset + entry->_value.size, true);
|
||||
archive->seek(entry.offset, SEEK_SET);
|
||||
Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry.offset, entry.offset + entry.size, true);
|
||||
assert(stream);
|
||||
return stream;
|
||||
}
|
||||
@ -548,8 +564,8 @@ class ResLoaderIns : public ResArchiveLoader {
|
||||
public:
|
||||
bool checkFilename(Common::String filename) const;
|
||||
bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const;
|
||||
bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, ResFileMap &map) const;
|
||||
Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileMap &map) const;
|
||||
bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const;
|
||||
Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const;
|
||||
|
||||
ResFileEntry::kType getType() const {
|
||||
return ResFileEntry::kIns;
|
||||
@ -575,7 +591,7 @@ bool ResLoaderIns::isLoadable(const Common::String &filename, Common::SeekableRe
|
||||
return (buffer[0] == 0x0D && buffer[1] == 0x0A);
|
||||
}
|
||||
|
||||
bool ResLoaderIns::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, ResFileMap &map) const {
|
||||
bool ResLoaderIns::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const {
|
||||
Common::List<Common::String> filenames;
|
||||
|
||||
// thanks to eriktorbjorn for this code (a bit modified though)
|
||||
@ -614,22 +630,17 @@ bool ResLoaderIns::loadFile(const Common::String &filename, Common::SeekableRead
|
||||
entry.size = stream.readUint32LE();
|
||||
entry.offset = stream.pos();
|
||||
stream.seek(entry.size, SEEK_CUR);
|
||||
|
||||
map[*file] = entry;
|
||||
files.push_back(File(*file, entry));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *ResLoaderIns::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileMap &map) const {
|
||||
Common::SeekableReadStream *ResLoaderIns::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const {
|
||||
assert(archive);
|
||||
|
||||
ResFileMap::const_iterator entry = map.find(file);
|
||||
if (entry == map.end())
|
||||
return 0;
|
||||
|
||||
archive->seek(entry->_value.offset, SEEK_SET);
|
||||
Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry->_value.offset, entry->_value.offset + entry->_value.size, true);
|
||||
archive->seek(entry.offset, SEEK_SET);
|
||||
Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry.offset, entry.offset + entry.size, true);
|
||||
assert(stream);
|
||||
return stream;
|
||||
}
|
||||
|
@ -62,13 +62,22 @@ class Resource;
|
||||
|
||||
class ResArchiveLoader {
|
||||
public:
|
||||
struct File {
|
||||
File() : filename(), entry() {}
|
||||
File(const Common::String &f, const ResFileEntry &e) : filename(f), entry(e) {}
|
||||
|
||||
Common::String filename;
|
||||
ResFileEntry entry;
|
||||
};
|
||||
typedef Common::List<File> FileList;
|
||||
|
||||
virtual ~ResArchiveLoader() {}
|
||||
|
||||
virtual bool checkFilename(Common::String filename) const = 0;
|
||||
virtual bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const = 0;
|
||||
virtual bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, ResFileMap &map) const = 0;
|
||||
virtual bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const = 0;
|
||||
// parameter 'archive' can be deleted by this method and it may not be deleted from the caller
|
||||
virtual Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileMap &map) const = 0;
|
||||
virtual Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const = 0;
|
||||
|
||||
virtual ResFileEntry::kType getType() const = 0;
|
||||
protected:
|
||||
|
Loading…
x
Reference in New Issue
Block a user