public override void Deserialize_Array(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, Array target, int index) { STUInstance instanceObj = (STUInstance)DeserializeArrayInternal(manager, data, field, target); instanceObj.Usage = TypeUsage.InlineArray; target.SetValue(instanceObj, index); }
/// <summary>Deserialize instance</summary> public void Deserialize(teStructuredData assetFile, STUField_Info field = null) { BinaryReader data = assetFile.Data; uint instanceHash = teStructuredData.Manager.InstancesInverted[GetType()]; STUAttribute stuAttribute = teStructuredData.Manager.InstanceAttributes[instanceHash]; Dictionary <uint, KeyValuePair <FieldInfo, STUFieldAttribute> > fields = teStructuredData.Manager.FieldAttributes[instanceHash]; if (assetFile.Format == teStructuredDataFormat.V2) { int fieldBagIdx = data.ReadInt32(); if (fieldBagIdx == -1) { return; } if (fieldBagIdx >= assetFile.FieldInfoBags.Count) { throw new ArgumentOutOfRangeException($"FieldBag index is out of range. Id: {fieldBagIdx}, Type: '{GetType().Name}', Data offset: {data.BaseStream.Position - 4}"); } foreach (STUField_Info stuField in assetFile.FieldInfoBags[fieldBagIdx]) { int fieldSize = stuField.Size; if (fieldSize == 0) { fieldSize = data.ReadInt32(); } long startPosition = data.BaseStream.Position; DeserializeField(assetFile, stuField, fields, stuAttribute); data.BaseStream.Position = startPosition + fieldSize; //long endPosition = data.BaseStream.Position; //if (endPosition - startPosition != fieldSize) // throw new InvalidDataException($"read len != field size. Type: '{GetType().Name}', Field: {stuField.Hash:X8}, Data offset: {startPosition}"); } } else if (assetFile.Format == teStructuredDataFormat.V1) { //if (instanceHash == 0xEA30C5E9 || instanceHash == 0x298FC27F || instanceHash == 0x75526BC2 || // instanceHash == 0x5C7059E || instanceHash == 0x646FF8C3 || instanceHash == 0xAD5967B3 || // instanceHash == 0x74F13350) { // Debugger.Log(0, "STUInstnace", "HACK: SKIPPING DESERIALIZE\r\n"); // return; // //Debugger.Break(); //} uint[] fieldOrder = teStructuredData.Manager.InstanceFields[instanceHash]; foreach (uint fieldHash in fieldOrder) { //long fieldStart = data.BaseStream.Position; STUField_Info stuField = new STUField_Info { Hash = fieldHash, Size = -1 }; DeserializeField(assetFile, stuField, fields, stuAttribute); } } }
protected object DeserializeInternal(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, FieldInfo target) { if (manager.Factories.TryGetValue(target.FieldType, out var factory)) { return(factory.Deserialize(data, field)); } if (typeof(ISerializable_STU).IsAssignableFrom(target.FieldType)) { ISerializable_STU ret = (ISerializable_STU)Activator.CreateInstance(target.FieldType); ret.Deserialize(data, field); return(ret); } if (target.FieldType.IsEnum) { IStructuredDataPrimitiveFactory enumFactory = manager.Factories[target.FieldType.GetEnumUnderlyingType()]; return(enumFactory.Deserialize(data, field)); } bool isStruct = target.FieldType.IsValueType && !target.FieldType.IsPrimitive; if (isStruct) { MethodInfo method = typeof(Extensions).GetMethod(nameof(Extensions.Read))?.MakeGenericMethod(target.FieldType); return(method?.Invoke(data.Data, new object[] { data.Data })); } throw new NotImplementedException(); }
public override void Deserialize(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, object instance, FieldInfo target) { STUInstance instanceObj = (STUInstance)DeserializeInternal(manager, data, field, target); instanceObj.Usage = TypeUsage.Inline; target.SetValue(instance, instanceObj); }
public override void Deserialize_Array(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, Array target, int index) { // todo: ??? //if (data.Format == teStructuredDataFormat.V1 && index == 0) { // var n = data.Data.ReadInt64(); // if (n > 0) { // // } //} STUInstance instanceObj = (STUInstance)DeserializeArrayInternal(manager, data, field, target); instanceObj.Usage = TypeUsage.InlineArray; target.SetValue(instanceObj, index); }
public void Deserialize_Array(teStructuredData data, STUField_Info field) { if (data.Format == teStructuredDataFormat.V2) { Padding = data.DynData.ReadUInt64(); ulong guid = data.DynData.ReadUInt64(); Deobfuscate(data.HeaderChecksum, field.Hash, guid); } else if (data.Format == teStructuredDataFormat.V1) { Padding = data.Data.ReadUInt64(); ulong guid = data.Data.ReadUInt64(); GUID = (teResourceGUID)guid; } }
public override void Deserialize(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, object instance, FieldInfo target) { if (data.Format == teStructuredDataFormat.V1) { var n = data.Data.ReadInt64(); if (n > 0) { } } STUInstance instanceObj = (STUInstance)DeserializeInternal(manager, data, field, target); instanceObj.Usage = TypeUsage.Inline; target.SetValue(instance, instanceObj); }
public void Deserialize_Array(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, Array target, int index) { if (data.Format == teStructuredDataFormat.V2) { int value = data.DynData.ReadInt32(); data.DynData.ReadInt32(); // Padding for in-place deserialization if (value == -1) { return; } if (value < data.Instances.Length) { STUInstance embeddedInstance = data.Instances[value]; if (embeddedInstance != null) { embeddedInstance.Usage = TypeUsage.EmbedArray; } target.SetValue(embeddedInstance, index); } else { throw new ArgumentOutOfRangeException( $"Instance index is out of range. Id: {value}, Type: EmbeddedInstanceFieldReader, DynData offset: {data.DynData.Position() - 8}"); } } else if (data.Format == teStructuredDataFormat.V1) { long offset = data.Data.ReadInt32(); data.Data.ReadInt32(); if (offset == -1) { return; } STUInstance embeddedInstance = data.GetInstanceAtOffset(offset); if (embeddedInstance != null) { embeddedInstance.Usage = TypeUsage.EmbedArray; } target.SetValue(embeddedInstance, index); } }
public void Deserialize(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, object instance, FieldInfo target) { if (data.Format == teStructuredDataFormat.V2) { int value = data.Data.ReadInt32(); if (value == -1) { return; } if (value < data.Instances.Length) { STUInstance embeddedInstance = data.Instances[value]; if (embeddedInstance != null) { embeddedInstance.Usage = TypeUsage.Embed; } target.SetValue(instance, embeddedInstance); } } else if (data.Format == teStructuredDataFormat.V1) { int value = data.Data.ReadInt32(); data.Data.ReadInt32(); if (value <= 0) { return; } STUInstance embeddedInstance = data.GetInstanceAtOffset(value); if (embeddedInstance != null) { embeddedInstance.Usage = TypeUsage.Embed; } target.SetValue(instance, embeddedInstance); } }
protected object DeserializeArrayInternal(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, Array target) { Type elementType = target.GetType().GetElementType(); if (elementType == null) { throw new InvalidDataException("elementType is null"); } if (manager.Factories.ContainsKey(elementType)) { IStructuredDataPrimitiveFactory factory = manager.Factories[elementType]; return(factory.DeserializeArray(data, field)); } if (typeof(ISerializable_STU).IsAssignableFrom(elementType)) { ISerializable_STU ret = (ISerializable_STU)Activator.CreateInstance(elementType); ret.Deserialize_Array(data, field); return(ret); } if (elementType.IsEnum) { IStructuredDataPrimitiveFactory factory = manager.Factories[elementType.GetEnumUnderlyingType()]; return(Enum.ToObject(elementType, factory.DeserializeArray(data, field))); } bool isStruct = elementType.IsValueType && !elementType.IsPrimitive; if (isStruct) { MethodInfo method = typeof(Extensions).GetMethod(nameof(Extensions.Read))?.MakeGenericMethod(elementType); return(method?.Invoke(data.DynData, new object[] { data.DynData })); } throw new NotImplementedException(); }
/// <summary>Read a specified STU field</summary> protected void DeserializeField(teStructuredData assetFile, STUField_Info fieldInfo, Dictionary <uint, KeyValuePair <FieldInfo, STUFieldAttribute> > fields, STUAttribute stuAttribute) { if (!fields.TryGetValue(fieldInfo.Hash, out var field)) { #if DEBUG string name = stuAttribute.Name ?? $"STU_{stuAttribute.Hash:X8}"; Debugger.Log(0, "STUInstance", $"Unhandled field: {name}:{fieldInfo.Hash:X8} (size: {fieldInfo.Size})\r\n"); #endif return; } if (assetFile.Format == teStructuredDataFormat.V1) { assetFile.DynData = assetFile.Data; } IStructuredDataFieldReader reader = teStructuredData.Manager.FieldReaders[field.Value.ReaderType]; if (field.Key.FieldType.IsArray) { Type elementType = field.Key.FieldType.GetElementType(); if (elementType == null) { return; } Array array; BinaryReader data = assetFile.Data; BinaryReader dynData = assetFile.DynData; if (assetFile.Format == teStructuredDataFormat.V2) { if (fieldInfo.Size == 0 || reader is InlineInstanceFieldReader) // inline { int size = data.ReadInt32(); if (size == 0) { return; } array = Array.CreateInstance(elementType, size); for (int i = 0; i != size; ++i) { reader.Deserialize_Array(teStructuredData.Manager, assetFile, fieldInfo, array, i); } } else { int offset = data.ReadInt32(); if (offset == -1) { return; } dynData.Seek(offset); int size = dynData.ReadInt32(); if (size == 0) { return; } array = Array.CreateInstance(elementType, size); uint unknown = dynData.ReadUInt32(); dynData.Seek(dynData.ReadInt64()); // Seek to dataoffset for (int i = 0; i != size; ++i) { reader.Deserialize_Array(teStructuredData.Manager, assetFile, fieldInfo, array, i); } } } else { long offset = data.ReadInt32(); data.ReadInt32(); // :kyaah: long position = data.Position(); if (offset <= 0) { array = null; } else { data.BaseStream.Position = offset + assetFile.StartPos; long count = data.ReadInt64(); long dataOffset = data.ReadInt64(); if (count != -1 && dataOffset > 0) { array = Array.CreateInstance(elementType, count); data.BaseStream.Position = dataOffset + assetFile.StartPos; for (int i = 0; i != count; ++i) { reader.Deserialize_Array(teStructuredData.Manager, assetFile, fieldInfo, array, i); } } else { array = null; } } data.BaseStream.Position = position + 8; } field.Key.SetValue(this, array); } else { reader.Deserialize(teStructuredData.Manager, assetFile, fieldInfo, this, field.Key); } }
public virtual void Deserialize_Array(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, Array target, int index) { target.SetValue(DeserializeArrayInternal(manager, data, field, target), index); }
public void Deserialize(teStructuredData assetFile, STUField_Info field) { BinaryReader data = assetFile.Data; BinaryReader dynData = assetFile.DynData; int offset = data.ReadInt32(); if (offset == -1) { return; } dynData.Seek(offset); int unk2Size = dynData.ReadInt32(); if (unk2Size == 0) { return; } Unknown1 = dynData.ReadUInt32(); long unk2Offset = dynData.ReadInt64(); long dataOffset = dynData.ReadInt64(); dynData.Seek(unk2Offset); Unknown2 = new uint[unk2Size]; for (int i = 0; i != unk2Size; ++i) { Unknown2[i] = dynData.ReadUInt32(); } dynData.Seek(dataOffset); uint mapSize = Unknown2.Last(); for (int i = 0; i != mapSize; ++i) { ulong key = dynData.ReadUInt64(); // Last 4 bytes are padding for in-place deserialization. int value = (int)dynData.ReadUInt64(); if (value == -1) { Add(key, null); } else { if (value < assetFile.Instances.Length) { STUInstance stuType = assetFile.Instances[value]; if (stuType != null) { stuType.Usage = TypeUsage.HashMap; } if (stuType is T casted) { Add(key, casted); } else { throw new InvalidCastException( $"Attempted to cast '{stuType?.GetType().Name}' to '{typeof(T).Name}'"); } } else { throw new ArgumentOutOfRangeException( $"DataRoot index is out of range. Id: {value}, Type: STUHashMap<{typeof(T).Name}>, Data offset: {dynData.Position() - 8}"); } } } }
public virtual void Deserialize(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, object instance, FieldInfo target) { target.SetValue(instance, DeserializeInternal(manager, data, field, target)); }
public void Deserialize_Array(teStructuredData data, STUField_Info field) { // Not possible throw new NotImplementedException(); }
public void Deserialize_Array(teStructuredData assetFile, STUField_Info field) => Deserialize(assetFile, field);
/// <summary>Deserialize instance</summary> public void Deserialize(teStructuredData assetFile, STUField_Info field = null) { BinaryReader data = assetFile.Data; uint instanceHash = teStructuredData.Manager.InstancesInverted[GetType()]; STUAttribute stuAttribute = teStructuredData.Manager.InstanceAttributes[instanceHash]; Dictionary <uint, KeyValuePair <FieldInfo, STUFieldAttribute> > fields = teStructuredData.Manager.FieldAttributes[instanceHash]; if (assetFile.Format == teStructuredDataFormat.V2) { int fieldBagIdx = data.ReadInt32(); if (fieldBagIdx == -1) { return; } if (fieldBagIdx >= assetFile.FieldInfoBags.Count) { throw new ArgumentOutOfRangeException($"FieldBag index is out of range. Id: {fieldBagIdx}, Type: '{GetType().Name}', Data offset: {data.BaseStream.Position - 4}"); } foreach (STUField_Info stuField in assetFile.FieldInfoBags[fieldBagIdx]) { int fieldSize = stuField.Size; if (fieldSize == 0) { fieldSize = data.ReadInt32(); } long startPosition = data.BaseStream.Position; DeserializeField(assetFile, stuField, fields, stuAttribute); data.BaseStream.Position = startPosition + fieldSize; //long endPosition = data.BaseStream.Position; //if (endPosition - startPosition != fieldSize) // throw new InvalidDataException($"read len != field size. Type: '{GetType().Name}', Field: {stuField.Hash:X8}, Data offset: {startPosition}"); } } else if (assetFile.Format == teStructuredDataFormat.V1) { //if (instanceHash == 0xEA30C5E9 || instanceHash == 0x298FC27F || instanceHash == 0x75526BC2 || // instanceHash == 0x5C7059E || instanceHash == 0x646FF8C3 || instanceHash == 0xAD5967B3 || // instanceHash == 0x74F13350) { // Debugger.Log(0, "STUInstnace", "HACK: SKIPPING DESERIALIZE\r\n"); // return; // //Debugger.Break(); //} long instanceStartPos = assetFile.Data.BaseStream.Position - m_posInDataAtDeserializeCall; uint[] fieldOrder = teStructuredData.Manager.InstanceFields[instanceHash]; foreach (uint fieldHash in fieldOrder) { var fieldDefinition = fields[fieldHash]; if (fieldDefinition.Value.m_offset < m_posInDataAtDeserializeCall) { throw new InvalidDataException( $"Internal STU parser error. Field offset ({fieldDefinition.Value.m_offset}) is located " + "in data that was read before the instance deserialize method was called. (e.g field is " + "at 0, called at 8 due to crc+offset thing)"); } // go to correct field pos. e.g vecs are aligned to 16 byte so not always exactly sequential assetFile.Data.BaseStream.Position = instanceStartPos + fieldDefinition.Value.m_offset; // todo: how does alignment work on arrays // e.g will an array of vec3a be aligned by the compiler or do we need to process that STUField_Info stuField = new STUField_Info { Hash = fieldHash, Size = -1 }; DeserializeField(assetFile, stuField, fields, stuAttribute); } // make sure we are at the correct end of data including alignment padding etc assetFile.Data.BaseStream.Position = instanceStartPos + stuAttribute.m_size; } }