/// <summary> /// Reads JMP from a data stream. /// </summary> /// <param name="stream">The stream containing the JMP data.</param> public JMP(Stream stream) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(stream, DhEndian.Big); // Read JMP's Header uint entryCount = br.ReadU32(); uint fieldCount = br.ReadU32(); EntryOffset = br.ReadU32(); EntrySize = br.ReadU32(); // Read JMP's Fields Fields = new List <JField>(); for (int i = 0; i < fieldCount; i++) { Fields.Add(new JField(br)); } // Seek to beginning of file. br.Goto(0); // Read JMP's Entries Entries = new List <JEntry>(); for (int i = 0; i < entryCount; i++) { br.Goto(EntryOffset + (i * EntrySize)); Entries.Add(new JEntry(br, Fields)); } }
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 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); }
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> /// 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)); } }
/// <summary> /// Read a single entry from BAS. /// </summary> /// <param name="br">Binary Reader to use.</param> public BasEntry(DhBinaryReader br) { // Read Id. Id = br.ReadU32(); // Read Gain. Gain = br.ReadF32(); // Read Delay / Length. Delay = br.ReadF32(); // Read Pitch. Pitch = br.ReadF32(); // Read Unknown 1. Unknown1 = br.ReadS32(); // Read Balance. Balance = br.Read(); // Read Unknown 2. Unknown2 = br.Read(); // Read Unknown 3. Unknown3 = br.Read(); // Read Unknown 4. Unknown4 = br.Read(); // Read Padding. Padding = br.ReadU32s(2); }
/// <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!"); } }
/// <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); }
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 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 ANM from a data stream. /// </summary> /// <param name="stream">The stream containing the ANM data.</param> public ANM(Stream stream) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(stream, DhEndian.Big); // Reader ANM's Header. Version = br.ReadU8(); Loop = br.ReadBool8(); Unknown1 = br.ReadS16(); KeyFrameCount = br.ReadU32(); KeyFrameOffset = br.ReadU32(); Unknown2 = br.ReadS32(); Unknown3 = br.ReadS32(); Unknown4 = br.ReadS32(); /* * Keyframes - Interpolation type list: * https://ia800802.us.archive.org/9/items/GCN_SDK_Documentation/Game%20Engine%20Programming.pdf */ }
/// <summary> /// Reads JMP from a byte array. /// </summary> /// <param name="stream">The byte array containing the JMP data.</param> public JMP(byte[] data) { DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big); uint entryCount = br.ReadU32(); uint fieldCount = br.ReadU32(); uint entryOffset = br.ReadU32(); uint entrySize = br.ReadU32(); Fields = new List <JField>(); for (int i = 0; i < fieldCount; i++) { Fields.Add(new JField(br)); } br.Goto(0); Entries = new List <JEntry>(); for (int i = 0; i < entryCount; i++) { br.Goto(entryOffset + (i * entrySize)); Entries.Add(new JEntry(br, Fields)); } }
/// <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> /// 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> /// Reads PRM from a byte array. /// </summary> /// <param name="data">The byte array containing the PRM data.</param> public PRM(byte[] data) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big); // Read PRM's parameter entry count. uint entryCount = br.ReadU32(); // Define a new list to hold the parameter entries. Entries = new List <PrmEntry>(); // Loop through the parameter entries. for (int i = 0; i < entryCount; i++) { // Add the read parameter entry to the Entries list. Entries.Add(new PrmEntry(br)); } }
/// <summary> /// Reads GEB from a data stream. /// </summary> /// <param name="stream">The stream containing the GEB data.</param> public GEB(Stream stream) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(stream, DhEndian.Big); // Read GEB's sprite count. uint spriteCount = br.ReadU32(); // Define a new list to hold the sprite entries. Sprites = new List <GSprite>(); // Loop through the sprite entries. for (int i = 0; i < spriteCount; i++) { // Add the read sprite to the Sprites list. Sprites.Add(new GSprite(br)); } }
/// <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 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> /// Decompressing Yay0 compressed data. Full credits for this snippet goes to Daniel McCarthy: /// https://github.com/Daniel-McCarthy/Mr-Peeps-Compressor/blob/master/PeepsCompress/PeepsCompress/Algorithm%20Classes/YAY0.cs /// </summary> /// <param name="stream">Stream containing the Yay0 compressed data.</param> /// <returns>Decompressed data as a stream.</returns> public static Stream Decompress(Stream stream) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(stream, DhEndian.Big); // Define a list of bytes to hold the decompressed data. List <byte> output = new List <byte>(); // Make sure the magic is "Yay0" if (br.ReadU32() != 1499560240) { throw new Exception("No valid Yay0 signature was found!"); } int decompressedLength = br.ReadS32(); int compressedOffset = br.ReadS32(); int decompressedOffset = br.ReadS32(); int layoutBitsOffset; // Begin decompression. while (output.Count < decompressedLength) { // Define variable to hold the layout byte. byte LayoutByte = br.Read(); // Define variable to hold the individual layout bits. BitArray LayoutBits = new BitArray(new byte[1] { LayoutByte }); // Loop through the layout bits. for (int i = 7; i > -1 && (output.Count < decompressedLength); i--) { // The next layout bit is 1. (Uncompressed data) if (LayoutBits[i] == true) { // Yay0 Non-compressed Data Chunk: // Add one byte from decompressedOffset to decompressedData. // Define variable to hold the current layout bits offset. layoutBitsOffset = (int)stream.Position; // Seek to the compressed data offset. stream.Seek(decompressedOffset, SeekOrigin.Begin); // Read a byte and add it to the list of output bytes. output.Add(br.Read()); // Advance the decompressed offset by one byte. decompressedOffset++; // Return to the current layout bits offset. stream.Seek(layoutBitsOffset, SeekOrigin.Begin); } // The next layout bit is 0. (Compressed data) else { // Yay0 Compressed Data Chunk: // Total length is 2 bytes. // 4 bits = Length // 12 bits = Offset // Define variable to hold the current offset. layoutBitsOffset = (int)stream.Position; // Seek to the compressed data offset. stream.Seek(compressedOffset, SeekOrigin.Begin); // Read the first byte of the compressed data. byte byte1 = br.Read(); // Read the second byte of the compressed data. byte byte2 = br.Read(); // Advance the compressed data offset by 2 (Since we just read 2 bytes) compressedOffset += 2; // Get 4 upper bits of the first byte. byte byte1Upper = (byte)((byte1 & 0x0F)); // Get 4 lower bits of the first byte. byte byte1Lower = (byte)((byte1 & 0xF0) >> 4); int finalOffset = ((byte1Upper << 8) | byte2) + 1; int finalLength; // Compressed chunk length is higher than 17. if (byte1Lower == 0) { stream.Seek(decompressedOffset, SeekOrigin.Begin); finalLength = br.Read() + 0x12; // Advance the decompressed offset by one byte. decompressedOffset++; } // Compressed chunk length is lower or equal to 17. else { // The data chunk length is equals to the first byte's 4 lower bits + 2. finalLength = byte1Lower + 2; } // Add data for finalLength iterations. for (int j = 0; j < finalLength; j++) { // Add byte at offset (fileSize - finalOffset) to file. output.Add(output[output.Count - finalOffset]); } // Return to the current layout bits offset. stream.Seek(layoutBitsOffset, SeekOrigin.Begin); } } } // Return decompressed data. return(new MemoryStream(output.ToArray())); }
/// <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); }
/// <summary> /// Reads BIN from a stream. /// </summary> /// <param name="stream">The stream containing the BIN data.</param> public BIN(Stream stream) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(stream, DhEndian.Big); // Read bin version. Version = br.Read(); // Make sure the bin version is either 0x01 or 0x02. if (Version == 0x00 || Version > 0x02) { throw new Exception(string.Format("{0} is not a valid bin version!", Version.ToString())); } // Read bin model name. ModelName = br.ReadStr(11).Trim('\0'); // Define a new list to hold the bin's offsets. Offsets = new List <uint>(); // Loop through the bin's offsets. for (int i = 0; i < 21; i++) { // Read offset and add it to the offsets list. Offsets.Add(br.ReadU32()); } // Go to the bin textures offset. br.Goto(Offsets[0]); // Define a new list to hold the bin's textures. Textures = new List <BinTexture>(); // Loop through bin's textures. TODO: This is static for now, add automatic texture count. for (int i = 0; i < 3; i++) { // Read texture and add it to the textures list. Textures.Add(new BinTexture(br, Offsets[0])); } // Go to the bin materials offset. br.Goto(Offsets[1]); // Define a new list to hold the bin's materials. Materials = new List <BinMaterial>(); // Loop through bin's materials. TODO: This is static for now, add automatic material count. for (int i = 0; i < 3; i++) { // Read texture and add it to the materials list. Materials.Add(new BinMaterial(br)); } // Go to the bin positions offset. br.Goto(Offsets[2]); // Define a new list to hold the bin's positions. Positions = new List <Vector3>(); // Loop through bin's positions. TODO: Fix this; This is a pretty shitty way to calculate amount of bin positions ... for (int i = 0; i < ((Math.Floor((decimal)(Offsets[3] - Offsets[2])) / 6) - 1); i++) { // Skip 6 bytes to "simulate" reading a bin position. br.Skip(6); // Make sure the currenet position has not passed the normals offset. if (!(br.Position() > Offsets[3])) { // Go back 6 bytes as we just "simulated" to read a bin position. br.Goto(br.Position() - 6); // Read a position and add it to the positions list. Positions.Add(new Vector3(br.ReadF16(), br.ReadF16(), br.ReadF16())); } } // Go to the bin normals offset. br.Goto(Offsets[3]); // Define a new list to hold the bin's normals. Normals = new List <Vector3>(); // Loop through bin's normals. TODO: This is static for now, add automatic normal count. for (int i = 0; i < 69; i++) { // Read a normal and add it to the normals list. Normals.Add(new Vector3(br.ReadF32(), br.ReadF32(), br.ReadF32())); } // Go to the bin texture coordinates offset. br.Goto(Offsets[6]); // Define a new list to hold the bin's texture coordinates. TextureCoordinates = new List <BinTextureCoordinate>(); // Loop through bin's texture coordinates. TODO: This is static for now, add automatic texture coordinates count. for (int i = 0; i < 72; i++) { // Read a bin texture coordinates and add it to the texture coordinates list. TextureCoordinates.Add(new BinTextureCoordinate(br)); } // Go to the bin shaders offset. br.Goto(Offsets[10]); // Define a new list to hold the bin's shaders. Shaders = new List <BinShader>(); // Loop through bin's shaders. TODO: This is static for now, add automatic shader count. for (int i = 0; i < 3; i++) { // Read a bin shader and add it to the shaders list. Shaders.Add(new BinShader(br)); } // Go to the bin batches offset. br.Goto(Offsets[11]); // Define a new list to hold the bin's batches. Batches = new List <BinBatch>(); // Loop through bin's batches. TODO: This is static for now, add automatic batch count. for (int i = 0; i < 2; i++) { // Read a bin batch and add it to the batches list. Batches.Add(new BinBatch(br, Offsets[11])); } }
/// <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> /// 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); }
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(); }
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); }