/// <summary> /// Read a PrmEntry from PRM. /// </summary> /// <param name="br">Binary Reader to use.</param> public PrmEntry(DhBinaryReader br) { // Read Hash. Hash = br.ReadU16(); // Read NameLength. NameLength = br.ReadU16(); // Read Name. Name = br.ReadStr(NameLength); // Read ValueLength. ValueLength = br.ReadU32(); // Resolve Type from Hash. Type = PRMUtils.HashToType(Hash); // Check Type. switch (Type) { case PrmType.BYTE: // Read Value as a byte. Value = br.Read(); break; case PrmType.SHORT: // Read Value as a short. Value = br.ReadS16(); break; case PrmType.INT: // Read Value as a int. Value = br.ReadS32(); break; case PrmType.FLOAT: // Read Value as a float. Value = br.ReadF32(); break; case PrmType.RGBA: // Read Value as a Clr4. Value = br.ReadClr4(); break; case PrmType.VECTOR3: // Read Value as a Vector3. Value = br.ReadVec3(); break; default: throw new NotImplementedException("PRM parameter entry type is unknown!"); } }
public TXP(Stream stream) { DhBinaryReader br = new DhBinaryReader(stream, DhEndian.Big); //Ensure that Uknown 1 and 2 are 1 and 0 respectivley if (br.ReadU16() != 1) { throw new Exception("Unknown1 wasn't 1!"); } if (br.ReadU16() != 0) { throw new Exception("Unknown2 wasn't 0!"); } //Read the number of entries in the txp file ushort entryCount = br.ReadU16(); //Read the number of frames in each entry FrameCount = br.ReadU16(); //Skip unused frame offset br.ReadU32(); TXPEntries = new List <TXPEntry>(); for (int entry = 0; entry < entryCount; entry++) { TXPEntries.Add(new TXPEntry(br, FrameCount)); } }
/// <summary> /// Read a single texture from BIN. /// </summary> /// <param name="br">Binary Reader to use.</param> /// <param name="texturesOffset">Offset to textures.</param> public BinTexture(DhBinaryReader br, long texturesOffset) { // Read texture width. Width = br.ReadU16(); // Read texture height. Height = br.ReadU16(); // Read texture format. Format = br.ReadU8(); // Read texture unknown 1. (Flags?) Unknown1 = br.ReadU8(); // Read texture unknown 2. (Padding) Unknown2 = br.ReadU16(); // Read texture data offset. DataOffset = br.ReadU32(); // Save the current position. long currentPosition = br.Position(); // Go to the bin textures offset. br.Goto(texturesOffset); // Sail to the texture's data offset. br.Sail(DataOffset); // Read the texture's raw data. Data = br.Read((Width * Height) / 2); // Go to the previously saved offset. br.Goto(currentPosition); }
/// <summary> /// Reads TXP from a data stream. /// </summary> /// <param name="stream">The stream containing the TXP data.</param> public TXP(Stream stream) { // Define a new binary reader to read with. DhBinaryReader br = new DhBinaryReader(stream, DhEndian.Big); // Read Unknown 1. Unknown1 = br.ReadU16(); // Read Unknown 2. Unknown2 = br.ReadU16(); // Read Entry Count. EntryCount = br.ReadU16(); // Read Keyframe Count. KeyFrameCount = br.ReadU16(); // Read Keyframe Offset. KeyFrameOffset = br.ReadU32(); // Initialize the list to hold our entries. Entries = new List <TxpEntry>(); // Loop through entries. for (int i = 0; i < EntryCount; i++) { // Read entry. Entries.Add(new TxpEntry(br, KeyFrameCount)); } }
public MDLSampler(DhBinaryReader br) { TextureIndex = br.ReadU16(); UnknownIndex = br.ReadU16(); WrapU = (WrapMode)br.ReadU8(); WrapV = (WrapMode)br.ReadU8(); MinFilter = br.ReadU8(); MagFilter = br.ReadU8(); }
public MDLShape(DhBinaryReader br, List <MDLShapePacket> packets) { NormalFlag = br.ReadU8(); Unknown1 = br.ReadU8(); SurfaceFlag = br.ReadU8(); Unknown2 = br.ReadU8(); PacketCount = br.ReadU16(); PacketBeginIndex = br.ReadU16(); Packets = packets.GetRange(PacketBeginIndex, PacketCount); UseNbt = (NormalFlag > 0); }
public MDLNode(DhBinaryReader br, List <MDLDrawElement> drawElements) { MatrixIndex = br.ReadU16(); ChildIndex = br.ReadU16(); SiblingIndex = br.ReadU16(); Padding1 = br.ReadS16(); DrawElementCount = br.ReadU16(); DrawElementBeginIndex = br.ReadU16(); Padding2 = br.ReadS32(); DrawElements = drawElements.GetRange(DrawElementBeginIndex, DrawElementCount); }
public TXPEntry(DhBinaryReader br, ushort frameCount) { //Ensure that Uknown 1 is 1 if (br.ReadU16() != 1) { throw new Exception("Unknown1 wasn't 1!"); } //Read material index MaterialIndex = br.ReadS16(); if (br.ReadU32() != 0) { throw new Exception("Unknown2 wasn't 0!"); } //Read the frame data offset for this uint frameDataOffset = br.ReadU32(); TexObjIndicies = new short[frameCount]; //Save reader's current position and seek to the frame data br.SaveOffset(0); br.Goto(frameDataOffset); //Fill TexObjIndicies for each frame for (int frame = 0; frame < frameCount; frame++) { TexObjIndicies[frame] = br.ReadS16(); } br.LoadOffset(0); }
/// <summary> /// Read a single sequence from TMB. /// </summary> /// <param name="br">The binary reader to read with.</param> public TMBSequence(DhBinaryReader br) { // Read name. Name = br.ReadFixedStr(28); // Read keyframe count. KeyFrameCount = br.ReadU32(); // Read start index. StartIndex = br.ReadU16(); // Read keyframe size. KeyFrameSize = br.ReadU16(); // Define a new list to hold our keyframes. KeyFrames = new List <TIMKeyFrame>(); }
/// <summary> /// Read a single field from JMP. /// </summary> /// <param name="br">Binary Reader to use.</param> public JField(DhBinaryReader br) { Hash = br.ReadU32(); Bitmask = br.ReadU32(); Offset = br.ReadU16(); Shift = br.ReadS8(); Type = (JFieldType)br.ReadU8(); Name = JMPUtils.HashToName(Hash); }
/// <summary> /// Read a single batch from BIN. /// </summary> /// <param name="br">The binaryreader to write with.</param> /// <param name="batchesOffset">Offset to batches.</param> public Batch(DhBinaryReader br, long batchesOffset) { // Read face count. FaceCount = br.ReadU16(); // Read primitive list size. ListSize = br.ReadS16(); // Read vertex attributes. VertexAttributes = (Attributes)br.ReadU32(); // Read UseNormals flag. UseNormals = br.ReadBool8(); // Read Position Winding. Positions = br.Read(); // Read UV Count. UvCount = br.Read(); // Read UseNBT flag. UseNBT = br.ReadBool8(); // Read Primitive offset. PrimitiveOffset = br.ReadU32(); // Read Unknown 1. (Padding?) Unknown1 = br.ReadS32s(2); // Save the current position. long currentPosition = br.Position(); // Go to the batch's primitive offset offset. br.Goto(batchesOffset + PrimitiveOffset); // Define list to hold batch's primitives. Primitives = new List <Primitive>(); // Define int to keep track of the amount of faces read. int readFaces = 0; // Read primitives until batch's face count has been reached. while ((readFaces < FaceCount) && (br.Position() < (batchesOffset + PrimitiveOffset + (ListSize << 5)))) { // Read primitive. Primitive binPrimitive = new Primitive(br, VertexAttributes, UseNBT); // Add the primitive to the batch's primitives. Primitives.Add(binPrimitive); // Add primitive's face count to the read faces counter. readFaces += binPrimitive.FaceCount; } // Go to the previously saved offset. br.Goto(currentPosition); }
/// <summary> /// Read a single triangle group from MP. /// </summary> /// <param name="br">The BinaryReader to read with.</param> public TriangleGroup(DhBinaryReader br) { // Define temporary list of ushorts to hold the indices. List <ushort> indices = new List <ushort>(); // We'll read untill we read 0xFFFF, that means the end of this triangle group. while (br.ReadU16() != 0xFFFF) { // We'll go two bytes back, since we checked for 0xFFFF. br.Sail(-2); // Read a ushort, and add it to the list of indices. indices.Add(br.ReadU16()); } // Set the indices array to the ones we've read. Indices = indices.ToArray(); }
public MDLShapePacket(DhBinaryReader br) { DataOffset = br.ReadU32(); DataSize = br.ReadU32(); Unknown = br.ReadS16(); MatrixCount = br.ReadU16(); MatrixIndices = br.ReadU16s(10); PacketData = new List <ShapePacketData>(); Data = br.ReadAt(DataOffset, (int)DataSize); }
/// <summary> /// Read a single texture from BIN. /// </summary> /// <param name="br">The BinaryReader to read with..</param> public UnusedTexture(DhBinaryReader br, uint textureOffset) { // Read texture width. Width = br.ReadU16(); // Read texture height. Height = br.ReadU16(); // Read texture format. Format = (TextureFormat)br.Read(); // Read texture alpha flag (Unsure, but seems logical) AlphaFlag = br.Read(); // Read texture unknown 1. (Padding?) Unknown1 = 0; // Read texture data offset. DataOffset = br.ReadU32(); }
/// <summary> /// Reads TMB from a byte array. /// </summary> /// <param name="data">The byte array containing the TMB data.</param> public TMB(byte[] data) { // Define a new binary reader to read with. DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big); // Read sequence count. SequenceCount = br.ReadU16(); // Read timing duration. Duration = br.ReadU16(); // Read sequence data offset. SequenceDataOffset = br.ReadU32(); // Define a new list to hold our sequences. Sequences = new List <TMBSequence>(); // Goto sequence data offset. br.Goto(SequenceDataOffset); // Loop through sequences within this bank. for (int i = 0; i < SequenceCount; i++) { // Read a sequence and add it to the list of sequences. Sequences.Add(new TMBSequence(br)); } // Loop through sequences within this bank. for (int i = 0; i < SequenceCount; i++) { // Go to this sequence's keyframe data. br.Goto(8 + ((Sequences[i].StartIndex * 4))); // Loop through keyframe's within this sequence. for (int y = 0; y < Sequences[i].KeyFrameCount; y++) { // Read this keyframe and add it to the sequence's list of the keyframes. Sequences[i].KeyFrames.Add(new TIMKeyFrame(br, Sequences[i].KeyFrameSize)); } } }
public MDLVertex(DhBinaryReader br, MDLHeader header, bool useNbt) { MatrixIndex = br.ReadS8(); Tex0MatrixIndex = br.ReadS8(); Tex1MatrixIndex = br.ReadS8(); PositionIndex = br.ReadU16(); if (header.NormalCount > 0) { NormalIndex = br.ReadU16(); } if (useNbt) { //TangentIndex = br.ReadU16(); //BiTangentIndex = br.ReadU16(); } if (header.ColorCount > 0) { ColorIndex = br.ReadU16(); } if (header.TextureCoordinateCount > 0) { TexCoordIndex = br.ReadU16(); } }
private static byte[] ReadRGB565(DhBinaryReader br, uint width, uint height) { // Buffer to store our decoded data. byte[] decoded = new byte[width * height * 4]; // Loop through blocks y. for (int yBlock = 0; yBlock < (height / 4); yBlock++) { // Loop through blocks x. for (int xBlock = 0; xBlock < (width / 4); xBlock++) { // Loop through pixels in block y. for (int pY = 0; pY < 4; pY++) { // Loop through pixels in block x. for (int pX = 0; pX < 4; pX++) { // Determine if pixel is oob (x || y). if ((xBlock * 4 + pX >= width) || (yBlock * 4 + pY >= height)) { // Skip. continue; } // Calculate offset for decoded data. int offset = (int)(4 * (width * ((yBlock * 4) + pY) + (xBlock * 4) + pX)); // Read current pixel. ushort pixel = br.ReadU16(); // Declare three bytes to hold our R, G, B components. byte r = (byte)((((pixel & 0xF100) >> 11) << 3) | (((pixel & 0xF100) >> 11) >> 2)); byte g = (byte)((((pixel & 0x7E0) >> 5) << 2) | (((pixel & 0x7E0) >> 5) >> 4)); byte b = (byte)(((pixel & 0x1F) << 3) | ((pixel & 0x1F) >> 2)); // Store decoded data in buffer. decoded[offset + 0] = b; decoded[offset + 1] = g; decoded[offset + 2] = r; decoded[offset + 3] = 0xFF; } } } } return(decoded); }
/// <summary> /// Read a single entry in TXP. /// </summary> /// <param name="br">The binaryreader to read with.</param> /// <param name="keyFrameCount">The amount of keyframes in each entry.</param> public TxpEntry(DhBinaryReader br, ushort keyFrameCount) { // Read Unknown 1. Unknown1 = br.ReadS16(); //Read Material Index. MaterialIndex = br.ReadU16(); // Read Unknown 2. Unknown2 = br.ReadS32(); // Read Indices Offset. IndicesOffset = br.ReadU32(); // Read Indices. Indices = br.ReadU16sAt(IndicesOffset, keyFrameCount).ToList(); }
/// <summary> /// Method for reading IA8 encoded data. /// </summary> /// <param name="br">BinaryReader to read with.</param> /// <param name="width">Texture width.</param> /// <param name="height">Texture height.</param> /// <returns>Texture as a stream containing RGBA data.</returns> private static byte[] ReadIA8(DhBinaryReader br, ushort width, ushort height) { // Buffer to store our decoded data. byte[] decoded = new byte[width * height * 4]; // Loop through blocks y. for (int y = 0; y < (height / 4); y++) { // Loop through blocks x. for (int x = 0; x < (width / 4); x++) { // Loop through pixels in block y. for (int yx = 0; yx < 4; yx++) { // Loop through pixels in block x. for (int xy = 0; xy < 4; xy++) { // Determine if pixel is oob (x || y). if ((x * 4 + xy >= width) || (y * 4 + yx >= height)) { // Skip. continue; } // Calculate offset for decoded data. uint offset = (uint)(4 * (width * ((y * 4) + yx) + (x * 4) + xy)); // Read current pixel. ushort data = br.ReadU16(); // Store decoded data in buffer. decoded[offset + 3] = (byte)data; decoded[offset + 2] = (byte)(data >> 8); decoded[offset + 1] = (byte)(data >> 8); decoded[offset + 0] = (byte)(data >> 8); } } } } // Return the texture as RGBA. return(decoded); }
/// <summary> /// Read a single field from JMP. /// </summary> /// <param name="br">Binary Reader to use.</param> public JField(DhBinaryReader br) { // Read field's hash. Hash = br.ReadU32(); // Read field's bitmask. Bitmask = br.ReadU32(); // Read field's offset. Offset = br.ReadU16(); // Read field's shift. Shift = br.ReadS8(); // Read field's type. Type = (JFieldType)br.ReadU8(); // Resolve field's hash to get field name. Name = JMPUtils.HashToName(Hash); }
/// <summary> /// Reads BAS from a data stream. /// </summary> /// <param name="data">The byte array containing the BAS data.</param> public BAS(byte[] data) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big); // Read entry count. EntryCount = br.ReadU16(); // Read unknown 1. Unknown1 = br.Read(); // Read padding. (5 byte) Padding = br.Read(5); // Define a new list to hold the BAS entries. Entries = new List <BasEntry>(); // Loop through the BAS entries. for (int i = 0; i < EntryCount; i++) { // Add the read entry to the Entries list. Entries.Add(new BasEntry(br)); } }
/// <summary> /// Read a single batch from BIN. /// </summary> /// <param name="br">Binary Reader to use.</param> /// <param name="batchesOffset">Offset to batches.</param> public BinBatch(DhBinaryReader br, long batchesOffset) { // Read face count. FaceCount = br.ReadU16(); // Read primitive list size. ListSize = (ushort)(br.ReadS16() << 5); // Read vertex attributes. VertexAttributes = (BinBatchAttributes)br.ReadU32(); // Read UseNormals flag. UseNormals = br.Read(); // Read Position Winding. Positions = br.Read(); // Read UV Count. UvCount = br.Read(); // Read UseNBT flag. UseNBT = br.Read(); // Read Primitive offset. PrimitiveOffset = br.ReadU32(); // Define array to hold Unknown 1 values. Unknown1 = new int[2]; // Loop through Unknown 1 values. for (int i = 0; i < 2; i++) { // Read current Unknown 1 value. Unknown1[i] = br.ReadS32(); } // Save the current position. long currentPosition = br.Position(); // Go to the bin batches offset. br.Goto(batchesOffset); // Sail to the batches's primitive offset. br.Sail(PrimitiveOffset); // Define list to hold batch's primitives. Primitives = new List <BinPrimitive>(); // Define int to hold amount of faces read. int readFaces = 0; // Read primitives until batch's face count has been reached. while (readFaces < FaceCount && br.Position() < (batchesOffset + PrimitiveOffset + ListSize)) { // Read primitive. BinPrimitive binPrimitive = new BinPrimitive(br, UseNBT, UvCount, VertexAttributes); // Add the primitive to the batch's primitives. Primitives.Add(binPrimitive); // Add primitive's face count to the read faces counter. readFaces += binPrimitive.FaceCount; } // Go to the previously saved offset. br.Goto(currentPosition); }
/// <summary> /// Reads BTI using a BinaryReader. (BinTexture Format) /// </summary> /// <param name="br">The BinaryReader to use.</param> public BTI(DhBinaryReader br, uint textureHeader) { // Set Width. Width = br.ReadU16(); // Set Height. Height = br.ReadU16(); // Set Texture Format. Format = (TextureFormat)br.Read(); // Set Alpha Flag. AlphaFlag = br.Read(); // Set WrapS. WrapS = WrapMode.ClampToEdge; // Set WrapT. WrapT = WrapMode.ClampToEdge; // Set Palette Format. PaletteFormat = PaletteFormat.RGB565; // Set Palette Count. PaletteCount = 0; // Set Palette Offset. PaletteOffset = 0; // Set Unknown 1. (Padding?) Unknown1 = 0; // Set MinFilterMode. MinFilterMode = FilterMode.Linear; // Set MagFilterMode. MagFilterMode = FilterMode.Linear; // Set MinLOD. MinLOD = 0; // Set MagLOD. MagLOD = 1; // Set MipMap Count. MipMapCount = 0; // Set LodBias. LodBias = 0; // Skip 2 bytes of padding. br.Skip(2); // Set Data Offset. DataOffset = br.ReadU32(); // Read data. int length = 0; switch (Format) { case TextureFormat.C4: length = Width * Height * 8; break; case TextureFormat.C8: length = Width * Height * 8; break; default: length = Width * Height * 4; break; } Data = br.ReadAt((textureHeader) + DataOffset, length); }
/// <summary> /// Reads BTI using a BinaryReader. (BinTexture Format) /// </summary> /// <param name="br">The BinaryReader to use.</param> public BTI(DhBinaryReader br, uint textureOffset, uint textureLocationOffset) { // Set Texture Format. byte format = br.Read(); // Texture Formats IDs are different in MDL's for some reason. switch (format) { case 3: Format = TextureFormat.I4; break; case 4: Format = TextureFormat.I8; break; case 6: Format = TextureFormat.IA8; break; case 7: Format = TextureFormat.RGB565; break; case 8: Format = TextureFormat.RGB5A3; break; case 10: Format = TextureFormat.CMPR; break; default: throw new Exception($"Texture format {format} is not supported yet!"); } // Set Alpha Flag. AlphaFlag = br.Read(); // Set Width. Width = br.ReadU16(); // Set Height. Height = br.ReadU16(); // Skip 26 bytes of padding. br.Skip(26); // Read data. int length = 0; switch (Format) { case TextureFormat.C4: length = Width * Height * 8; break; case TextureFormat.C8: length = Width * Height * 8; break; default: length = Width * Height * 4; break; } Data = br.Read(length); }
public static VirtDirectory LoadRarc(byte[] data) { if (Yay0.IsCompressed(data)) { data = Yay0.Decompress(data); } DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big); if (br.ReadStr(4) != "RARC") { throw new InvalidDataException("No valid RARC signature was found!"); } List <RarcNode> nodes = new List <RarcNode>(); List <RarcEntry> entries = new List <RarcEntry>(); // read header // RARC here br.Skip(4); br.Skip(4); var dataOffset = br.ReadU32() + 0x20; br.Skip(4); br.Skip(4); br.Skip(4); br.Skip(4); // read infoblock var NodeCount = br.ReadU32(); var NodeOffset = br.ReadU32() + 0x20; var EntryCount = br.ReadU32(); var EntryOffset = br.ReadU32() + 0x20; br.Skip(4); var StringTableOffset = br.ReadU32() + 0x20; br.Skip(2); br.Skip(2); br.Skip(4); br.Goto(EntryOffset); // read entries for (int i = 0; i < EntryCount; i++) { RarcEntry entry = new RarcEntry() { Id = br.ReadU16(), NameHash = br.ReadU16(), Type = br.ReadU16(), NameOffset = br.ReadU16(), DataOffset = br.ReadU32(), DataLength = br.ReadU32() }; if (entry.Type == 0x1100) { entry.Data = br.ReadAt(dataOffset + entry.DataOffset, (int)entry.DataLength); } entry.MemoryPointer = br.ReadU32(); entry.Name = br.ReadStrAt(StringTableOffset + entry.NameOffset); entries.Add(entry); } br.Goto(NodeOffset); // read nodes for (int i = 0; i < NodeCount; i++) { RarcNode rarcNode = new RarcNode() { Id = br.ReadStr(4), NameOffset = br.ReadU32(), NameHash = br.ReadU16(), EntryCount = br.ReadU16(), FirstEntryIndex = br.ReadU32() }; rarcNode.Name = br.ReadStrAt(StringTableOffset + rarcNode.NameOffset); rarcNode.Entries = entries.GetRange((int)rarcNode.FirstEntryIndex, (int)rarcNode.EntryCount); nodes.Add(rarcNode); } List <VirtDirectory> virtDirectories = new List <VirtDirectory>(nodes.Count); foreach (RarcNode rarcNode in nodes) { virtDirectories.Add(new VirtDirectory(rarcNode.Name, Guid.Empty)); } for (int i = 0; i < nodes.Count; i++) { RarcNode rarcNode = nodes[i]; for (int y = 0; y < nodes[i].Entries.Count; y++) { if (rarcNode.Entries[y].Name == "." || rarcNode.Entries[y].Name == "..") { continue; } if (rarcNode.Entries[y].Type == (ushort)NodeType.Directory) { var virtDirectory = virtDirectories[(int)rarcNode.Entries[y].DataOffset]; virtDirectory.ParentGuid = virtDirectories[i].Guid; virtDirectory.Name = rarcNode.Entries[y].Name; virtDirectories[i].Children.Add(virtDirectory); } else { VirtFile virtFile = new VirtFile(rarcNode.Entries[y].Name, virtDirectories[i].Guid, rarcNode.Entries[y].Data); virtDirectories[i].Children.Add(virtFile); } } } return(virtDirectories.Count > 0 ? virtDirectories[0] : null); }
/// <summary> /// Reads BTI from a stream. /// </summary> /// <param name="stream">The stream containing the BTI data.</param> public BTI(Stream stream) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(stream, DhEndian.Big); // Read Texture Format. Format = (TextureFormat)br.Read(); // Read Alpha Flag. AlphaFlag = br.Read(); // Read Width. Width = br.ReadU16(); // Read Height. Height = br.ReadU16(); // Read WrapS. WrapS = (WrapMode)br.Read(); // Read WrapT. WrapT = (WrapMode)br.Read(); // Read Palette Format. PaletteFormat = (PaletteFormat)br.ReadU16(); // Read Palette Count. PaletteCount = br.ReadU16(); // Read Palette Offset. PaletteOffset = br.ReadU32(); // Read Unknown 1. Unknown1 = br.ReadU32(); // Read MinFilterMode. MinFilterMode = (FilterMode)br.Read(); // Read MagFilterMode. MagFilterMode = (FilterMode)br.Read(); // Read MinLOD. MinLOD = br.ReadU16(); // Read MagLOD. MagLOD = br.Read(); // Read MipMap Count. MipMapCount = br.Read(); // Read LodBias. LodBias = br.ReadU16(); // Read DataOffset. DataOffset = br.ReadU32(); // Read data. Data = br.Read((Width * Height) / 2); // Read Data. //Data = br.ReadAt(DataOffset, (Width * Height) / 4); }
public MDL(byte[] data) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big); Header = new MDLHeader(br); br.Goto(Header.MatricesOffset); Matrices = new Mat4[Header.JointCount + Header.WeightCount]; for (int i = 0; i < Matrices.Length; i++) { Matrices[i] = Mat4.Identity; } for (int i = 0; i < Header.JointCount; i++) { float[] matrix = br.ReadF32s(12); Matrices[i] = new Mat4() { Row1 = new Vec4(matrix[0], matrix[1], matrix[2], matrix[3]), Row2 = new Vec4(matrix[4], matrix[5], matrix[6], matrix[7]), Row3 = new Vec4(matrix[8], matrix[9], matrix[10], matrix[11]), Row4 = new Vec4(0, 0, 0, 1), }; } br.Goto(Header.PositionOffset); Positions = br.ReadVec3s(Header.PositionCount).ToList(); br.Goto(Header.NormalOffset); Normals = br.ReadVec3s(Header.NormalCount).ToList(); br.Goto(Header.ColorOffset); Colors = br.ReadClr4s(Header.ColorCount).ToList(); br.Goto(Header.TextureCoordinateOffset); TextureCoordinates = br.ReadVec2s(Header.TextureCoordinateCount).ToList(); br.Goto(Header.PacketOffset); Packets = new List <MDLShapePacket>(); for (int i = 0; i < Header.PacketCount; i++) { Packets.Add(new MDLShapePacket(br)); } br.Goto(Header.ShapeOffset); Shapes = new List <MDLShape>(); for (int i = 0; i < Header.ShapeCount; i++) { Shapes.Add(new MDLShape(br, Packets)); } foreach (MDLShape shape in Shapes) { ushort[] matrixIndices = new ushort[10]; foreach (MDLShapePacket packet in shape.Packets) { for (int m = 0; m < packet.MatrixCount; m++) { if (packet.MatrixIndices[m] == ushort.MaxValue) { continue; } matrixIndices[m] = packet.MatrixIndices[m]; } DhBinaryReader reader = new DhBinaryReader(packet.Data, DhEndian.Big); while (reader.Position() < packet.DataSize) { ShapePacketData packetData = new ShapePacketData(); packetData.PrimitiveType = reader.ReadU8(); if (packetData.PrimitiveType == 0x00) { continue; } packetData.VertexCount = reader.ReadU16(); for (int i = 0; i < packetData.VertexCount; i++) { MDLVertex vertex = new MDLVertex(reader, Header, shape.UseNbt); if (vertex.MatrixIndex != -1) { vertex.MatrixDataIndex = matrixIndices[(vertex.MatrixIndex / 3)]; } packetData.Vertices.Add(vertex); } packet.PacketData.Add(packetData); } } } br.Goto(Header.TextureLocationOffset); Textures = new List <BTI>(); for (int i = 0; i < Header.TextureCount; i++) { uint offset = br.ReadU32(); long currentPosition = br.Position(); br.Goto(offset); BTI bti = new BTI(br, offset, Header.TextureLocationOffset); Textures.Add(bti); br.Goto(currentPosition); } br.Goto(Header.SamplerOffset); Samplers = new List <MDLSampler>(); for (int i = 0; i < Header.SamplerCount; i++) { Samplers.Add(new MDLSampler(br)); } br.Goto(Header.MaterialOffset); Materials = new List <MDLMaterial>(); for (int i = 0; i < Header.MaterialCount; i++) { Materials.Add(new MDLMaterial(br, Samplers)); } br.Goto(Header.DrawElementOffset); DrawElements = new List <MDLDrawElement>(); for (int i = 0; i < Header.DrawElementCount; i++) { DrawElements.Add(new MDLDrawElement(br, Materials, Shapes)); } br.Goto(Header.NodeOffset); Nodes = new List <MDLNode>(); for (int i = 0; i < Header.NodeCount; i++) { Nodes.Add(new MDLNode(br, DrawElements)); } }
/// <summary> /// Method for reading RBG5A3 encoded data. /// </summary> /// <param name="br">BinaryReader to read with.</param> /// <param name="width">Texture width.</param> /// <param name="height">Texture height.</param> /// <returns>Texture as a stream containing RGBA data.</returns> private static byte[] ReadRGB5A3(DhBinaryReader br, ushort width, ushort height) { // Buffer to store our decoded data. byte[] decoded = new byte[width * height * 4]; // Loop through blocks y. for (int y = 0; y < (height / 4); y++) { // Loop through blocks x. for (int x = 0; x < (width / 4); x++) { // Loop through pixels in block y. for (int yx = 0; yx < 4; yx++) { // Loop through pixels in block x. for (int xy = 0; xy < 4; xy++) { // Determine if pixel is oob (x || y). if ((x * 4 + xy >= width) || (y * 4 + yx >= height)) { // Skip. continue; } // Read current pixel. ushort pixel = br.ReadU16(); // Calculate offset for decoded data. int offset = 4 * (width * ((y * 4) + yx) + (x * 4) + xy); // Declare four bytes to hold our R, G, B, A components. byte r, g, b, a; // Determine if there is any alpha bits. if ((pixel & 0x8000) == 0x8000) { // Alpha component. (No Alpha) a = 0xFF; // Red component. r = (byte)((pixel & 0x7C00) >> 10); r = (byte)((r << 3) | (r >> 2)); // Green component. g = (byte)((pixel & 0x3E0) >> 5); g = (byte)((g << 3) | (g >> 2)); // Blue component. b = (byte)(pixel & 0x1F); b = (byte)((b << 3) | (b >> 2)); } else { // Alpha component. a = (byte)((pixel & 0x7000) >> 12); a = (byte)((a << 2) | (a << 2) | (a >> 1)); // Red component. r = (byte)((pixel & 0xF00) >> 8); r = (byte)((r << 4) | r); // Green component. g = (byte)((pixel & 0xF0) >> 4); g = (byte)((g << 4) | g); // Blue component. b = (byte)(pixel & 0xF); b = (byte)((b << 4) | b); } // Store decoded data in buffer. decoded[offset + 0] = a; decoded[offset + 1] = b; decoded[offset + 2] = g; decoded[offset + 3] = r; } } } } // Return the texture as RGBA. return(decoded); }
/// <summary> /// Read a single graph object from BIN. /// </summary> /// <param name="br">Binary Reader to use.</param> /// <param name="graphObjectOffset">Offset to the graph objects.</param> public GraphObject(DhBinaryReader br, uint graphObjectOffset) // 112 bytes long { // Read Parent Index. ParentIndex = br.ReadS16(); // Read Child Index. ChildIndex = br.ReadS16(); // Read Next Index. NextIndex = br.ReadS16(); // Read Previous Index. PreviousIndex = br.ReadS16(); // Read Render Flags. RenderFlags = (GraphObjectRenderFlags)br.ReadU16(); // Unknown 1. (Padding?) Unknown1 = br.ReadU16(); // Read Scale. Scale = br.ReadVec3(); // Read Rotation. Rotation = br.ReadVec3(); // Read Position Position = br.ReadVec3(); // Read Bounding Box Minimum. BoundingBoxMinimum = br.ReadVec3(); // Read Bounding Box Maximum. BoundingBoxMaximum = br.ReadVec3(); // Read Bounding Sphere Radius. BoundingSphereRadius = br.ReadF32(); // Read Parent Index. PartCount = br.ReadS16(); // Unknown 3. (Padding?) Unknown3 = br.ReadU16(); // Read Parent Index. PartOffset = br.ReadS32(); // Unknown 4. (Padding?) Unknown4 = br.ReadU32s(7); // Initialize a new list to hold parts. Parts = new List <BinGraphObjectPart>(); // Offset to continue reading from. long currentPosition = br.Position(); // Goto graphobject's parts. br.Goto(graphObjectOffset + PartOffset); // Loop through parts. for (int i = 0; i < PartCount; i++) { // Read part and add it to the list of parts. Parts.Add(new BinGraphObjectPart(br)); } // Go back to return offset we saved earlier. br.Goto(currentPosition); }
public MDLHeader(DhBinaryReader br) { // magic Magic = br.ReadU32(); // counts FaceCount = br.ReadU16(); Padding = br.ReadS16(); NodeCount = br.ReadU16(); PacketCount = br.ReadU16(); WeightCount = br.ReadU16(); JointCount = br.ReadU16(); PositionCount = br.ReadU16(); NormalCount = br.ReadU16(); ColorCount = br.ReadU16(); TextureCoordinateCount = br.ReadU16(); Padding2 = br.ReadS64(); TextureCount = br.ReadU16(); Padding3 = br.ReadS16(); SamplerCount = br.ReadU16(); DrawElementCount = br.ReadU16(); MaterialCount = br.ReadU16(); ShapeCount = br.ReadU16(); Padding4 = br.ReadS32(); // offsets NodeOffset = br.ReadU32(); PacketOffset = br.ReadU32(); MatricesOffset = br.ReadU32(); WeightOffset = br.ReadU32(); JointOffset = br.ReadU32(); WeightCountTableOffset = br.ReadU32(); PositionOffset = br.ReadU32(); NormalOffset = br.ReadU32(); ColorOffset = br.ReadU32(); TextureCoordinateOffset = br.ReadU32(); Padding5 = br.ReadS64(); TextureLocationOffset = br.ReadU32(); Padding6 = br.ReadS32(); MaterialOffset = br.ReadU32(); SamplerOffset = br.ReadU32(); ShapeOffset = br.ReadU32(); DrawElementOffset = br.ReadU32(); Padding7 = br.ReadS64(); }