public void DeserializeNestedTypes_FromSpan() { var tagStruct = (StructTestTag)BlamSerializer.Deserialize(typeof(StructTestTag), testTagData, 0, 100, null); AssertData(tagStruct); tagStruct = BlamSerializer.Deserialize <StructTestTag>(testTagData, 0, 100, null); AssertData(tagStruct); var tagRef = (ClassTestTag)BlamSerializer.Deserialize(typeof(ClassTestTag), testTagData, 0, 100, null); AssertData(tagRef); tagRef = BlamSerializer.Deserialize <ClassTestTag>(testTagData, 0, 100, null); AssertData(tagRef); var tagStructInstance = new StructTestTag(); tagStructInstance = (StructTestTag)BlamSerializer.DeserializeInto(tagStructInstance, typeof(StructTestTag), testTagData, 0, 100, null); AssertData(tagStructInstance); tagStructInstance = new StructTestTag(); tagStructInstance = BlamSerializer.DeserializeInto <StructTestTag>(tagStructInstance, testTagData, 0, 100, null); AssertData(tagStructInstance); var tagRefInstance = new ClassTestTag(); tagRefInstance = (ClassTestTag)BlamSerializer.DeserializeInto(tagRefInstance, typeof(ClassTestTag), testTagData, 0, 100, null); AssertData(tagRefInstance); tagRefInstance = new ClassTestTag(); tagRefInstance = BlamSerializer.DeserializeInto <ClassTestTag>(tagRefInstance, testTagData, 0, 100, null); AssertData(tagRefInstance); }
public void Deserialize_WrapperUsingInPlaceObjec() { var tagRef = BlamSerializer.Deserialize <EmptyWrapper>(new MemoryStream(testTagData), 0, 100, null); AssertData(tagRef); var offsetData = new byte[24 + testTagData.Length]; testTagData.CopyTo(offsetData, 20); tagRef = BlamSerializer.Deserialize <EmptyWrapper>(new MemoryStream(offsetData), 20, 80, null); AssertData(tagRef); }
public void Deserialize_ReferenceValue() { var tagRef = BlamSerializer.Deserialize <ReferenceValueHolderTag>(new MemoryStream(testTagData), 0, 100, null); AssertData(tagRef.SubValue); var offsetData = new byte[24 + testTagData.Length]; testTagData.CopyTo(offsetData, 20); tagRef = BlamSerializer.Deserialize <ReferenceValueHolderTag>(new MemoryStream(offsetData), 20, 80, null); AssertData(tagRef.SubValue); }
public IH2Map Load(string mapFileName) { Span <byte> header = new byte[2048]; using (var peek = File.OpenRead(Path.Combine(this.mapRoot, mapFileName))) { peek.Read(header); } var baseHeader = BlamSerializer.Deserialize <H2HeaderBase>(header); return(baseHeader.Version switch { MapVersion.Halo2 => LoadH2Map(mapFileName, header), MapVersion.Halo2Mcc => LoadH2mccMap(mapFileName), _ => throw new NotSupportedException() });
public void DeserializeNestedTypes_FromStream() { var tagStruct = (StructTestTag)BlamSerializer.Deserialize(typeof(StructTestTag), new MemoryStream(testTagData), 0, 100, null); AssertData(tagStruct); tagStruct = BlamSerializer.Deserialize <StructTestTag>(new MemoryStream(testTagData), 0, 100, null); AssertData(tagStruct); var tagRef = (ClassTestTag)BlamSerializer.Deserialize(typeof(ClassTestTag), new MemoryStream(testTagData), 0, 100, null); AssertData(tagRef); tagRef = BlamSerializer.Deserialize <ClassTestTag>(new MemoryStream(testTagData), 0, 100, null); AssertData(tagRef); var offsetData = new byte[24 + testTagData.Length]; testTagData.CopyTo(offsetData, 20); tagRef = BlamSerializer.Deserialize <ClassTestTag>(new MemoryStream(offsetData), 20, 80, null); AssertData(tagRef); var tagStructInstance = new StructTestTag(); tagStructInstance = (StructTestTag)BlamSerializer.DeserializeInto(tagStructInstance, typeof(StructTestTag), new MemoryStream(testTagData), 0, 100, null); AssertData(tagStructInstance); tagStructInstance = new StructTestTag(); tagStructInstance = BlamSerializer.DeserializeInto <StructTestTag>(tagStructInstance, new MemoryStream(testTagData), 0, 100, null); AssertData(tagStructInstance); var tagRefInstance = new ClassTestTag(); tagRefInstance = (ClassTestTag)BlamSerializer.DeserializeInto(tagRefInstance, typeof(ClassTestTag), new MemoryStream(testTagData), 0, 100, null); AssertData(tagRefInstance); tagRefInstance = new ClassTestTag(); tagRefInstance = BlamSerializer.DeserializeInto <ClassTestTag>(tagRefInstance, new MemoryStream(testTagData), 0, 100, null); AssertData(tagRefInstance); }
public override void PopulateExternalData(MapStream reader) { foreach (var part in Parts) { var headerOffset = new NormalOffset((int)part.DataBlockRawOffset); var mapData = reader.GetStream(headerOffset.Location); part.Header = BlamSerializer.Deserialize<ModelResourceBlockHeader>(mapData, headerOffset.Value); foreach (var resource in part.Resources) { var dataOffset = part.DataBlockRawOffset + 8 + part.DataPreambleSize + resource.Offset; mapData.Position = new NormalOffset((int)dataOffset).Value; var resourceData = new byte[resource.Size]; var readCount = mapData.Read(resourceData, 0, resource.Size); Debug.Assert(readCount == resource.Size); resource.Data = resourceData; } var meshes = ModelResourceContainerProcessor.ProcessContainer(part, ModelShaderReferences); if(this.BoundingBoxes.Length > 0) { var bbIndex = 0; var maxBounds = new Vector3( this.BoundingBoxes[bbIndex].MaxX, this.BoundingBoxes[bbIndex].MaxY, this.BoundingBoxes[bbIndex].MaxZ); var minBounds = new Vector3( this.BoundingBoxes[bbIndex].MinX, this.BoundingBoxes[bbIndex].MinY, this.BoundingBoxes[bbIndex].MinZ); var maxUV = new Vector2( this.BoundingBoxes[bbIndex].MaxU, this.BoundingBoxes[bbIndex].MaxV); var minUV = new Vector2( this.BoundingBoxes[bbIndex].MinU, this.BoundingBoxes[bbIndex].MinV); var mesh = meshes[0]; for (var i = 0; i < mesh.Verticies.Length; i++) { var vert = mesh.Verticies[i]; var newPos = part.Flags.HasFlag(Properties.CompressedVerts) ? new Vector3( Decompress(vert.Position.X, minBounds.X, maxBounds.X), Decompress(vert.Position.Y, minBounds.Y, maxBounds.Y), Decompress(vert.Position.Z, minBounds.Z, maxBounds.Z) ) : vert.Position; var newTex = part.Flags.HasFlag(Properties.CompressedTexCoords) ? new Vector2( Decompress(vert.TexCoords.X, minUV.X, maxUV.X), Decompress(vert.TexCoords.Y, minUV.Y, maxUV.Y) ) : vert.TexCoords; // Workaround for JIT issue // https://github.com/dotnet/runtime/issues/1241 var newVert = new VertexFormat(newPos, newTex, vert.Normal, vert.Tangent, vert.Bitangent); mesh.Verticies[i] = newVert; } } part.Model = new MeshCollection(meshes); } }
//[InternalReferenceValue(540)] //public object[] MiscObject20Cao { get; set; } //[InternalReferenceValue(548)] //public object[] MiscObject21Cao { get; set; } //[InternalReferenceValue(556)] //public object[] MiscObject22Cao { get; set; } //[InternalReferenceValue(564)] //public object[] MiscObject23Cao { get; set; } public override void PopulateExternalData(MapStream reader) { foreach (var part in RenderChunks) { if (part.DataBlockRawOffset == uint.MaxValue) { // TODO: determine why this happens, and if it's expected? //Console.WriteLine("Bsp part with max DataBlock offset"); part.Model = new MeshCollection(new ModelMesh[0]); continue; } var headerOffset = new NormalOffset((int)part.DataBlockRawOffset); var mapData = reader.GetStream(headerOffset.Location); part.Header = BlamSerializer.Deserialize <ModelResourceBlockHeader>(mapData, headerOffset.Value); foreach (var resource in part.Resources) { var dataOffset = part.DataBlockRawOffset + 8 + part.DataPreambleSize + resource.Offset; mapData.Position = new NormalOffset((int)dataOffset).Value; var resourceData = new byte[resource.Size]; var readCount = mapData.Read(resourceData, 0, resource.Size); Debug.Assert(readCount == resource.Size); resource.Data = resourceData; } var meshes = ModelResourceContainerProcessor.ProcessContainer(part, ModelShaderReferences); part.Model = new MeshCollection(meshes); } foreach (var def in InstancedGeometryDefinitions) { if (def.DataBlockRawOffset == uint.MaxValue) { Console.WriteLine("InstancedGeometry with max DataBlock offset"); def.Model = new MeshCollection(new ModelMesh[0]); continue; } var headerOffset = new NormalOffset((int)def.DataBlockRawOffset); var mapData = reader.GetStream(headerOffset.Location); def.Header = BlamSerializer.Deserialize <ModelResourceBlockHeader>(mapData, headerOffset.Value); foreach (var resource in def.Resources) { var dataOffset = def.DataBlockRawOffset + 8 + def.DataPreambleSize + resource.Offset; mapData.Position = new NormalOffset((int)dataOffset).Value; var resourceData = new byte[resource.Size]; var readCount = mapData.Read(resourceData, 0, resource.Size); Debug.Assert(readCount == resource.Size); resource.Data = resourceData; } var meshes = ModelResourceContainerProcessor.ProcessContainer(def, ModelShaderReferences, "InstancedGeometry_" + def.DataBlockRawOffset); def.Model = new MeshCollection(meshes); } }
/// <summary> /// Decompresses the provided stream into the other stream, if the map has not already been decompressed. /// If the provided stream has already been decompressed, it will simply return the original stream /// </summary> public static Stream DecompressInline(Stream input) { using var compressed = input; if (compressed.CanSeek == false) { throw new NotSupportedException("Must be able to seek on compressed"); } var fourCC = compressed.ReadUInt32At(0); if (fourCC == DecompressedFourCC) { compressed.Position = 0; return(compressed); } if (fourCC != RealFourCC) { throw new Exception("Provided map stream was not valid"); } var decompressTo = new MemoryStream(); var info = BlamSerializer.Deserialize <H2mccCompressionSections>(compressed); var header = new Span <byte>(new byte[4096]); compressed.Position = 0; compressed.Read(header); decompressTo.WriteUInt32(DecompressedFourCC); decompressTo.Write(header.Slice(4)); foreach (var section in info.Sections) { if (section.Offset == 0 || section.Count == 0) { continue; } // Looks like compression is optional and count is negative when that happens if (section.Count < 0) { var realCount = -section.Count; var buf = copyPool.Rent(realCount); compressed.Position = section.Offset; var readCount = compressed.Read(buf); if (readCount != realCount) { copyPool.Return(buf); throw new Exception("Unable to read the amount of data required"); } decompressTo.Write(((Span <byte>)buf).Slice(0, readCount)); copyPool.Return(buf); } else { compressed.Seek(section.Offset + 2, SeekOrigin.Begin); using var deflate = new DeflateStream(compressed, CompressionMode.Decompress, leaveOpen: true); deflate.CopyTo(decompressTo); } } decompressTo.Position = 0; return(decompressTo); }