|
@@ -10,6 +10,7 @@
|
|
|
#include "StdInc.h"
|
|
|
#include "CArchiveLoader.h"
|
|
|
|
|
|
+#include "VCMIDirs.h"
|
|
|
#include "CFileInputStream.h"
|
|
|
#include "CCompressedStream.h"
|
|
|
|
|
@@ -17,13 +18,17 @@
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
|
|
+namespace bfs = boost::filesystem;
|
|
|
+
|
|
|
+const bool extractArchives = 1;
|
|
|
+
|
|
|
ArchiveEntry::ArchiveEntry()
|
|
|
: offset(0), fullSize(0), compressedSize(0)
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
-CArchiveLoader::CArchiveLoader(std::string _mountPoint, boost::filesystem::path _archive) :
|
|
|
+CArchiveLoader::CArchiveLoader(std::string _mountPoint, bfs::path _archive) :
|
|
|
archive(std::move(_archive)),
|
|
|
mountPoint(std::move(_mountPoint))
|
|
|
{
|
|
@@ -77,6 +82,28 @@ void CArchiveLoader::initLODArchive(const std::string &mountPoint, CFileInputStr
|
|
|
|
|
|
// Add lod entry to local entries map
|
|
|
entries[ResourceID(mountPoint + entry.name)] = entry;
|
|
|
+
|
|
|
+ if(extractArchives)
|
|
|
+ {
|
|
|
+ si64 currentPosition = fileStream.tell(); // save filestream position
|
|
|
+
|
|
|
+ boost::locale::generator gen;
|
|
|
+ std::locale::global(gen("")); // Create locale generator
|
|
|
+
|
|
|
+ std::string fName = filename;
|
|
|
+ boost::to_upper(fName);
|
|
|
+
|
|
|
+ if(fName.find(".PCX") != std::string::npos)
|
|
|
+ extractToFolder("Images", mountPoint, entry);
|
|
|
+ else if ((fName.find(".DEF") != std::string::npos ) || (fName.find(".MSK") != std::string::npos) || (fName.find(".FNT") != std::string::npos) || (fName.find(".PAL") != std::string::npos))
|
|
|
+ extractToFolder("Sprites", mountPoint, entry);
|
|
|
+ else if ((fName.find(".h3c") != std::string::npos))
|
|
|
+ extractToFolder("Sprites", mountPoint, entry);
|
|
|
+ else
|
|
|
+ extractToFolder("Misc", mountPoint, entry);
|
|
|
+
|
|
|
+ fileStream.seek(currentPosition); // restore filestream position
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -112,6 +139,9 @@ void CArchiveLoader::initVIDArchive(const std::string &mountPoint, CFileInputStr
|
|
|
auto it = offsets.find(entry.second.offset);
|
|
|
it++;
|
|
|
entry.second.fullSize = *it - entry.second.offset;
|
|
|
+
|
|
|
+ if(extractArchives)
|
|
|
+ extractToFolder("Video", fileStream, entry.second);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -139,6 +169,9 @@ void CArchiveLoader::initSNDArchive(const std::string &mountPoint, CFileInputStr
|
|
|
entry.fullSize = reader.readInt32();
|
|
|
entry.compressedSize = 0;
|
|
|
entries[ResourceID(mountPoint + entry.name)] = entry;
|
|
|
+
|
|
|
+ if(extractArchives)
|
|
|
+ extractToFolder("Sound", fileStream, entry);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -182,4 +215,48 @@ std::unordered_set<ResourceID> CArchiveLoader::getFilteredFiles(std::function<bo
|
|
|
return foundID;
|
|
|
}
|
|
|
|
|
|
+void CArchiveLoader::extractToFolder( std::string outputSubFolder, CFileInputStream& fileStream, ArchiveEntry entry)
|
|
|
+{
|
|
|
+ si64 currentPosition = fileStream.tell(); // save filestream position
|
|
|
+
|
|
|
+ std::unique_ptr<char[]> data = std::unique_ptr<char[]>(new char[entry.fullSize]);
|
|
|
+ fileStream.seek(entry.offset);
|
|
|
+ fileStream.read((ui8*)data.get(), entry.fullSize);
|
|
|
+
|
|
|
+ bfs::path extractedFilePath = createExtractedFilePath(outputSubFolder, entry.name);
|
|
|
+
|
|
|
+ // writeToOutputFile
|
|
|
+ std::ofstream out(extractedFilePath.string(), std::ofstream::binary);
|
|
|
+ out.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
|
|
+ out.write(data.get(), entry.fullSize);
|
|
|
+
|
|
|
+ fileStream.seek(currentPosition); // restore filestream position
|
|
|
+}
|
|
|
+
|
|
|
+void CArchiveLoader::extractToFolder( std::string outputSubFolder, const std::string& mountPoint, ArchiveEntry entry)
|
|
|
+{
|
|
|
+
|
|
|
+ std::unique_ptr<CInputStream> & inputStream = load(ResourceID(mountPoint + entry.name));
|
|
|
+
|
|
|
+ std::unique_ptr<char[]> data = std::unique_ptr<char[]>(new char[entry.fullSize]);
|
|
|
+ inputStream->read((ui8*)data.get(), entry.fullSize);
|
|
|
+
|
|
|
+ bfs::path extractedFilePath = createExtractedFilePath(outputSubFolder, entry.name);
|
|
|
+
|
|
|
+ // writeToOutputFile
|
|
|
+ std::ofstream out(extractedFilePath.string(), std::ofstream::binary);
|
|
|
+ out.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
|
|
+ out.write(data.get(), entry.fullSize);
|
|
|
+}
|
|
|
+
|
|
|
+bfs::path createExtractedFilePath(std::string outputSubFolder, std::string entryName)
|
|
|
+{
|
|
|
+ bfs::path extractionFolderPath = VCMIDirs::get().userCachePath() / "extracted" / outputSubFolder;
|
|
|
+ bfs::path extractedFilePath = extractionFolderPath / entryName;
|
|
|
+
|
|
|
+ bfs::create_directories(extractionFolderPath);
|
|
|
+
|
|
|
+ return extractedFilePath;
|
|
|
+}
|
|
|
+
|
|
|
VCMI_LIB_NAMESPACE_END
|