mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-31 16:36:41 +00:00
Use the right archive type to load bsa according to their type
This commit is contained in:
parent
974799c011
commit
d30deef4b5
4 changed files with 91 additions and 161 deletions
|
@ -48,12 +48,14 @@ std::unique_ptr<VFS::Archive> makeBsaArchive(const std::filesystem::path& path)
|
||||||
case Bsa::BSAVER_UNKNOWN:
|
case Bsa::BSAVER_UNKNOWN:
|
||||||
std::cerr << '"' << path << "\" is unknown BSA archive" << std::endl;
|
std::cerr << '"' << path << "\" is unknown BSA archive" << std::endl;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case Bsa::BSAVER_UNCOMPRESSED:
|
|
||||||
return std::make_unique<VFS::BsaArchive>(path);
|
|
||||||
case Bsa::BSAVER_COMPRESSED:
|
case Bsa::BSAVER_COMPRESSED:
|
||||||
|
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_COMPRESSED>::type>(path);
|
||||||
case Bsa::BSAVER_BA2_GNRL:
|
case Bsa::BSAVER_BA2_GNRL:
|
||||||
|
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_BA2_GNRL>::type>(path);
|
||||||
case Bsa::BSAVER_BA2_DX10:
|
case Bsa::BSAVER_BA2_DX10:
|
||||||
return std::make_unique<VFS::CompressedBsaArchive>(path);
|
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_BA2_DX10>::type>(path);
|
||||||
|
case Bsa::BSAVER_UNCOMPRESSED:
|
||||||
|
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_UNCOMPRESSED>::type>(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << '"' << path << "\" is unsupported BSA archive" << std::endl;
|
std::cerr << '"' << path << "\" is unsupported BSA archive" << std::endl;
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
#include "bsaarchive.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace VFS
|
|
||||||
{
|
|
||||||
|
|
||||||
BsaArchive::BsaArchive(const std::filesystem::path& filename)
|
|
||||||
{
|
|
||||||
mFile = std::make_unique<Bsa::BSAFile>();
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BsaArchive::BsaArchive() {}
|
|
||||||
|
|
||||||
BsaArchive::~BsaArchive() {}
|
|
||||||
|
|
||||||
void BsaArchive::listResources(std::map<std::string, File*>& out, char (*normalize_function)(char))
|
|
||||||
{
|
|
||||||
for (std::vector<BsaArchiveFile>::iterator it = mResources.begin(); it != mResources.end(); ++it)
|
|
||||||
{
|
|
||||||
std::string ent = it->mInfo->name();
|
|
||||||
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
|
|
||||||
|
|
||||||
out[ent] = &*it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BsaArchive::contains(const std::string& file, char (*normalize_function)(char)) const
|
|
||||||
{
|
|
||||||
for (const auto& it : mResources)
|
|
||||||
{
|
|
||||||
std::string ent = it.mInfo->name();
|
|
||||||
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
|
|
||||||
if (file == ent)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string BsaArchive::getDescription() const
|
|
||||||
{
|
|
||||||
return std::string{ "BSA: " } + mFile->getFilename();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
BsaArchiveFile::BsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::BSAFile* bsa)
|
|
||||||
: mInfo(info)
|
|
||||||
, mFile(bsa)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Files::IStreamPtr BsaArchiveFile::open()
|
|
||||||
{
|
|
||||||
return mFile->getFile(mInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
CompressedBsaArchive::CompressedBsaArchive(const std::filesystem::path& filename)
|
|
||||||
: Archive()
|
|
||||||
{
|
|
||||||
mCompressedFile = std::make_unique<Bsa::CompressedBSAFile>();
|
|
||||||
mCompressedFile->open(filename);
|
|
||||||
|
|
||||||
const Bsa::BSAFile::FileList& filelist = mCompressedFile->getList();
|
|
||||||
for (Bsa::BSAFile::FileList::const_iterator it = filelist.begin(); it != filelist.end(); ++it)
|
|
||||||
{
|
|
||||||
mCompressedResources.emplace_back(&*it, mCompressedFile.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CompressedBsaArchive::contains(const std::string& file, char (*normalize_function)(char)) const
|
|
||||||
{
|
|
||||||
for (const auto& it : mCompressedResources)
|
|
||||||
{
|
|
||||||
std::string ent = it.mInfo->name();
|
|
||||||
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
|
|
||||||
if (file == ent)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CompressedBsaArchive::getDescription() const
|
|
||||||
{
|
|
||||||
return std::string{ "BSA: " } + mCompressedFile->getFilename();
|
|
||||||
}
|
|
||||||
|
|
||||||
CompressedBsaArchiveFile::CompressedBsaArchiveFile(
|
|
||||||
const Bsa::BSAFile::FileStruct* info, Bsa::CompressedBSAFile* bsa)
|
|
||||||
: mInfo(info)
|
|
||||||
, mCompressedFile(bsa)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Files::IStreamPtr CompressedBsaArchiveFile::open()
|
|
||||||
{
|
|
||||||
return mCompressedFile->getFile(mInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,66 +3,108 @@
|
||||||
|
|
||||||
#include "archive.hpp"
|
#include "archive.hpp"
|
||||||
|
|
||||||
|
#include <components/bsa/ba2dx10file.hpp>
|
||||||
|
#include <components/bsa/ba2gnrlfile.hpp>
|
||||||
#include <components/bsa/bsa_file.hpp>
|
#include <components/bsa/bsa_file.hpp>
|
||||||
#include <components/bsa/compressedbsafile.hpp>
|
#include <components/bsa/compressedbsafile.hpp>
|
||||||
|
|
||||||
namespace VFS
|
namespace VFS
|
||||||
{
|
{
|
||||||
|
template <typename FileType>
|
||||||
class BsaArchiveFile : public File
|
class BsaArchiveFile : public File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::BSAFile* bsa);
|
BsaArchiveFile(const Bsa::BSAFile::FileStruct* info, FileType* bsa)
|
||||||
|
: mInfo(info)
|
||||||
|
, mFile(bsa)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Files::IStreamPtr open() override;
|
Files::IStreamPtr open() override { return mFile->getFile(mInfo); }
|
||||||
|
|
||||||
std::filesystem::path getPath() override { return mInfo->name(); }
|
std::filesystem::path getPath() override { return mInfo->name(); }
|
||||||
|
|
||||||
const Bsa::BSAFile::FileStruct* mInfo;
|
const Bsa::BSAFile::FileStruct* mInfo;
|
||||||
Bsa::BSAFile* mFile;
|
FileType* mFile;
|
||||||
};
|
|
||||||
|
|
||||||
class CompressedBsaArchiveFile : public File
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CompressedBsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::CompressedBSAFile* bsa);
|
|
||||||
|
|
||||||
Files::IStreamPtr open() override;
|
|
||||||
|
|
||||||
std::filesystem::path getPath() override { return mInfo->name(); }
|
|
||||||
|
|
||||||
const Bsa::BSAFile::FileStruct* mInfo;
|
|
||||||
Bsa::CompressedBSAFile* mCompressedFile;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename BSAFileType>
|
||||||
class BsaArchive : public Archive
|
class BsaArchive : public Archive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BsaArchive(const std::filesystem::path& filename);
|
BsaArchive(const std::filesystem::path& filename)
|
||||||
BsaArchive();
|
: Archive()
|
||||||
virtual ~BsaArchive();
|
{
|
||||||
void listResources(std::map<std::string, File*>& out, char (*normalize_function)(char)) override;
|
mFile = std::make_unique<BSAFileType>();
|
||||||
bool contains(const std::string& file, char (*normalize_function)(char)) const override;
|
mFile->open(filename);
|
||||||
std::string getDescription() const override;
|
|
||||||
|
|
||||||
protected:
|
const Bsa::BSAFile::FileList& filelist = mFile->getList();
|
||||||
std::unique_ptr<Bsa::BSAFile> mFile;
|
for (Bsa::BSAFile::FileList::const_iterator it = filelist.begin(); it != filelist.end(); ++it)
|
||||||
std::vector<BsaArchiveFile> mResources;
|
{
|
||||||
};
|
mResources.emplace_back(&*it, mFile.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CompressedBsaArchive : public Archive
|
virtual ~BsaArchive() {}
|
||||||
{
|
|
||||||
public:
|
void listResources(std::map<std::string, File*>& out, char (*normalize_function)(char)) override
|
||||||
CompressedBsaArchive(const std::filesystem::path& filename);
|
{
|
||||||
virtual ~CompressedBsaArchive() {}
|
for (auto& resource : mResources)
|
||||||
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;
|
std::string ent = resource.mInfo->name();
|
||||||
std::string getDescription() const override;
|
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
|
||||||
|
|
||||||
|
out[ent] = &resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const std::string& file, char (*normalize_function)(char)) const override
|
||||||
|
{
|
||||||
|
for (const auto& it : mResources)
|
||||||
|
{
|
||||||
|
std::string ent = it.mInfo->name();
|
||||||
|
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
|
||||||
|
if (file == ent)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getDescription() const override { return std::string{ "BSA: " } + mFile->getFilename(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Bsa::CompressedBSAFile> mCompressedFile;
|
std::unique_ptr<BSAFileType> mFile;
|
||||||
std::vector<CompressedBsaArchiveFile> mCompressedResources;
|
std::vector<BsaArchiveFile<BSAFileType>> mResources;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <Bsa::BsaVersion>
|
||||||
|
struct ArchiveSelector
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ArchiveSelector<Bsa::BSAVER_UNCOMPRESSED>
|
||||||
|
{
|
||||||
|
using type = BsaArchive<Bsa::BSAFile>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ArchiveSelector<Bsa::BSAVER_COMPRESSED>
|
||||||
|
{
|
||||||
|
using type = BsaArchive<Bsa::CompressedBSAFile>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ArchiveSelector<Bsa::BSAVER_BA2_GNRL>
|
||||||
|
{
|
||||||
|
using type = BsaArchive<Bsa::BA2GNRLFile>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ArchiveSelector<Bsa::BSAVER_BA2_DX10>
|
||||||
|
{
|
||||||
|
using type = BsaArchive<Bsa::BA2DX10File>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,9 +28,15 @@ namespace VFS
|
||||||
Bsa::BsaVersion bsaVersion = Bsa::BSAFile::detectVersion(archivePath);
|
Bsa::BsaVersion bsaVersion = Bsa::BSAFile::detectVersion(archivePath);
|
||||||
|
|
||||||
if (bsaVersion == Bsa::BSAVER_COMPRESSED)
|
if (bsaVersion == Bsa::BSAVER_COMPRESSED)
|
||||||
vfs->addArchive(std::make_unique<CompressedBsaArchive>(archivePath));
|
vfs->addArchive(std::make_unique<ArchiveSelector<Bsa::BSAVER_COMPRESSED>::type>(archivePath));
|
||||||
|
else if (bsaVersion == Bsa::BSAVER_BA2_GNRL)
|
||||||
|
vfs->addArchive(std::make_unique<ArchiveSelector<Bsa::BSAVER_BA2_GNRL>::type>(archivePath));
|
||||||
|
else if (bsaVersion == Bsa::BSAVER_BA2_DX10)
|
||||||
|
vfs->addArchive(std::make_unique<ArchiveSelector<Bsa::BSAVER_BA2_DX10>::type>(archivePath));
|
||||||
|
else if (bsaVersion == Bsa::BSAVER_UNCOMPRESSED)
|
||||||
|
vfs->addArchive(std::make_unique<ArchiveSelector<Bsa::BSAVER_UNCOMPRESSED>::type>(archivePath));
|
||||||
else
|
else
|
||||||
vfs->addArchive(std::make_unique<BsaArchive>(archivePath));
|
throw std::runtime_error("Unknown archive type '" + *archive + "'");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue