Example #1
0
        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);
        }
Example #2
0
        /// <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);
                }
            }
        }
Example #3
0
        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();
        }
Example #4
0
        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);
        }
Example #5
0
        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);
        }
Example #6
0
 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;
     }
 }
Example #7
0
        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);
        }
Example #8
0
        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);
            }
        }
Example #9
0
        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);
            }
        }
Example #10
0
        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();
        }
Example #11
0
        /// <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);
            }
        }
Example #12
0
 public virtual void Deserialize_Array(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, Array target, int index)
 {
     target.SetValue(DeserializeArrayInternal(manager, data, field, target), index);
 }
Example #13
0
        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}");
                    }
                }
            }
        }
Example #14
0
 public virtual void Deserialize(teStructuredDataMgr manager, teStructuredData data, STUField_Info field, object instance, FieldInfo target)
 {
     target.SetValue(instance, DeserializeInternal(manager, data, field, target));
 }
Example #15
0
 public void Deserialize_Array(teStructuredData data, STUField_Info field)
 {
     // Not possible
     throw new NotImplementedException();
 }
Example #16
0
 public void Deserialize_Array(teStructuredData assetFile, STUField_Info field) => Deserialize(assetFile, field);
Example #17
0
        /// <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;
            }
        }