示例#1
0
        /// <summary>
        /// Deserializes a data reference.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="context">The serialization context to use.</param>
        /// <returns>The deserialized data reference.</returns>
        public byte[] DeserializeDataReference(EndianReader reader, ISerializationContext context)
        {
            // Read size and pointer
            var startOffset = reader.BaseStream.Position;
            var size        = reader.ReadInt32();

            if (Version > CacheVersion.Halo2Vista)
            {
                reader.BaseStream.Position = startOffset + 0xC;
            }
            var pointer = reader.ReadUInt32();

            if (pointer == 0)
            {
                // Null data reference
                reader.BaseStream.Position = startOffset + (Version > CacheVersion.Halo2Vista ? 0x14 : 0x8);
                return(new byte[0]);
            }

            // Read the data
            var result = new byte[size];

            reader.BaseStream.Position = context.AddressToOffset((uint)(startOffset + (Version > CacheVersion.Halo2Vista ? 0xC : 0x4)), pointer);
            reader.Read(result, 0, size);
            reader.BaseStream.Position = startOffset + (Version > CacheVersion.Halo2Vista ? 0x14 : 0x8);
            return(result);
        }
示例#2
0
        /// <summary>
        /// Deserializes a tag block (list of values).
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="context">The serialization context to use.</param>
        /// <param name="valueType">The type of the value to deserialize.</param>
        /// <returns>The deserialized tag block.</returns>
        private object DeserializeTagBlock(BinaryReader reader, ISerializationContext context, Type valueType)
        {
            var elementType = valueType.GenericTypeArguments[0];
            var result      = Activator.CreateInstance(valueType);

            // Read count and offset
            var startOffset = reader.BaseStream.Position;
            var count       = reader.ReadInt32();
            var pointer     = reader.ReadUInt32();

            if (count == 0 || pointer == 0)
            {
                // Null tag block
                reader.BaseStream.Position = startOffset + 0xC;
                return(result);
            }

            // Read each value
            var addMethod = valueType.GetMethod("Add");

            reader.BaseStream.Position = context.AddressToOffset((uint)startOffset + 4, pointer);
            for (var i = 0; i < count; i++)
            {
                var element = DeserializeValue(reader, context, null, elementType);
                addMethod.Invoke(result, new[] { element });
            }
            reader.BaseStream.Position = startOffset + 0xC;
            return(result);
        }
示例#3
0
        /// <summary>
        /// Deserializes a tag block (list of values).
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="context">The serialization context to use.</param>
        /// <param name="valueType">The type of the value to deserialize.</param>
        /// <returns>The deserialized tag block.</returns>
        public object DeserializeTagBlockAsList(EndianReader reader, ISerializationContext context, Type valueType)
        {
            var result      = Activator.CreateInstance(valueType);
            var elementType = valueType.GenericTypeArguments[0];

            // Read count and offset
            var startOffset = reader.BaseStream.Position;
            var count       = reader.ReadInt32();
            var pointer     = new CacheAddress(reader.ReadUInt32());

            if (count == 0)
            {
                // Null tag block
                reader.BaseStream.Position = startOffset + (Version > CacheVersion.Halo2Vista ? 0xC : 0x8);
                return(result);
            }

            //
            // Read each value
            //

            var addMethod = valueType.GetMethod("Add");

            reader.BaseStream.Position = context.AddressToOffset((uint)startOffset + 4, pointer.Value);

            for (var i = 0; i < count; i++)
            {
                var element = DeserializeValue(reader, context, null, elementType);
                addMethod.Invoke(result, new[] { element });
            }

            reader.BaseStream.Position = startOffset + (Version > CacheVersion.Halo2Vista ? 0xC : 0x8);

            return(result);
        }
示例#4
0
        /// <summary>
        /// Deserializes a value which is pointed to by an address.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="context">The serialization context to use.</param>
        /// <param name="valueType">The type of the value to deserialize.</param>
        /// <returns>The deserialized value.</returns>
        private object DeserializeIndirectValue(BinaryReader reader, ISerializationContext context, Type valueType)
        {
            // Read the pointer
            var pointer = reader.ReadUInt32();

            if (pointer == 0)
            {
                return(null); // Null object
            }
            // Seek to it and read the object
            var nextOffset = reader.BaseStream.Position;

            reader.BaseStream.Position = context.AddressToOffset((uint)nextOffset - 4, pointer);
            var result = DeserializeValue(reader, context, null, valueType);

            reader.BaseStream.Position = nextOffset;
            return(result);
        }
示例#5
0
        /// <summary>
        /// Deserializes a value which is pointed to by an address.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="context">The serialization context to use.</param>
        /// <param name="valueType">The type of the value to deserialize.</param>
        /// <returns>The deserialized value.</returns>
        public object DeserializeIndirectValue(EndianReader reader, ISerializationContext context, Type valueType)
        {
            // Read the pointer
            var pointer = reader.ReadUInt32();

            if (valueType == typeof(PageableResource) && pointer == 0)
            {
                return(null); // Null object
            }
            // Seek to it and read the object
            var nextOffset = reader.BaseStream.Position;

            reader.BaseStream.Position = context.AddressToOffset((uint)nextOffset - 4, pointer);
            var result = DeserializeValue(reader, context, null, valueType);

            reader.BaseStream.Position = nextOffset;
            return(result);
        }
示例#6
0
        /// <summary>
        /// Deserializes a value which is pointed to by an address.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="context">The serialization context to use.</param>
        /// <param name="valueType">The type of the value to deserialize.</param>
        /// <returns>The deserialized value.</returns>
        public virtual object DeserializeD3DStructure(EndianReader reader, ISerializationContext context, Type valueType)
        {
            var result      = Activator.CreateInstance(valueType);
            var elementType = valueType.GenericTypeArguments[0];

            // Read the pointer
            var startOffset = reader.BaseStream.Position;
            var pointer     = reader.ReadUInt32();

            // Seek to it and read the object

            reader.BaseStream.Position = context.AddressToOffset((uint)startOffset + 4, pointer);

            var definition = DeserializeValue(reader, context, null, elementType);

            valueType.GetField("Definition").SetValue(result, definition);

            reader.BaseStream.Position = startOffset + 0xC;
            return(result);
        }
示例#7
0
        /// <summary>
        /// Deserializes a tag block
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="context">The serialization context to use.</param>
        /// <param name="valueType">The type of the value to deserialize.</param>
        /// <returns>The deserialized tag block.</returns>
        public virtual object DeserializeTagBlock(EndianReader reader, ISerializationContext context, Type valueType)
        {
            var result      = Activator.CreateInstance(valueType);
            var elementType = valueType.GenericTypeArguments[0];

            // Read count and offset
            var startOffset = reader.BaseStream.Position;
            var count       = reader.ReadInt32();

            var pointer = new CacheAddress(reader.ReadUInt32());

            if (count == 0)
            {
                // Null tag block
                reader.BaseStream.Position = startOffset + (Version > CacheVersion.Halo2Vista ? 0xC : 0x8);
                return(result);
            }

            //
            // Read each value
            //

            var methods = valueType.GetMethods();
            // select the add method from IList<T> and not IList interfaces
            var addMethod = methods.FirstOrDefault(method => method.Name == "Add" & method.ReturnType == typeof(void));

            reader.BaseStream.Position = context.AddressToOffset((uint)startOffset + 4, pointer.Value);

            for (var i = 0; i < count; i++)
            {
                var element = DeserializeValue(reader, context, null, elementType);
                addMethod.Invoke(result, new[] { element });
            }

            reader.BaseStream.Position = startOffset + (Version > CacheVersion.Halo2Vista ? 0xC : 0x8);

            return(result);
        }
示例#8
0
        /// <summary>
        /// Deserializes a data reference.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="context">The serialization context to use.</param>
        /// <returns>The deserialized data reference.</returns>
        private static byte[] DeserializeDataReference(BinaryReader reader, ISerializationContext context)
        {
            // Read size and pointer
            var startOffset = reader.BaseStream.Position;
            var size        = reader.ReadInt32();

            reader.BaseStream.Position = startOffset + 0xC;
            var pointer = reader.ReadUInt32();

            if (pointer == 0)
            {
                // Null data reference
                reader.BaseStream.Position = startOffset + 0x14;
                return(new byte[0]);
            }

            // Read the data
            var result = new byte[size];

            reader.BaseStream.Position = context.AddressToOffset((uint)startOffset + 0xC, pointer);
            reader.Read(result, 0, size);
            reader.BaseStream.Position = startOffset + 0x14;
            return(result);
        }
示例#9
0
        public VertexShaderReference DeserializeVertexShaderReference(EndianReader reader, ISerializationContext context)
        {
            // This reference is a uint32 pointer, we'll be moving the stream position around. Right before returning
            // from this method 'reader.SeekTo(endPosition)' will bring us to where the serializer expects the next
            // bit of data to be.
            var endPosition = reader.BaseStream.Position + 0x04;

            var headerAddress = reader.ReadUInt32();

            if (headerAddress < 1)
            {
                return(null);
            }

            var headerOffset = context.AddressToOffset((uint)(reader.BaseStream.Position - 4), headerAddress);

            reader.SeekTo(headerOffset);

            var header = (VertexShaderHeader)DeserializeStruct(reader, context, TagStructure.GetTagStructureInfo(typeof(VertexShaderHeader)));

            if (header.ShaderDataAddress == 0)
            {
                return(null);
            }

            var debugHeaderOffset = reader.Position;
            var debugHeader       = (ShaderDebugHeader)DeserializeStruct(reader, context, TagStructure.GetTagStructureInfo(typeof(ShaderDebugHeader)));

            if ((debugHeader.Magic >> 16) != 0x102A)
            {
                return(null);
            }

            if (debugHeader.StructureSize == 0)
            {
                return(null);
            }

            reader.SeekTo(debugHeaderOffset);
            var debugData = reader.ReadBytes((int)debugHeader.StructureSize);

            var updbName = "";

            if (debugHeader.UpdbPointerOffset != 0)
            {
                reader.SeekTo(debugHeaderOffset + (long)debugHeader.UpdbPointerOffset);
                var updbNameLength = reader.ReadUInt64();

                if (updbNameLength > 0)
                {
                    updbName = new string(reader.ReadChars((int)updbNameLength));
                }
            }

            var totalSize    = debugHeader.ShaderDataSize;
            var constantSize = 0U;
            var codeSize     = totalSize;

            if (debugHeader.CodeHeaderOffset != 0)
            {
                reader.SeekTo(debugHeaderOffset + debugHeader.CodeHeaderOffset);
                constantSize = reader.ReadUInt32();
                codeSize     = reader.ReadUInt32();
            }

            var constant_block_offset = context.AddressToOffset(headerOffset + 0x10, header.ShaderDataAddress);

            reader.SeekTo(constant_block_offset);
            var constantData = reader.ReadBytes((int)constantSize);

            var shader_data_block_offset = constant_block_offset + constantSize;

            reader.SeekTo(shader_data_block_offset);
            var shaderData = reader.ReadBytes((int)codeSize);

            reader.SeekTo(endPosition);

            var info = new XboxShaderInfo
            {
                DataAddress      = shader_data_block_offset,
                DebugInfoOffset  = (uint)debugHeaderOffset,
                DebugInfoSize    = debugHeader.StructureSize,
                DatabasePath     = updbName,
                DataSize         = totalSize,
                ConstantDataSize = constantSize,
                CodeDataSize     = codeSize
            };

            return(new VertexShaderReference
            {
                Info = info,
                UpdbName = updbName,
                Header = header,
                DebugHeader = debugHeader,
                DebugData = debugData,
                ShaderData = shaderData,
                ConstantData = constantData
            });
        }