Dump CommonStructuredDataDefSet instead of the game's internal structures

This commit is contained in:
Jan
2022-03-19 23:39:50 +01:00
parent c38367d55b
commit b2140260a4
11 changed files with 339 additions and 19 deletions

View File

@ -5,6 +5,7 @@
#include <algorithm>
#include "Dumping/StructuredDataDef/StructuredDataDefDumper.h"
#include "StructuredDataDef/StructuredDataDefDumper.h"
using namespace IW4;
using namespace std::string_literals;
@ -343,6 +344,161 @@ void AssetDumperStructuredDataDefSet::DumpStruct(StructuredDataDefDumper& dumper
dumper.EndStruct();
}
CommonStructuredDataType AssetDumperStructuredDataDefSet::ConvertType(const CommonStructuredDataDef* def, const StructuredDataType in)
{
CommonStructuredDataType out;
switch (in.type)
{
case DATA_INT:
out.m_category = CommonStructuredDataTypeCategory::INT;
break;
case DATA_BYTE:
out.m_category = CommonStructuredDataTypeCategory::BYTE;
break;
case DATA_BOOL:
out.m_category = CommonStructuredDataTypeCategory::BOOL;
break;
case DATA_FLOAT:
out.m_category = CommonStructuredDataTypeCategory::FLOAT;
break;
case DATA_SHORT:
out.m_category = CommonStructuredDataTypeCategory::SHORT;
break;
case DATA_STRING:
out.m_category = CommonStructuredDataTypeCategory::STRING;
out.m_info.string_length = in.u.stringDataLength;
break;
case DATA_ENUM:
assert(!def->m_enums.empty());
out.m_category = CommonStructuredDataTypeCategory::ENUM;
out.m_info.type_index = std::max(std::min(static_cast<size_t>(in.u.enumIndex), def->m_enums.size() - 1u), 0u);
break;
case DATA_STRUCT:
assert(!def->m_structs.empty());
out.m_category = CommonStructuredDataTypeCategory::STRUCT;
out.m_info.type_index = std::max(std::min(static_cast<size_t>(in.u.structIndex), def->m_structs.size() - 1u), 0u);
break;
case DATA_INDEXED_ARRAY:
assert(!def->m_indexed_arrays.empty());
out.m_category = CommonStructuredDataTypeCategory::INDEXED_ARRAY;
out.m_info.type_index = std::max(std::min(static_cast<size_t>(in.u.indexedArrayIndex), def->m_indexed_arrays.size() - 1u), 0u);
break;
case DATA_ENUM_ARRAY:
assert(!def->m_enumed_arrays.empty());
out.m_category = CommonStructuredDataTypeCategory::ENUM_ARRAY;
out.m_info.type_index = std::max(std::min(static_cast<size_t>(in.u.enumedArrayIndex), def->m_enumed_arrays.size() - 1u), 0u);
break;
case DATA_COUNT:
default:
assert(false);
break;
}
return out;
}
void AssetDumperStructuredDataDefSet::ConvertEnum(CommonStructuredDataEnum* out, const StructuredDataEnum* in, const size_t enumIndex)
{
out->m_name = "ENUM_" + std::to_string(enumIndex);
out->m_reserved_entry_count = std::max(in->reservedEntryCount, 0);
out->m_entries.resize(static_cast<size_t>(std::max(in->entryCount, 0)));
for(auto i = 0u; i < out->m_entries.size(); i++)
{
auto& outEntry = out->m_entries[i];
const auto& inEntry = in->entries[i];
outEntry.m_name = std::string(inEntry.string);
outEntry.m_value = inEntry.index;
}
out->SortEntries();
}
void AssetDumperStructuredDataDefSet::ConvertStruct(const CommonStructuredDataDef* def, CommonStructuredDataStruct* out, const StructuredDataStruct* in, const size_t structIndex, const size_t rootIndex)
{
if (structIndex == rootIndex)
out->m_name = "root";
else
out->m_name = "STRUCT_" + std::to_string(structIndex);
out->m_size_in_byte = static_cast<size_t>(std::max(in->size, 0));
out->m_bit_offset = in->bitOffset;
out->m_properties.resize(static_cast<size_t>(std::max(in->propertyCount, 0)));
for (auto i = 0u; i < out->m_properties.size(); i++)
{
auto& outProperty = out->m_properties[i];
const auto& inProperty = in->properties[i];
outProperty.m_name = std::string(inProperty.name);
outProperty.m_type = ConvertType(def, inProperty.type);
if (inProperty.type.type == DATA_BOOL)
outProperty.m_offset_in_bits = inProperty.offset;
else
outProperty.m_offset_in_bits = inProperty.offset * 8;
}
out->SortProperties();
}
void AssetDumperStructuredDataDefSet::ConvertIndexedArray(const CommonStructuredDataDef* def, CommonStructuredDataIndexedArray* out, const StructuredDataIndexedArray* in)
{
out->m_element_count = static_cast<size_t>(std::max(in->arraySize, 0));
out->m_element_size_in_bits = in->elementType.type == DATA_BOOL ? 1 : in->elementSize * 8;
out->m_array_type = ConvertType(def, in->elementType);
}
void AssetDumperStructuredDataDefSet::ConvertEnumedArray(const CommonStructuredDataDef* def, CommonStructuredDataEnumedArray* out, const StructuredDataEnumedArray* in)
{
assert(!def->m_enums.empty());
out->m_element_size_in_bits = in->elementType.type == DATA_BOOL ? 1 : in->elementSize * 8;
out->m_array_type = ConvertType(def, in->elementType);
out->m_enum_index = std::max(std::min(static_cast<size_t>(in->enumIndex), def->m_enums.size() - 1u), 0u);
if (def->m_enums.empty())
return;
out->m_element_count = def->m_enums[out->m_enum_index]->ElementCount();
}
std::unique_ptr<CommonStructuredDataDef> AssetDumperStructuredDataDefSet::ConvertDef(const StructuredDataDef* in)
{
auto out = std::make_unique<CommonStructuredDataDef>();
out->m_version = in->version;
out->m_checksum = in->formatChecksum;
out->m_size_in_byte = in->size;
out->m_enums.resize(static_cast<size_t>(std::max(in->enumCount, 0)));
out->m_structs.resize(static_cast<size_t>(std::max(in->structCount, 0)));
out->m_indexed_arrays.resize(static_cast<size_t>(std::max(in->indexedArrayCount, 0)));
out->m_enumed_arrays.resize(static_cast<size_t>(std::max(in->enumedArrayCount, 0)));
for (auto i = 0u; i < out->m_enums.size(); i++)
{
auto _enum = std::make_unique<CommonStructuredDataEnum>();
ConvertEnum(_enum.get(), &in->enums[i], i);
out->m_enums[i] = std::move(_enum);
}
for (auto i = 0u; i < out->m_structs.size(); i++)
{
auto _struct = std::make_unique<CommonStructuredDataStruct>();
ConvertStruct(out.get(), _struct.get(), &in->structs[i], i, static_cast<size_t>(in->rootType.u.structIndex));
out->m_structs[i] = std::move(_struct);
}
for (auto i = 0u; i < out->m_indexed_arrays.size(); i++)
ConvertIndexedArray(out.get(), &out->m_indexed_arrays[i], &in->indexedArrays[i]);
for (auto i = 0u; i < out->m_enumed_arrays.size(); i++)
ConvertEnumedArray(out.get(), &out->m_enumed_arrays[i], &in->enumedArrays[i]);
out->m_root_type = ConvertType(out.get(), in->rootType);
return out;
}
void AssetDumperStructuredDataDefSet::DumpAsset(AssetDumpingContext& context, XAssetInfo<StructuredDataDefSet>* asset)
{
const auto* set = asset->Asset();
@ -351,25 +507,10 @@ void AssetDumperStructuredDataDefSet::DumpAsset(AssetDumpingContext& context, XA
if (!assetFile || set->defs == nullptr)
return;
StructuredDataDefDumper dumper(*assetFile);
for (auto defIndex = 0u; defIndex < set->defCount; defIndex++)
StructuredDataDefDumperNew newDumper(*assetFile);
for (auto i = 0u; i < set->defCount; i++)
{
const auto& def = set->defs[defIndex];
dumper.WriteLineComment("Size: "s + std::to_string(def.size));
dumper.WriteLineComment("Checksum: "s + std::to_string(def.formatChecksum));
dumper.BeginVersion(def.version);
for (auto enumIndex = 0; enumIndex < def.enumCount; enumIndex++)
DumpEnum(dumper, enumIndex, &def.enums[enumIndex]);
const auto rootStructIndex = def.rootType.type == DATA_STRUCT ? def.rootType.u.structIndex : -1;
assert(rootStructIndex >= 0);
const auto structDumpingOrder = CalculateStructDumpingOrder(&def);
for (auto i = structDumpingOrder.rbegin(); i != structDumpingOrder.rend(); ++i)
DumpStruct(dumper, *i, &def.structs[*i], &def, rootStructIndex);
dumper.EndVersion();
const auto def = ConvertDef(&set->defs[i]);
newDumper.DumpDef(*def);
}
}