Add IWD project type.

This commit is contained in:
JezuzLizard 2023-12-23 06:33:35 -08:00
parent 6ca9485b55
commit c4a527eb57
3 changed files with 162 additions and 2 deletions

View File

@ -9,6 +9,7 @@
#include "LinkerSearchPaths.h" #include "LinkerSearchPaths.h"
#include "ObjContainer/IPak/IPakWriter.h" #include "ObjContainer/IPak/IPakWriter.h"
#include "ObjContainer/IWD/IWD.h" #include "ObjContainer/IWD/IWD.h"
#include "ObjContainer/IWD/IWDWriter.h"
#include "ObjLoading.h" #include "ObjLoading.h"
#include "ObjWriting.h" #include "ObjWriting.h"
#include "SearchPath/SearchPaths.h" #include "SearchPath/SearchPaths.h"
@ -45,7 +46,7 @@ enum class ProjectType
NONE, NONE,
FASTFILE, FASTFILE,
IPAK, IPAK,
IWD,
MAX MAX
}; };
@ -53,7 +54,7 @@ constexpr const char* PROJECT_TYPE_NAMES[static_cast<unsigned>(ProjectType::MAX)
"none", "none",
"fastfile", "fastfile",
"ipak", "ipak",
}; "iwd"};
class LinkerImpl final : public Linker class LinkerImpl final : public Linker
{ {
@ -462,6 +463,32 @@ class LinkerImpl final : public Linker
return true; return true;
} }
bool BuildIWD(const std::string& projectName, const ZoneDefinition& zoneDefinition, SearchPaths& assetSearchPaths) const
{
const fs::path iwdFolderPath(m_args.GetOutputFolderPathForProject(projectName));
auto iwdFilePath(iwdFolderPath);
const auto iwdFileName = zoneDefinition.m_name + ".iwd";
iwdFilePath.append(iwdFileName);
fs::create_directories(iwdFolderPath);
const auto iwdWriter = IWDWriter::Create(iwdFilePath.string(), &assetSearchPaths);
for (const auto& assetEntry : zoneDefinition.m_assets)
{
iwdWriter->AddFile(assetEntry.m_asset_name);
}
if (!iwdWriter->Write())
{
std::cout << "Writing iwd failed." << std::endl;
return false;
}
std::cout << "Created iwd \"" << iwdFilePath.string() << "\"\n";
return true;
}
bool BuildReferencedTargets(const std::string& projectName, const std::string& targetName, const ZoneDefinition& zoneDefinition) bool BuildReferencedTargets(const std::string& projectName, const std::string& targetName, const ZoneDefinition& zoneDefinition)
{ {
return std::all_of(zoneDefinition.m_targets_to_build.begin(), return std::all_of(zoneDefinition.m_targets_to_build.begin(),
@ -512,6 +539,10 @@ class LinkerImpl final : public Linker
result = BuildIPak(projectName, *zoneDefinition, assetSearchPaths); result = BuildIPak(projectName, *zoneDefinition, assetSearchPaths);
break; break;
case ProjectType::IWD:
result = BuildIWD(projectName, *zoneDefinition, assetSearchPaths);
break;
default: default:
assert(false); assert(false);
result = false; result = false;

View File

@ -0,0 +1,105 @@
#include "IWDWriter.h"
#include <algorithm>
#include <iostream>
#include "../minizip/zip.h"
class IWDWriterImpl final : public IWDWriter
{
public:
explicit IWDWriterImpl(const std::string& iwdFileName, ISearchPath* assetSearchPath)
: m_filename(iwdFileName),
m_asset_search_path(assetSearchPath),
m_files(0)
{
m_zipfile = zipOpen(m_filename.c_str(), APPEND_STATUS_CREATE);
if (!m_zipfile)
{
throw std::runtime_error("Error creating IWD file: \"" + m_filename + "\"");
}
}
void AddFile(std::string fileName) override
{
m_files.emplace_back(std::move(fileName));
}
bool AddFileToArchive(const std::string& fileName, const std::unique_ptr<char []>& fileData, const size_t& fileSize)
{
zip_fileinfo zi = {};
if (zipOpenNewFileInZip(m_zipfile, fileName.c_str(), &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK)
{
zipClose(m_zipfile, NULL);
throw std::runtime_error( "Could not open new file in IWD \"" + fileName + "\"\n");
}
if (zipWriteInFileInZip(m_zipfile, fileData.get(), fileSize) != ZIP_OK)
{
zipClose(m_zipfile, NULL);
throw std::runtime_error("Could not write file data to IWD \"" + fileName + "\"\n");
}
if (zipCloseFileInZip(m_zipfile) != ZIP_OK)
{
zipClose(m_zipfile, NULL);
throw std::runtime_error("Could not close file in IWD \"" + fileName + "\"\n");
}
return true;
}
std::unique_ptr<char[]> ReadFileDataFromSearchPath(const std::string& fileName, size_t& fileSize) const
{
const auto openFile = m_asset_search_path->Open(fileName);
if (!openFile.IsOpen())
{
std::cerr << "Could not open file for writing to IWD \"" << fileName << "\"\n";
return nullptr;
}
fileSize = static_cast<size_t>(openFile.m_length);
auto fileData = std::make_unique<char[]>(fileSize);
openFile.m_stream->read(fileData.get(), fileSize);
return fileData;
}
bool WriteFileData(const std::string& fileName)
{
size_t fileSize;
const auto fileData = ReadFileDataFromSearchPath(fileName, fileSize);
if (!fileData)
return false;
AddFileToArchive(fileName, fileData, fileSize);
return true;
}
bool Write() override
{
const auto result = std::all_of(m_files.begin(),
m_files.end(),
[this](const std::string& fileName)
{
return WriteFileData(fileName);
});
zipClose(m_zipfile, NULL);
return result;
}
private:
const std::string m_filename;
ISearchPath* m_asset_search_path;
std::vector<std::string> m_files;
zipFile m_zipfile;
};
std::unique_ptr<IWDWriter> IWDWriter::Create(const std::string& iwdFileName, ISearchPath* assetSearchPath)
{
return std::make_unique<IWDWriterImpl>(iwdFileName, assetSearchPath);
}

View File

@ -0,0 +1,24 @@
#pragma once
#include "SearchPath/ISearchPath.h"
#include <memory>
#include <ostream>
class IWDWriter
{
public:
static constexpr auto USE_COMPRESSION = true;
IWDWriter() = default;
virtual ~IWDWriter() = default;
IWDWriter(const IWDWriter& other) = default;
IWDWriter(IWDWriter&& other) noexcept = default;
IWDWriter& operator=(const IWDWriter& other) = default;
IWDWriter& operator=(IWDWriter&& other) noexcept = default;
virtual void AddFile(std::string fileName) = 0;
virtual bool Write() = 0;
static std::unique_ptr<IWDWriter> Create(const std::string& iwdFileName, ISearchPath* assetSearchPath);
};