feat: QOS (007: Quantum of Solace) support (#894)

* feat: QOS (007: Quantum of Solace) support

* feat: add qos localize loader

* feat: add qos stringtable loader

* chore: comment about official zones

* fix: add qos gfximage runtime fields

* chore: remove useless dev time comments

* fix: remove all `static_asserts`s from asset headers causing build fail on x64

* chore: change union ordering of qos `entryInternalData`

* chore: move qos asset type enum to qos.h

* fix: qos and t4 xsurface index buffer

* chore: implement qos MaterialInfo struct

* chore: adjust some gfxworld struct members

* chore: implement qos PhysPreset and PhysConstraints

* chore: fix and adjust slight inconsistencies with qos zone code

* chore: reorder qos ZoneCode.lua entries in order of asset type enum

* chore: remove asset types that are not actual asset types in zones

* chore: check common asset arrays with static_assert

* chore: rename qos assets

* chore: reorder qos in templates to be in alphabetical order

* chore: use function for CopyMipLevel in Dx9TextureLoader

* chore: use templates for qos MapEntsDumper

* chore: add missing braces in XModelToCommonConverter

* chore: add generic way to peek at zone data

* Qos does not use a classic ZoneHeader so code needs to be more generic

* fix: do not use raw_byte and raw_uint typedefs for qos

* fix: not being able to write clipmapmp

* chore: additional research on qos vertex property and stuff

---------

Co-authored-by: Jan Laupetin <[email protected]>
This commit is contained in:
mo
2026-08-05 00:32:23 +02:00
committed by GitHub
co-authored by Jan Laupetin
parent 5c0a7257fd
commit 9f49e0e31c
142 changed files with 6000 additions and 97 deletions
+2
View File
@@ -4,6 +4,7 @@
#include "IW4/AutoSearchPathsIW4.h"
#include "IW4/InfoString/InfoStringToStructConverter.h"
#include "IW5/AutoSearchPathsIW5.h"
#include "QOS/AutoSearchPathsQOS.h"
#include "T4/AutoSearchPathsT4.h"
#include "T5/AutoSearchPathsT5.h"
#include "T6/AutoSearchPathsT6.h"
@@ -76,6 +77,7 @@ AutoSearchPaths* AutoSearchPaths::GetForGame(GameId gameId)
new AutoSearchPathsIW3(),
new AutoSearchPathsIW4(),
new AutoSearchPathsIW5(),
new AutoSearchPathsQOS(),
new AutoSearchPathsT4(),
new AutoSearchPathsT5(),
new AutoSearchPathsT6(),
@@ -0,0 +1,22 @@
#include "AutoSearchPathsQOS.h"
const std::vector<std::string>& AutoSearchPathsQOS::RecognizedZoneDirs() const
{
static std::vector<std::string> recognizedZoneDirs = {
"zone",
"zone/english",
"zone/french",
"zone/german",
"zone/italian",
"zone/spanish",
};
return recognizedZoneDirs;
}
const std::vector<std::string>& AutoSearchPathsQOS::AdditionalSearchPaths() const
{
static std::vector<std::string> additionalSearchPaths = {
"main",
};
return additionalSearchPaths;
}
@@ -0,0 +1,10 @@
#pragma once
#include "Game/AutoSearchPaths.h"
class AutoSearchPathsQOS final : public AutoSearchPaths
{
protected:
[[nodiscard]] const std::vector<std::string>& RecognizedZoneDirs() const override;
[[nodiscard]] const std::vector<std::string>& AdditionalSearchPaths() const override;
};
@@ -0,0 +1,44 @@
#include "AssetLoaderLocalizeQOS.h"
#include "Localize/CommonLocalizeLoader.h"
using namespace QOS;
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 localize
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLoaderQOS(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<LocalizeLoader>(memory, searchPath, zone);
}
} // namespace localize
@@ -0,0 +1,14 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/QOS/QOS.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include "Zone/Zone.h"
#include <memory>
namespace localize
{
std::unique_ptr<AssetCreator<QOS::AssetLocalize>> CreateLoaderQOS(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace localize
+113
View File
@@ -0,0 +1,113 @@
#include "ObjLoaderQOS.h"
#include "Asset/GlobalAssetPoolsLoader.h"
#include "Game/QOS/AssetMarkerQOS.h"
#include "Game/QOS/QOS.h"
#include "Localize/AssetLoaderLocalizeQOS.h"
#include "RawFile/AssetLoaderRawFileQOS.h"
#include "StringTable/AssetLoaderStringTableQOS.h"
using namespace QOS;
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const
{
(void)searchPath;
(void)zone;
}
void ObjLoader::UnloadContainersOfZone(Zone& zone) const
{
(void)zone;
}
namespace
{
void ConfigureDefaultCreators(AssetCreatorCollection& collection, Zone& zone)
{
auto& memory = zone.Memory();
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetPhysPreset>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetPhysConstraints>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetDestructibleDef>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetXAnim>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetXModel>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetMaterial>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetTechniqueSet>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetImage>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetSound>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetSoundCurve>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetClipMapMp>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetComWorld>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetGameWorldSp>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetGameWorldMp>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetMapEnts>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetGfxWorld>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetLightDef>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetFont>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetMenuList>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetMenu>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetLocalize>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetWeapon>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetFx>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetImpactFx>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetRawFile>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetStringTable>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetXmlTree>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetSceneAnimation>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetCutscene>>(memory));
collection.AddDefaultAssetCreator(std::make_unique<DefaultAssetCreator<AssetCustomCamera>>(memory));
}
void ConfigureGlobalAssetPoolsLoaders(AssetCreatorCollection& collection, Zone& zone)
{
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetPhysPreset>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetPhysConstraints>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetDestructibleDef>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetXAnim>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetXModel>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetMaterial>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetTechniqueSet>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetImage>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetSound>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetSoundCurve>>(zone));
// collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetClipMapSp>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetClipMapMp>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetComWorld>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetGameWorldSp>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetGameWorldMp>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetMapEnts>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetGfxWorld>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetLightDef>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetFont>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetMenuList>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetMenu>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetLocalize>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetWeapon>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetFx>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetImpactFx>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetRawFile>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetStringTable>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetXmlTree>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetSceneAnimation>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetCutscene>>(zone));
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetCustomCamera>>(zone));
}
void ConfigureLoaders(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath)
{
auto& memory = zone.Memory();
collection.AddAssetCreator(localize::CreateLoaderQOS(memory, searchPath, zone));
collection.AddAssetCreator(raw_file::CreateLoaderQOS(memory, searchPath));
collection.AddAssetCreator(string_table::CreateLoaderQOS(memory, searchPath));
}
} // namespace
void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const
{
(void)gdt;
ConfigureDefaultCreators(collection, zone);
ConfigureLoaders(collection, zone, searchPath);
ConfigureGlobalAssetPoolsLoaders(collection, zone);
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "IObjLoader.h"
#include "SearchPath/ISearchPath.h"
namespace QOS
{
class ObjLoader final : public IObjLoader
{
public:
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
void UnloadContainersOfZone(Zone& zone) const override;
void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const override;
};
} // namespace QOS
@@ -0,0 +1,51 @@
#include "AssetLoaderRawFileQOS.h"
#include "Game/QOS/QOS.h"
using namespace QOS;
namespace
{
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();
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));
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace raw_file
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateLoaderQOS(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<RawFileLoader>(memory, searchPath);
}
} // namespace raw_file
@@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/QOS/QOS.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace raw_file
{
std::unique_ptr<AssetCreator<QOS::AssetRawFile>> CreateLoaderQOS(MemoryManager& memory, ISearchPath& searchPath);
} // namespace raw_file
@@ -0,0 +1,45 @@
#include "AssetLoaderStringTableQOS.h"
#include "Game/QOS/QOS.h"
#include "StringTable/StringTableLoader.h"
using namespace QOS;
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::StringTableLoaderV1<StringTable> loader;
auto* stringTable = loader.LoadFromStream(assetName, m_memory, *file.m_stream);
if (!stringTable)
return AssetCreationResult::Failure();
return AssetCreationResult::Success(context.AddAsset<AssetStringTable>(assetName, stringTable));
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace string_table
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateLoaderQOS(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<StringTableLoader>(memory, searchPath);
}
} // namespace string_table
@@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/QOS/QOS.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace string_table
{
std::unique_ptr<AssetCreator<QOS::AssetStringTable>> CreateLoaderQOS(MemoryManager& memory, ISearchPath& searchPath);
} // namespace string_table
+2
View File
@@ -3,6 +3,7 @@
#include "Game/IW3/ObjLoaderIW3.h"
#include "Game/IW4/ObjLoaderIW4.h"
#include "Game/IW5/ObjLoaderIW5.h"
#include "Game/QOS/ObjLoaderQOS.h"
#include "Game/T4/ObjLoaderT4.h"
#include "Game/T5/ObjLoaderT5.h"
#include "Game/T6/ObjLoaderT6.h"
@@ -15,6 +16,7 @@ const IObjLoader* IObjLoader::GetObjLoaderForGame(GameId game)
new IW3::ObjLoader(),
new IW4::ObjLoader(),
new IW5::ObjLoader(),
new QOS::ObjLoader(),
new T4::ObjLoader(),
new T5::ObjLoader(),
new T6::ObjLoader(),