diff --git a/src/ObjCommon/StructuredDataDef/CommonStructuredDataTypes.cpp b/src/ObjCommon/StructuredDataDef/CommonStructuredDataTypes.cpp index 0e69be6d..59f96e3b 100644 --- a/src/ObjCommon/StructuredDataDef/CommonStructuredDataTypes.cpp +++ b/src/ObjCommon/StructuredDataDef/CommonStructuredDataTypes.cpp @@ -1,5 +1,9 @@ #include "CommonStructuredDataTypes.h" +#include + +#include "CommonStructuredDataDef.h" + CommonStructuredDataType::CommonStructuredDataType() : m_category(CommonStructuredDataTypeCategory::UNKNOWN), m_info({0}) @@ -18,6 +22,62 @@ CommonStructuredDataType::CommonStructuredDataType(const CommonStructuredDataTyp { } +size_t CommonStructuredDataType::GetAlignmentInBits() const +{ + return m_category == CommonStructuredDataTypeCategory::BOOL ? 0u : 8u; +} + +size_t CommonStructuredDataType::GetSizeInBits(const CommonStructuredDataDef& def) const +{ + switch (m_category) + { + case CommonStructuredDataTypeCategory::INT: + case CommonStructuredDataTypeCategory::FLOAT: + return 32u; + case CommonStructuredDataTypeCategory::BYTE: + return 8u; + case CommonStructuredDataTypeCategory::BOOL: + return 1u; + case CommonStructuredDataTypeCategory::ENUM: + case CommonStructuredDataTypeCategory::SHORT: + return 16u; + case CommonStructuredDataTypeCategory::STRING: + return m_info.string_length * 8; + case CommonStructuredDataTypeCategory::STRUCT: + if (m_info.type_index >= def.m_structs.size()) + { + assert(false); + return 0u; + } + return def.m_structs[m_info.type_index]->m_size_in_byte * 8u; + case CommonStructuredDataTypeCategory::INDEXED_ARRAY: + { + if (m_info.type_index >= def.m_indexed_arrays.size()) + { + assert(false); + return 0u; + } + const auto& indexedArray = def.m_indexed_arrays[m_info.type_index]; + return indexedArray.m_element_size_in_bits * indexedArray.m_element_count; + } + case CommonStructuredDataTypeCategory::ENUM_ARRAY: + { + if (m_info.type_index >= def.m_enumed_arrays.size()) + { + assert(false); + return 0u; + } + const auto& enumedArray = def.m_enumed_arrays[m_info.type_index]; + return enumedArray.m_element_size_in_bits * enumedArray.m_element_count; + } + + case CommonStructuredDataTypeCategory::UNKNOWN: + default: + assert(false); + return 0u; + } +} + bool operator<(const CommonStructuredDataType& lhs, const CommonStructuredDataType& rhs) { if (lhs.m_category < rhs.m_category) diff --git a/src/ObjCommon/StructuredDataDef/CommonStructuredDataTypes.h b/src/ObjCommon/StructuredDataDef/CommonStructuredDataTypes.h index d3f1c460..4cc4fd3e 100644 --- a/src/ObjCommon/StructuredDataDef/CommonStructuredDataTypes.h +++ b/src/ObjCommon/StructuredDataDef/CommonStructuredDataTypes.h @@ -2,6 +2,8 @@ #include +#include "Utils/ClassUtils.h" + enum class CommonStructuredDataTypeCategory { UNKNOWN, @@ -23,6 +25,7 @@ union CommonStructuredDataTypeExtraInfo size_t type_index; }; +class CommonStructuredDataDef; struct CommonStructuredDataType { CommonStructuredDataTypeCategory m_category; @@ -32,6 +35,9 @@ struct CommonStructuredDataType explicit CommonStructuredDataType(CommonStructuredDataTypeCategory category); CommonStructuredDataType(CommonStructuredDataTypeCategory category, size_t extraInfo); + _NODISCARD size_t GetAlignmentInBits() const; + _NODISCARD size_t GetSizeInBits(const CommonStructuredDataDef& def) const; + friend bool operator<(const CommonStructuredDataType& lhs, const CommonStructuredDataType& rhs); friend bool operator<=(const CommonStructuredDataType& lhs, const CommonStructuredDataType& rhs); friend bool operator>(const CommonStructuredDataType& lhs, const CommonStructuredDataType& rhs); diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.cpp index 944ee225..d5be90db 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.cpp @@ -420,14 +420,19 @@ void AssetDumperStructuredDataDefSet::ConvertEnum(CommonStructuredDataEnum* out, out->SortEntries(); } -void AssetDumperStructuredDataDefSet::ConvertStruct(const CommonStructuredDataDef* def, CommonStructuredDataStruct* out, const StructuredDataStruct* in, const size_t structIndex, const size_t rootIndex) +void AssetDumperStructuredDataDefSet::ConvertStruct(const CommonStructuredDataDef* def, const StructuredDataDef* gameDef, CommonStructuredDataStruct* out, const StructuredDataStruct* in, const size_t structIndex) { - if (structIndex == rootIndex) + if (gameDef->rootType.type == DATA_STRUCT && structIndex == static_cast(gameDef->rootType.u.structIndex)) + { out->m_name = "root"; + out->m_size_in_byte = gameDef->size; + } else + { out->m_name = "STRUCT_" + std::to_string(structIndex); + out->m_size_in_byte = static_cast(std::max(in->size, 0)); + } - out->m_size_in_byte = static_cast(std::max(in->size, 0)); out->m_bit_offset = in->bitOffset; out->m_properties.resize(static_cast(std::max(in->propertyCount, 0))); @@ -463,7 +468,10 @@ void AssetDumperStructuredDataDefSet::ConvertEnumedArray(const CommonStructuredD out->m_enum_index = std::max(std::min(static_cast(in->enumIndex), def->m_enums.size() - 1u), 0u); if (def->m_enums.empty()) + { + assert(false); return; + } out->m_element_count = def->m_enums[out->m_enum_index]->ElementCount(); } @@ -490,7 +498,7 @@ std::unique_ptr AssetDumperStructuredDataDefSet::Conver for (auto i = 0u; i < out->m_structs.size(); i++) { auto _struct = std::make_unique(); - ConvertStruct(out.get(), _struct.get(), &in->structs[i], i, static_cast(in->rootType.u.structIndex)); + ConvertStruct(out.get(), in, _struct.get(), &in->structs[i], i); out->m_structs[i] = std::move(_struct); } for (auto i = 0u; i < out->m_indexed_arrays.size(); i++) diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.h index 3c6e96ab..244e5876 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.h +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.h @@ -23,7 +23,7 @@ namespace IW4 static CommonStructuredDataType ConvertType(const CommonStructuredDataDef* def, const StructuredDataType in); static void ConvertEnum(CommonStructuredDataEnum* out, const StructuredDataEnum* in, size_t enumIndex); - static void ConvertStruct(const CommonStructuredDataDef* def, CommonStructuredDataStruct* out, const StructuredDataStruct* in, const size_t structIndex, const size_t rootIndex); + static void ConvertStruct(const CommonStructuredDataDef* def, const StructuredDataDef* gameDef, CommonStructuredDataStruct* out, const StructuredDataStruct* in, const size_t structIndex); static void ConvertIndexedArray(const CommonStructuredDataDef* def, CommonStructuredDataIndexedArray* out, const StructuredDataIndexedArray* in); static void ConvertEnumedArray(const CommonStructuredDataDef* def, CommonStructuredDataEnumedArray* out, const StructuredDataEnumedArray* in); static std::unique_ptr ConvertDef(const StructuredDataDef* in); diff --git a/src/ObjWriting/StructuredDataDef/StructuredDataDefDumper.cpp b/src/ObjWriting/StructuredDataDef/StructuredDataDefDumper.cpp index 014e0b10..ca566f96 100644 --- a/src/ObjWriting/StructuredDataDef/StructuredDataDefDumper.cpp +++ b/src/ObjWriting/StructuredDataDef/StructuredDataDefDumper.cpp @@ -1,5 +1,8 @@ #include "StructuredDataDefDumper.h" +#include +#include + StructuredDataDefDumperNew::StructuredDataDefDumperNew(std::ostream& stream) : AbstractTextDumper(stream), m_flags{} @@ -44,32 +47,123 @@ void StructuredDataDefDumperNew::DumpEnum(const CommonStructuredDataEnum& _enum) m_stream << "};\n"; // end enum } -void StructuredDataDefDumperNew::DumpType(const CommonStructuredDataDef& def, CommonStructuredDataType type, std::string& typeName, std::vector& arraySpecifiersInReverseOrder) +void StructuredDataDefDumperNew::DumpType(const CommonStructuredDataDef& def, CommonStructuredDataType type, std::string& typeName, std::vector& arraySpecifiers) const { - typeName = "unknown"; + while (type.m_category != CommonStructuredDataTypeCategory::UNKNOWN) + { + switch (type.m_category) + { + case CommonStructuredDataTypeCategory::INT: + typeName = "int"; + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + case CommonStructuredDataTypeCategory::BYTE: + typeName = "byte"; + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + case CommonStructuredDataTypeCategory::BOOL: + typeName = "bool"; + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + case CommonStructuredDataTypeCategory::FLOAT: + typeName = "float"; + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + case CommonStructuredDataTypeCategory::SHORT: + typeName = "short"; + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + case CommonStructuredDataTypeCategory::STRING: + { + std::ostringstream ss; + ss << "string(" << type.m_info.string_length << ')'; + typeName = ss.str(); + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + } + break; + case CommonStructuredDataTypeCategory::ENUM: + assert(type.m_info.type_index < def.m_enums.size()); + if (type.m_info.type_index < def.m_enums.size()) + typeName = def.m_enums[type.m_info.type_index]->m_name; + else + typeName = "unknown"; + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + case CommonStructuredDataTypeCategory::STRUCT: + assert(type.m_info.type_index < def.m_structs.size()); + if (type.m_info.type_index < def.m_structs.size()) + typeName = def.m_structs[type.m_info.type_index]->m_name; + else + typeName = "unknown"; + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + case CommonStructuredDataTypeCategory::INDEXED_ARRAY: + assert(type.m_info.type_index < def.m_indexed_arrays.size()); + if (type.m_info.type_index < def.m_indexed_arrays.size()) + { + const auto& indexArray = def.m_indexed_arrays[type.m_info.type_index]; + arraySpecifiers.push_back(std::to_string(indexArray.m_element_count)); + type = indexArray.m_array_type; + } + else + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + case CommonStructuredDataTypeCategory::ENUM_ARRAY: + assert(type.m_info.type_index < def.m_enumed_arrays.size()); + if (type.m_info.type_index < def.m_enumed_arrays.size()) + { + const auto& enumedArray = def.m_enumed_arrays[type.m_info.type_index]; + + assert(enumedArray.m_enum_index < def.m_enums.size()); + if (enumedArray.m_enum_index < def.m_enums.size()) + arraySpecifiers.push_back(def.m_enums[enumedArray.m_enum_index]->m_name); + type = enumedArray.m_array_type; + } + else + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + default: + type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN); + break; + } + } } -void StructuredDataDefDumperNew::DumpProperty(const CommonStructuredDataDef& def, const CommonStructuredDataStructProperty& property, unsigned& currentOffsetInBit) +void StructuredDataDefDumperNew::DumpProperty(const CommonStructuredDataDef& def, const CommonStructuredDataStructProperty& property, unsigned& currentOffsetInBit) const { std::string typeName; - std::vector arraySpecifiersInReverseOrder; + std::vector arraySpecifiers; - DumpType(def, property.m_type, typeName, arraySpecifiersInReverseOrder); + DumpType(def, property.m_type, typeName, arraySpecifiers); Indent(); m_stream << typeName << ' ' << property.m_name; - for (auto ri = arraySpecifiersInReverseOrder.rbegin(); ri != arraySpecifiersInReverseOrder.rend(); ++ri) + for (auto ri = arraySpecifiers.begin(); ri != arraySpecifiers.end(); ++ri) m_stream << '[' << *ri << ']'; + #ifdef STRUCTUREDDATADEF_DEBUG - m_stream << " /* Offset: " << (property.m_offset_in_bits / 8) << " byte"; + m_stream << "; // Offset: " << (property.m_offset_in_bits / 8) << " byte"; if (property.m_offset_in_bits % 8 > 0) m_stream << " + " << (property.m_offset_in_bits % 8) << " bit"; - m_stream << " */"; -#endif + const auto sizeInBits = property.m_type.GetSizeInBits(def); + m_stream << " | Size: "; + + if (sizeInBits % 8 == 0) + m_stream << (sizeInBits / 8) << " byte"; + else if (sizeInBits > 8) + m_stream << (sizeInBits / 8) << " byte + " << (sizeInBits % 8) << " bit"; + else + m_stream << sizeInBits << " bit"; + + m_stream << " | Alignment: " << property.m_type.GetAlignmentInBits() << " bit"; + m_stream << '\n'; +#else m_stream << ";\n"; + +#endif } void StructuredDataDefDumperNew::DumpStruct(const CommonStructuredDataDef& def, const CommonStructuredDataStruct& _struct, const size_t structIndex) diff --git a/src/ObjWriting/StructuredDataDef/StructuredDataDefDumper.h b/src/ObjWriting/StructuredDataDef/StructuredDataDefDumper.h index 65f6ab98..7955d85d 100644 --- a/src/ObjWriting/StructuredDataDef/StructuredDataDefDumper.h +++ b/src/ObjWriting/StructuredDataDef/StructuredDataDefDumper.h @@ -16,8 +16,8 @@ class StructuredDataDefDumperNew : AbstractTextDumper void WriteLineComment(const std::string& comment) const; void DumpEnum(const CommonStructuredDataEnum& _enum); - void DumpType(const CommonStructuredDataDef& def, CommonStructuredDataType type, std::string& typeName, std::vector& arraySpecifiersInReverseOrder); - void DumpProperty(const CommonStructuredDataDef& def, const CommonStructuredDataStructProperty& property, unsigned& currentOffsetInBit); + void DumpType(const CommonStructuredDataDef& def, CommonStructuredDataType type, std::string& typeName, std::vector& arraySpecifiers) const; + void DumpProperty(const CommonStructuredDataDef& def, const CommonStructuredDataStructProperty& property, unsigned& currentOffsetInBit) const; void DumpStruct(const CommonStructuredDataDef& def, const CommonStructuredDataStruct& _struct, size_t structIndex); public: