chore: fix loading and writing code for T5

This commit is contained in:
Jan 2024-12-28 23:51:57 +01:00
parent a36581b06e
commit d8bc156ffd
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
22 changed files with 263 additions and 317 deletions

View File

@ -1,116 +0,0 @@
#include "AssetLoaderRawFile.h"
#include "Game/T5/T5.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <filesystem>
#include <iostream>
#include <zlib.h>
using namespace T5;
namespace fs = std::filesystem;
void* AssetLoaderRawFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* rawFile = memory->Create<RawFile>();
memset(rawFile, 0, sizeof(RawFile));
rawFile->name = memory->Dup(assetName.c_str());
return rawFile;
}
bool AssetLoaderRawFile::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderRawFile::LoadGsc(
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
{
const auto uncompressedBuffer = std::make_unique<char[]>(static_cast<size_t>(file.m_length + 1));
file.m_stream->read(uncompressedBuffer.get(), file.m_length);
if (file.m_stream->gcount() != file.m_length)
return false;
uncompressedBuffer[static_cast<size_t>(file.m_length)] = '\0';
const auto compressionBufferSize = static_cast<size_t>(file.m_length + 1 + sizeof(uint32_t) + sizeof(uint32_t) + COMPRESSED_BUFFER_SIZE_PADDING);
auto* compressedBuffer = memory->Alloc<char>(compressionBufferSize);
z_stream_s zs{};
zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
zs.avail_in = static_cast<uInt>(file.m_length + 1);
zs.avail_out = compressionBufferSize;
zs.next_in = reinterpret_cast<const Bytef*>(uncompressedBuffer.get());
zs.next_out = reinterpret_cast<Bytef*>(&compressedBuffer[sizeof(uint32_t) + sizeof(uint32_t)]);
int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK)
{
throw std::runtime_error("Initializing deflate failed");
}
ret = deflate(&zs, Z_FINISH);
if (ret != Z_STREAM_END)
{
std::cerr << "Deflate failed for loading gsc file \"" << assetName << "\"\n";
deflateEnd(&zs);
return false;
}
const auto compressedSize = compressionBufferSize - zs.avail_out;
reinterpret_cast<uint32_t*>(compressedBuffer)[0] = static_cast<uint32_t>(file.m_length + 1); // outLen
reinterpret_cast<uint32_t*>(compressedBuffer)[1] = compressedSize; // inLen
auto* rawFile = memory->Create<RawFile>();
rawFile->name = memory->Dup(assetName.c_str());
rawFile->len = static_cast<int>(compressedSize + sizeof(uint32_t) + sizeof(uint32_t));
rawFile->buffer = static_cast<const char*>(compressedBuffer);
deflateEnd(&zs);
manager->AddAsset<AssetRawFile>(assetName, rawFile);
return true;
}
bool AssetLoaderRawFile::LoadDefault(
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
{
auto* rawFile = memory->Create<RawFile>();
rawFile->name = memory->Dup(assetName.c_str());
rawFile->len = static_cast<int>(file.m_length);
auto* fileBuffer = memory->Alloc<char>(static_cast<size_t>(file.m_length + 1));
file.m_stream->read(fileBuffer, file.m_length);
if (file.m_stream->gcount() != file.m_length)
return false;
fileBuffer[rawFile->len] = '\0';
rawFile->buffer = fileBuffer;
manager->AddAsset<AssetRawFile>(assetName, rawFile);
return true;
}
bool AssetLoaderRawFile::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
const fs::path rawFilePath(assetName);
const auto extension = rawFilePath.extension().string();
if (extension == ".gsc" || extension == ".csc")
return LoadGsc(file, assetName, searchPath, memory, manager);
return LoadDefault(file, assetName, searchPath, memory, manager);
}

View File

@ -1,24 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T5/T5.h"
#include "SearchPath/ISearchPath.h"
namespace T5
{
class AssetLoaderRawFile final : public BasicAssetLoader<AssetRawFile>
{
static constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64;
static bool LoadGsc(
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager);
static bool LoadDefault(
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T5

View File

@ -1,39 +0,0 @@
#include "AssetLoaderStringTable.h"
#include "Csv/CsvStream.h"
#include "Game/T5/CommonT5.h"
#include "Game/T5/T5.h"
#include "Pool/GlobalAssetPool.h"
#include "StringTable/StringTableLoader.h"
#include <cstring>
using namespace T5;
void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* stringTable = memory->Create<StringTable>();
memset(stringTable, 0, sizeof(StringTable));
stringTable->name = memory->Dup(assetName.c_str());
return stringTable;
}
bool AssetLoaderStringTable::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderStringTable::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
string_table::StringTableLoaderV3<StringTable, Common::Com_HashString> loader;
auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream);
manager->AddAsset<AssetStringTable>(assetName, stringTable);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T5/T5.h"
#include "SearchPath/ISearchPath.h"
namespace T5
{
class AssetLoaderStringTable final : public BasicAssetLoader<AssetStringTable>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T5

View File

@ -1,47 +0,0 @@
#include "AssetLoaderXModel.h"
#include "Game/T5/T5.h"
#include "Game/T5/XModel/XModelLoaderT5.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace T5;
void* AssetLoaderXModel::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetXModel::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderXModel::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderXModel::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(std::format("xmodel/{}.json", assetName));
if (!file.IsOpen())
return false;
auto* xmodel = memory->Alloc<XModel>();
xmodel->name = memory->Dup(assetName.c_str());
std::vector<XAssetInfoGeneric*> dependencies;
if (LoadXModel(*file.m_stream, *xmodel, memory, manager, dependencies))
{
manager->AddAsset<AssetXModel>(assetName, xmodel, std::move(dependencies));
}
else
{
std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName);
return false;
}
return true;
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T5/T5.h"
#include "SearchPath/ISearchPath.h"
namespace T5
{
class AssetLoaderXModel final : public BasicAssetLoader<AssetXModel>
{
static std::string GetFileNameForAsset(const std::string& assetName);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T5

View File

@ -1,23 +0,0 @@
#include "AssetLoaderLocalizeT5.h"
using namespace T5;
AssetLoaderLocalize::AssetLoaderLocalize(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: CommonLocalizeLoader(searchPath, zone),
m_memory(memory)
{
}
AssetCreationResult AssetLoaderLocalize::CreateAsset(const std::string& assetName, AssetCreationContext& context)
{
return CreateLocalizeAsset(assetName, context);
}
AssetCreationResult AssetLoaderLocalize::CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context)
{
auto* asset = m_memory.Alloc<LocalizeEntry>();
asset->name = m_memory.Dup(localizeEntry.m_key.c_str());
asset->value = m_memory.Dup(localizeEntry.m_value.c_str());
return AssetCreationResult::Success(context.AddAsset<AssetLocalize>(localizeEntry.m_key, asset));
}

View File

@ -1,25 +0,0 @@
#pragma once
#include "Asset/AssetCreationContext.h"
#include "Asset/IAssetCreator.h"
#include "Game/T5/T5.h"
#include "Localize/CommonLocalizeLoader.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include "Zone/Zone.h"
namespace T5
{
class AssetLoaderLocalize final : public AssetCreator<AssetLocalize>, public CommonLocalizeLoader
{
public:
AssetLoaderLocalize(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override;
protected:
AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) override;
private:
MemoryManager& m_memory;
};
} // namespace T5

View File

@ -0,0 +1,44 @@
#include "LoaderLocalizeT5.h"
#include "Localize/CommonLocalizeLoader.h"
using namespace T5;
namespace
{
class LocalizeLoader final : public AssetCreator<AssetLocalize>, public CommonLocalizeLoader
{
public:
LocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: CommonLocalizeLoader(searchPath, zone),
m_memory(memory)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
return CreateLocalizeAsset(assetName, context);
}
protected:
AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) override
{
auto* asset = m_memory.Alloc<LocalizeEntry>();
asset->name = m_memory.Dup(localizeEntry.m_key.c_str());
asset->value = m_memory.Dup(localizeEntry.m_value.c_str());
return AssetCreationResult::Success(context.AddAsset<AssetLocalize>(localizeEntry.m_key, asset));
}
private:
MemoryManager& m_memory;
};
} // namespace
namespace T5
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<LocalizeLoader>(memory, searchPath, zone);
}
} // namespace T5

View File

@ -0,0 +1,14 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/T5/T5.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include "Zone/Zone.h"
#include <memory>
namespace T5
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace T5

View File

@ -3,8 +3,11 @@
#include "Asset/GlobalAssetPoolsLoader.h"
#include "Game/T5/GameT5.h"
#include "Game/T5/T5.h"
#include "Localize/AssetLoaderLocalizeT5.h"
#include "Game/T5/XModel/LoaderXModelT5.h"
#include "Localize/LoaderLocalizeT5.h"
#include "ObjLoading.h"
#include "RawFile/LoaderRawFileT5.h"
#include "StringTable/LoaderStringTableT5.h"
#include <memory>
@ -100,7 +103,7 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderPhysConstraints>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderDestructibleDef>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXModel>(memory));
collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMaterial>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImage>(memory));
@ -117,13 +120,13 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderFont>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenuList>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenu>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderLocalize>(memory));
collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderWeapon>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundDriverGlobals>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFx>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImpactFx>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderRawFile>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderStringTable>(memory));
collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath));
collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderPackIndex>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXGlobals>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderDDL>(memory));
@ -132,7 +135,7 @@ namespace
}
} // namespace
void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) const
void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const
{
ConfigureDefaultCreators(collection, zone);
ConfigureLoaders(collection, zone, searchPath);

View File

@ -12,6 +12,6 @@ namespace T5
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
void UnloadContainersOfZone(Zone& zone) const override;
void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) const override;
void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const override;
};
} // namespace T5

View File

@ -0,0 +1,123 @@
#include "LoaderRawFileT5.h"
#include "Game/T5/T5.h"
#include <cstring>
#include <filesystem>
#include <format>
#include <iostream>
#include <zlib.h>
using namespace T5;
namespace fs = std::filesystem;
namespace
{
constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64;
class RawFileLoader final : public AssetCreator<AssetRawFile>
{
public:
RawFileLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(assetName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
const fs::path rawFilePath(assetName);
const auto extension = rawFilePath.extension().string();
if (extension == ".gsc" || extension == ".csc")
return LoadGsc(file, assetName, context);
return LoadDefault(file, assetName, context);
}
private:
AssetCreationResult LoadGsc(const SearchPathOpenFile& file, const std::string& assetName, AssetCreationContext& context)
{
const auto uncompressedBuffer = std::make_unique<char[]>(static_cast<size_t>(file.m_length + 1));
file.m_stream->read(uncompressedBuffer.get(), file.m_length);
if (file.m_stream->gcount() != file.m_length)
return AssetCreationResult::Failure();
uncompressedBuffer[static_cast<size_t>(file.m_length)] = '\0';
const auto compressionBufferSize = static_cast<size_t>(file.m_length + 1 + sizeof(uint32_t) + sizeof(uint32_t) + COMPRESSED_BUFFER_SIZE_PADDING);
auto* compressedBuffer = m_memory.Alloc<char>(compressionBufferSize);
z_stream_s zs{};
zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
zs.avail_in = static_cast<uInt>(file.m_length + 1);
zs.avail_out = compressionBufferSize;
zs.next_in = reinterpret_cast<const Bytef*>(uncompressedBuffer.get());
zs.next_out = reinterpret_cast<Bytef*>(&compressedBuffer[sizeof(uint32_t) + sizeof(uint32_t)]);
int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK)
throw std::runtime_error("Initializing deflate failed");
ret = deflate(&zs, Z_FINISH);
if (ret != Z_STREAM_END)
{
std::cerr << std::format("Deflate failed for loading gsc file \"{}\"\n", assetName);
deflateEnd(&zs);
return AssetCreationResult::Failure();
}
const auto compressedSize = compressionBufferSize - zs.avail_out;
reinterpret_cast<uint32_t*>(compressedBuffer)[0] = static_cast<uint32_t>(file.m_length + 1); // outLen
reinterpret_cast<uint32_t*>(compressedBuffer)[1] = compressedSize; // inLen
auto* rawFile = m_memory.Alloc<RawFile>();
rawFile->name = m_memory.Dup(assetName.c_str());
rawFile->len = static_cast<int>(compressedSize + sizeof(uint32_t) + sizeof(uint32_t));
rawFile->buffer = static_cast<const char*>(compressedBuffer);
deflateEnd(&zs);
return AssetCreationResult::Success(context.AddAsset<AssetRawFile>(assetName, rawFile));
}
AssetCreationResult LoadDefault(const SearchPathOpenFile& file, const std::string& assetName, AssetCreationContext& context)
{
auto* rawFile = m_memory.Alloc<RawFile>();
rawFile->name = m_memory.Dup(assetName.c_str());
rawFile->len = static_cast<int>(file.m_length);
auto* fileBuffer = m_memory.Alloc<char>(static_cast<size_t>(file.m_length + 1));
file.m_stream->read(fileBuffer, file.m_length);
if (file.m_stream->gcount() != file.m_length)
return AssetCreationResult::Failure();
fileBuffer[rawFile->len] = '\0';
rawFile->buffer = fileBuffer;
return AssetCreationResult::Success(context.AddAsset<AssetRawFile>(assetName, rawFile));
}
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace T5
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<RawFileLoader>(memory, searchPath);
}
} // namespace T5

View File

@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/T5/T5.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace T5
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace T5

View File

@ -0,0 +1,46 @@
#include "LoaderStringTableT5.h"
#include "Game/T5/CommonT5.h"
#include "Game/T5/T5.h"
#include "StringTable/StringTableLoader.h"
#include <cstring>
using namespace T5;
namespace
{
class StringTableLoader final : public AssetCreator<AssetStringTable>
{
public:
StringTableLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(assetName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
string_table::StringTableLoaderV3<StringTable, Common::Com_HashString> loader;
auto* stringTable = loader.LoadFromStream(assetName, m_memory, *file.m_stream);
return AssetCreationResult::Success(context.AddAsset<AssetStringTable>(assetName, stringTable));
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace T5
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<StringTableLoader>(memory, searchPath);
}
} // namespace T5

View File

@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/T5/T5.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace T5
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace T5