1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Working Extractor, DefSplitter and pcx convertor

This commit is contained in:
krs 2022-11-08 23:39:56 +02:00
parent 3b072b80d5
commit 93cf2682f3
8 changed files with 241 additions and 6 deletions

View File

@ -59,6 +59,7 @@
#include "../lib/serializer/Connection.h"
#include "CServerHandler.h"
#include "gui/NotificationHandler.h"
#include "resourceExtractor/ResourceConverter.h"
#include <boost/asio.hpp>
@ -253,6 +254,7 @@ int main(int argc, char * argv[])
// Init filesystem and settings
preinitDLL(::console);
settings.init();
Settings session = settings.write["session"];
auto setSettingBool = [](std::string key, std::string arg) {
@ -464,6 +466,8 @@ int main(int argc, char * argv[])
CCS->curh = new CCursorHandler();
graphics = new Graphics(); // should be before curh->init()
ConvertOriginalResourceFiles();
CCS->curh->initCursor();
logGlobal->info("Screen handler: %d ms", pomtime.getDiff());
pomtime.getDiff();

View File

@ -54,6 +54,8 @@ set(client_SRCS
lobby/OptionsTab.cpp
lobby/RandomMapTab.cpp
lobby/SelectionTab.cpp
resourceExtractor/ResourceConverter.cpp
CBitmapHandler.cpp
CreatureCostBox.cpp
@ -128,6 +130,8 @@ set(client_HEADERS
lobby/OptionsTab.h
lobby/RandomMapTab.h
lobby/SelectionTab.h
resourceExtractor/ResourceConverter.h
CBitmapHandler.h
CreatureCostBox.h

View File

@ -951,7 +951,7 @@ void CAnimation::initFromJson(const JsonNode & config)
}
}
void CAnimation::exportBitmaps(const boost::filesystem::path& path) const
void CAnimation::exportBitmaps(const boost::filesystem::path& path, bool prependResourceName) const
{
if(images.empty())
{
@ -959,7 +959,7 @@ void CAnimation::exportBitmaps(const boost::filesystem::path& path) const
return;
}
boost::filesystem::path actualPath = path / "SPRITES" / name;
boost::filesystem::path actualPath = path / "Sprites" / name;
boost::filesystem::create_directories(actualPath);
size_t counter = 0;
@ -974,9 +974,13 @@ void CAnimation::exportBitmaps(const boost::filesystem::path& path) const
const auto img = imagePair.second;
boost::format fmt("%d_%d.bmp");
fmt % group % frame;
fmt% group% frame;
std::string fileName = fmt.str();
if (prependResourceName)
fileName = name + "_" + fileName;
img->exportBitmap(actualPath / fileName);
img->exportBitmap(actualPath / fmt.str());
counter++;
}
}

View File

@ -122,7 +122,7 @@ public:
std::shared_ptr<IImage> getImage(size_t frame, size_t group=0, bool verbose=true) const;
void exportBitmaps(const boost::filesystem::path & path) const;
void exportBitmaps(const boost::filesystem::path & path, bool prependResourceName = false) const;
//all available frames
void load ();

View File

@ -0,0 +1,126 @@
#include "StdInc.h"
#include "ResourceConverter.h"
#include "../lib/JsonNode.h"
#include "../lib/VCMIDirs.h"
#include "../lib/filesystem/Filesystem.h"
#include "SDL.h"
#include "./gui/CAnimation.h"
#include "CBitmapHandler.h"
#include "boost/filesystem/path.hpp"
#include "boost/locale.hpp"
namespace bfs = boost::filesystem;
bool split_def_files = 1;
bool convert_pcx_to_bmp = 1; // converts Images from .pcx to bmp. Can be used when you have .pcx converted already
bool delete_source_files = 1; // delete source files or leave a copy in place.
// converts all pcx files into bmp (H3 saves images as .pcx)
void convertPcxToBmp()
{
bfs::path extractedPath = VCMIDirs::get().userDataPath() / "extracted";
bfs::path imagesPath = extractedPath / "Images";
bfs::directory_iterator end_iter;
for ( bfs::directory_iterator dir_itr(imagesPath); dir_itr != end_iter; ++dir_itr )
{
try
{
if ( bfs::is_regular_file( dir_itr->status() ) )
{
std::string filename = dir_itr->path().filename().string();
filename = boost::locale::to_lower(filename);
if(filename.find(".pcx") != std::string::npos)
{
SDL_Surface *bitmap;
bitmap = BitmapHandler::loadBitmap(filename);
if(delete_source_files)
bfs::remove(imagesPath / filename);
bfs::path outFilePath = imagesPath / filename;
outFilePath.replace_extension(".bmp");
SDL_SaveBMP(bitmap, outFilePath.string().c_str());
}
}
else
{
logGlobal->info(dir_itr->path().filename().string() + " [other]\n");
}
}
catch ( const std::exception & ex )
{
logGlobal->info(dir_itr->path().filename().string() + " " + ex.what() + "\n");
}
}
}
// splits a def file into individual parts
void splitDefFile(std::string fileName, bfs::path spritesPath)
{
if (CResourceHandler::get()->existsResource(ResourceID("SPRITES/" + fileName)))
{
std::string URI = fileName;
std::unique_ptr<CAnimation> anim = make_unique<CAnimation>(URI);
anim->preload();
anim->exportBitmaps(VCMIDirs::get().userCachePath() / "extracted", true);
if(delete_source_files)
bfs::remove(spritesPath / fileName);
}
else
logGlobal->error("Def File Split error! " + fileName);
}
// split def files, this way faction resources are independent
void splitDefFiles()
{
bfs::path extractedPath = VCMIDirs::get().userDataPath() / "extracted";
bfs::path spritesPath = extractedPath / "Sprites";
splitDefFile("TwCrPort.def", spritesPath); // split town creature portraits
splitDefFile("CPRSMALL.def", spritesPath); // split hero army creature portraits
splitDefFile("FlagPort.def", spritesPath); // adventure map dwellings
splitDefFile("ITPA.def", spritesPath); // small town icons
splitDefFile("ITPt.def", spritesPath); // big town icons
splitDefFile("Un32.def", spritesPath); // big town icons
splitDefFile("Un44.def", spritesPath); // big town icons
}
// Splits def files that are shared between factions and converts pcx to bmp
void ConvertOriginalResourceFiles()
{
if (split_def_files)
splitDefFiles();
if (convert_pcx_to_bmp)
convertPcxToBmp();
}

View File

@ -0,0 +1,13 @@
#pragma once
/*
* VCMI_Lib.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
void ConvertOriginalResourceFiles();

View File

@ -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

View File

@ -64,6 +64,10 @@ public:
std::string getMountPoint() const override;
void updateFilteredFiles(std::function<bool(const std::string &)> filter) const override {}
std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
/** Extracts one archive entry to the specified subfolder. Used for Video and Sound */
void extractToFolder(std::string outputSubFolder, CFileInputStream & fileStream, ArchiveEntry entry);
/** Extracts one archive entry to the specified subfolder. Used for Images, Sprites, etc */
void extractToFolder(std::string outputSubFolder, const std::string &mountPoint, ArchiveEntry entry);
private:
/**
@ -96,4 +100,7 @@ private:
std::unordered_map<ResourceID, ArchiveEntry> entries;
};
/** Constructs the file path for the extracted file. Creates the subfolder hierarchy aswell **/
boost::filesystem::path createExtractedFilePath(std::string outputSubFolder, std::string entryName);
VCMI_LIB_NAMESPACE_END