mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 08:53:52 +00:00
devirtualises BSAFile (#3161)
Currently, Open MW's basic file access speed is limited by a peculiar layer of virtualisation in BSAFile's interface. This PR removes such virtualisation by properly separating BSAFile from CompressedBSAFile in low level contexts.
This commit is contained in:
parent
cbcdd705ee
commit
7c50f823d8
6 changed files with 79 additions and 19 deletions
|
@ -290,11 +290,6 @@ Files::IStreamPtr BSAFile::getFile(const char *file)
|
||||||
return Files::openConstrainedFileStream (mFilename.c_str (), fs.offset, fs.fileSize);
|
return Files::openConstrainedFileStream (mFilename.c_str (), fs.offset, fs.fileSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Files::IStreamPtr BSAFile::getFile(const FileStruct *file)
|
|
||||||
{
|
|
||||||
return Files::openConstrainedFileStream (mFilename.c_str (), file->offset, file->fileSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bsa::BSAFile::addFile(const std::string& filename, std::istream& file)
|
void Bsa::BSAFile::addFile(const std::string& filename, std::istream& file)
|
||||||
{
|
{
|
||||||
if (!mIsLoaded)
|
if (!mIsLoaded)
|
||||||
|
|
|
@ -154,7 +154,10 @@ public:
|
||||||
/** Open a file contained in the archive.
|
/** Open a file contained in the archive.
|
||||||
* @note Thread safe.
|
* @note Thread safe.
|
||||||
*/
|
*/
|
||||||
virtual Files::IStreamPtr getFile(const FileStruct* file);
|
Files::IStreamPtr getFile(const FileStruct *file)
|
||||||
|
{
|
||||||
|
return Files::openConstrainedFileStream (mFilename.c_str (), file->offset, file->fileSize);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void addFile(const std::string& filename, std::istream& file);
|
virtual void addFile(const std::string& filename, std::istream& file);
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace Bsa
|
||||||
void readHeader() override;
|
void readHeader() override;
|
||||||
|
|
||||||
Files::IStreamPtr getFile(const char* filePath) override;
|
Files::IStreamPtr getFile(const char* filePath) override;
|
||||||
Files::IStreamPtr getFile(const FileStruct* fileStruct) override;
|
Files::IStreamPtr getFile(const FileStruct* fileStruct);
|
||||||
void addFile(const std::string& filename, std::istream& file) override;
|
void addFile(const std::string& filename, std::istream& file) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "bsaarchive.hpp"
|
#include "bsaarchive.hpp"
|
||||||
#include <components/bsa/compressedbsafile.hpp>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace VFS
|
namespace VFS
|
||||||
|
@ -7,15 +7,7 @@ namespace VFS
|
||||||
|
|
||||||
BsaArchive::BsaArchive(const std::string &filename)
|
BsaArchive::BsaArchive(const std::string &filename)
|
||||||
{
|
{
|
||||||
Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(filename);
|
|
||||||
|
|
||||||
if (bsaVersion == Bsa::BSAVER_COMPRESSED) {
|
|
||||||
mFile = std::make_unique<Bsa::CompressedBSAFile>(Bsa::CompressedBSAFile());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mFile = std::make_unique<Bsa::BSAFile>(Bsa::BSAFile());
|
mFile = std::make_unique<Bsa::BSAFile>(Bsa::BSAFile());
|
||||||
}
|
|
||||||
|
|
||||||
mFile->open(filename);
|
mFile->open(filename);
|
||||||
|
|
||||||
const Bsa::BSAFile::FileList &filelist = mFile->getList();
|
const Bsa::BSAFile::FileList &filelist = mFile->getList();
|
||||||
|
@ -25,6 +17,10 @@ BsaArchive::BsaArchive(const std::string &filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BsaArchive::BsaArchive()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
BsaArchive::~BsaArchive() {
|
BsaArchive::~BsaArchive() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +52,31 @@ std::string BsaArchive::getDescription() const
|
||||||
return std::string{"BSA: "} + mFile->getFilename();
|
return std::string{"BSA: "} + mFile->getFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CompressedBsaArchive::CompressedBsaArchive(const std::string &filename)
|
||||||
|
: BsaArchive()
|
||||||
|
{
|
||||||
|
mFile = std::make_unique<Bsa::BSAFile>(Bsa::CompressedBSAFile());
|
||||||
|
mFile->open(filename);
|
||||||
|
|
||||||
|
const Bsa::BSAFile::FileList &filelist = mFile->getList();
|
||||||
|
for(Bsa::BSAFile::FileList::const_iterator it = filelist.begin();it != filelist.end();++it)
|
||||||
|
{
|
||||||
|
mResources.emplace_back(&*it, mFile.get());
|
||||||
|
mCompressedResources.emplace_back(&*it, static_cast<Bsa::CompressedBSAFile*>(mFile.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompressedBsaArchive::listResources(std::map<std::string, File *> &out, char (*normalize_function)(char))
|
||||||
|
{
|
||||||
|
for (std::vector<CompressedBsaArchiveFile>::iterator it = mCompressedResources.begin(); it != mCompressedResources.end(); ++it)
|
||||||
|
{
|
||||||
|
std::string ent = it->mInfo->name();
|
||||||
|
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
|
||||||
|
|
||||||
|
out[ent] = &*it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
BsaArchiveFile::BsaArchiveFile(const Bsa::BSAFile::FileStruct *info, Bsa::BSAFile* bsa)
|
BsaArchiveFile::BsaArchiveFile(const Bsa::BSAFile::FileStruct *info, Bsa::BSAFile* bsa)
|
||||||
|
@ -70,4 +91,16 @@ Files::IStreamPtr BsaArchiveFile::open()
|
||||||
return mFile->getFile(mInfo);
|
return mFile->getFile(mInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CompressedBsaArchiveFile::CompressedBsaArchiveFile(const Bsa::BSAFile::FileStruct *info, Bsa::CompressedBSAFile* bsa)
|
||||||
|
: BsaArchiveFile(info, bsa)
|
||||||
|
, mCompressedFile(bsa)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Files::IStreamPtr CompressedBsaArchiveFile::open()
|
||||||
|
{
|
||||||
|
return mCompressedFile->getFile(mInfo);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "archive.hpp"
|
#include "archive.hpp"
|
||||||
|
|
||||||
#include <components/bsa/bsa_file.hpp>
|
#include <components/bsa/bsa_file.hpp>
|
||||||
|
#include <components/bsa/compressedbsafile.hpp>
|
||||||
|
|
||||||
namespace VFS
|
namespace VFS
|
||||||
{
|
{
|
||||||
|
@ -18,19 +19,43 @@ namespace VFS
|
||||||
Bsa::BSAFile* mFile;
|
Bsa::BSAFile* mFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CompressedBsaArchiveFile : public BsaArchiveFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CompressedBsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::CompressedBSAFile* bsa);
|
||||||
|
|
||||||
|
Files::IStreamPtr open() override;
|
||||||
|
Bsa::CompressedBSAFile* mCompressedFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class BsaArchive : public Archive
|
class BsaArchive : public Archive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BsaArchive(const std::string& filename);
|
BsaArchive(const std::string& filename);
|
||||||
|
BsaArchive();
|
||||||
virtual ~BsaArchive();
|
virtual ~BsaArchive();
|
||||||
void listResources(std::map<std::string, File*>& out, char (*normalize_function) (char)) override;
|
void listResources(std::map<std::string, File*>& out, char (*normalize_function) (char)) override;
|
||||||
bool contains(const std::string& file, char (*normalize_function) (char)) const override;
|
bool contains(const std::string& file, char (*normalize_function) (char)) const override;
|
||||||
std::string getDescription() const override;
|
std::string getDescription() const override;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
std::unique_ptr<Bsa::BSAFile> mFile;
|
std::unique_ptr<Bsa::BSAFile> mFile;
|
||||||
std::vector<BsaArchiveFile> mResources;
|
std::vector<BsaArchiveFile> mResources;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CompressedBsaArchive : public BsaArchive
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CompressedBsaArchive(const std::string& filename);
|
||||||
|
void listResources(std::map<std::string, File*>& out, char (*normalize_function) (char)) override;
|
||||||
|
virtual ~CompressedBsaArchive() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Bsa::CompressedBSAFile> mCompressedFile;
|
||||||
|
std::vector<CompressedBsaArchiveFile> mCompressedResources;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,7 +23,11 @@ namespace VFS
|
||||||
// Last BSA has the highest priority
|
// Last BSA has the highest priority
|
||||||
const std::string archivePath = collections.getPath(*archive).string();
|
const std::string archivePath = collections.getPath(*archive).string();
|
||||||
Log(Debug::Info) << "Adding BSA archive " << archivePath;
|
Log(Debug::Info) << "Adding BSA archive " << archivePath;
|
||||||
|
Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(archivePath);
|
||||||
|
|
||||||
|
if (bsaVersion == Bsa::BSAVER_COMPRESSED)
|
||||||
|
vfs->addArchive(new CompressedBsaArchive(archivePath));
|
||||||
|
else
|
||||||
vfs->addArchive(new BsaArchive(archivePath));
|
vfs->addArchive(new BsaArchive(archivePath));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue