/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
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 }); }