/// <summary> /// Read a single grid index from MP. /// </summary> /// <param name="br">Binary Reader to use.</param> public GridIndex(DhBinaryReader br) { // Read TotalTriangleGroupIndex. TotalTriangleGroupIndex = br.ReadS32(); // Read FloorTriangleGroupIndex. FloorTriangleGroupIndex = br.ReadS32(); }
/// <summary> /// Read a single material from BIN. /// </summary> /// <param name="br">Binary Reader to use.</param> public BinMaterial(DhBinaryReader br) { // Read Index. Index = br.ReadS16(); // Read Unknown 1. (Unused index?) Unknown1 = br.ReadS16(); // Read U-Wrapping. WrapU = br.Read(); // Read V-Wrapping. WrapV = br.Read(); // Read Unknown 2. (Flags?) Unknown2 = br.ReadS16(); // Define a array to hold the unknown 3 values. Unknown3 = new int[3]; // Loop through the unknown 3 values. for (int i = 0; i < Unknown3.Length; i++) { // Write the current unknown value. Unknown3[i] = br.ReadS32(); } }
/// <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 single entry from JMP. /// </summary> /// <param name="br">Binary Reader to use.</param> /// <param name="fields">List of fields in JMP.</param> public JEntry(DhBinaryReader br, List <JField> fields) { long currentPosition = br.Position(); Values = new Dictionary <string, object>(); for (int i = 0; i < fields.Count; i++) { br.Sail(fields[i].Offset); object value; switch (fields[i].Type) { case JFieldType.INTEGER: value = ((br.ReadS32() & fields[i].Bitmask) >> fields[i].Shift); break; case JFieldType.STRING: value = br.ReadFixedStr(32); break; case JFieldType.FLOAT: value = br.ReadF32(); break; default: throw new InvalidDataException($"{fields[i].Type} is not a valid jmp entry type!"); } Values.Add(fields[i].Name, value); br.Goto(currentPosition); } }
/// <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 SpritePoint from GEB. /// </summary> /// <param name="br">Binary Reader to use.</param> public SpritePoint(DhBinaryReader br) { // Read SpritePoint's Position. Position = new Vector2(br.ReadF32(), br.ReadF32()); // Read SpritePoint's Unknown 1. Unknown1 = br.ReadS32(); }
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 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); }
/// <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> /// Read a GSprite from GEB. /// </summary> /// <param name="br">Binary Reader to use.</param> public GSprite(DhBinaryReader br) { // Read GSprite's Unknown 1. Unknown1 = br.ReadS16(); // Read GSprite's Unknown 2. Unknown2 = br.ReadS16(); // Read GSprite's RGBA. RGBA = br.ReadS32(); // Define a new list to hold the GSprite's points. Points = new List <SpritePoint>(); // Loop through GSprite's points. for (int i = 0; i < 4; i++) { // Read point and add it to the spritepoint list. Points.Add(new SpritePoint(br)); } // Define a array to hold the unknown values. Unknown3 = new int[10]; // Loop through the unknown values. for (int i = 0; i < Unknown3.Length; i++) { // Read the current unknown value. Unknown3[i] = br.ReadS32(); } // Read GSprite's Unknown 4. Unknown4 = br.ReadF32(); // Read GSprite's Unknown 5. Unknown5 = br.ReadF32(); // Read GSprite's Unknown 6. Unknown6 = br.ReadS32(); }
/// <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 entry from JMP. /// </summary> /// <param name="br">Binary Reader to use.</param> /// <param name="fields">List of fields in JMP.</param> public JEntry(DhBinaryReader br, List <JField> fields) { // Save the current position. long currentPosition = br.Position(); // Define a new object array to hold entry's values. Values = new object[fields.Count]; // Loop through each field in the JMP. for (int i = 0; i < fields.Count; i++) { // Seek from the current position to value's offset in the entry. br.Sail(fields[i].Offset); // Define a new object to hold our data. object value; // Check which type the current value is. switch (fields[i].Type) { case JFieldType.INTEGER: // Read the data as a integer. value = ((br.ReadS32() & fields[i].Bitmask) >> fields[i].Shift); break; case JFieldType.STRING: // Read the data as a 32-byte long string. value = br.ReadStr32(); break; case JFieldType.FLOAT: // Read the data as a float32. value = br.ReadF32(); break; default: // Something went horribly wrong. throw new InvalidDataException(); } // Set the value of this entry's value's data to the value we just read. Values[i] = value; // Seek back to the position we saved earlier. br.Goto(currentPosition); } }
/// <summary> /// Read a single shader from BIN. /// </summary> /// <param name="br">Binary Reader to use.</param> public BinShader(DhBinaryReader br) { // Read Unknown 1. Unknown1 = br.Read(); // Read Unknown 2. Unknown2 = br.Read(); // Read Unknown 3. Unknown3 = br.Read(); // Read Tint. Tint = br.ReadS32(); // Read Unknown 4. (Padding) Unknown4 = br.Read(); // Define a new array to hold the Material Indices. MaterialIndices = new short[8]; // Loop through Material Indices. for (int i = 0; i < 8; i++) { // Read a material index and store it in Material Indices array. MaterialIndices[i] = br.ReadS16(); } // Define a new array to hold Unknown 5. (Indices?) Unknown5 = new short[8]; // Loop through Unknown 5. for (int i = 0; i < 8; i++) { // Read a Unknown 5 value and store it in Unknown5 array. Unknown5[i] = br.ReadS16(); } }
/// <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); }
/// <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 MP from a stream. /// </summary> /// <param name="stream">The stream containing the MP data.</param> public MP(Stream stream) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(stream, DhEndian.Big); // Read Grid Scale. GridScale = new Vector3(br.ReadF32(), br.ReadF32(), br.ReadF32()); // Read Minimum Bounds. MinimumBounds = new Vector3(br.ReadF32(), br.ReadF32(), br.ReadF32()); // Read Axis Lengths. AxisLengths = new Vector3(br.ReadF32(), br.ReadF32(), br.ReadF32()); // Define new array to hold offsets. Offsets = new int[7]; // Loop through our offsets. for (int i = 0; i < 7; i++) { // Read offset and store it to the offsets array. Offsets[i] = br.ReadS32(); } // Go to mp's vertex data offset. br.Goto(Offsets[0]); // Calculate amount of vertices. int verticeCount = (Offsets[1] - Offsets[0]) / 12; // Define new list to hold vertices. Vertices = new List <Vector3>(); // Loop through vertices. for (int i = 0; i < verticeCount; i++) { // Read vertex and add it to the vertice list. Vertices.Add(new Vector3(br.ReadF32(), br.ReadF32(), br.ReadF32())); } // Go to mp's normals offset. br.Goto(Offsets[1]); // Calculate amount of normals. int normalCount = (Offsets[2] - Offsets[1]) / 12; // Define new list to hold normals. Normals = new List <Vector3>(); // Loop through normals. for (int i = 0; i < verticeCount; i++) { // Read normal and add it to the normal list. Normals.Add(new Vector3(br.ReadF32(), br.ReadF32(), br.ReadF32())); } // Go to mp's triangle data offset. br.Goto(Offsets[2]); // Calculate amount of normals. int triangleDataCount = (Offsets[3] - Offsets[2]) / 24; // Define new list to hold normals. TriangleData = new List <MpTriangleData>(); // Loop through normals. for (int i = 0; i < triangleDataCount; i++) { // Read normal and add it to the normal list. TriangleData.Add(new MpTriangleData(br)); } // Go to mp's triangle group offset. br.Goto(Offsets[3]); // TODO: Implement reading Triangle Group data. // Go to mp's grid index offset. br.Goto(Offsets[4]); // Calculate amount of grid index entries. int gridIndexCount = (Offsets[4] - Offsets[3]) / 8; // Define new list to hold grid indices. GridIndices = new List <MpGridIndex>(); // Loop through grid indices. for (int i = 0; i < gridIndexCount; i++) { // Read grid index and add it to the grid indices list. GridIndices.Add(new MpGridIndex(br)); } // Go to mp's unknown offset. br.Goto(Offsets[5]); // TODO: Implement reading Unknown data. }
/// <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 MP from a byte array. /// </summary> /// <param name="data">The byte array containing the MP data.</param> public MP(byte[] data) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big); // Read Grid Scale. GridScale = br.ReadVec3(); // Read Minimum Bounds. MinimumBounds = br.ReadVec3(); // Read Axis Lengths. AxisLengths = br.ReadVec3(); // Define new array to hold offsets. Offsets = new int[7]; // Loop through our offsets. for (int i = 0; i < 7; i++) { // Read offset and store it to the offsets array. Offsets[i] = br.ReadS32(); } // Go to mp's vertex data offset. br.Goto(Offsets[0]); // Calculate amount of vertices. int verticeCount = (Offsets[1] - Offsets[0]) / 12; // Define new list to hold vertices. Vertices = new List <Vec3>(); // Loop through vertices. for (int i = 0; i < verticeCount; i++) { // Read vertex and add it to the list of vertices. Vertices.Add(br.ReadVec3()); } // Go to mp's normals offset. br.Goto(Offsets[1]); // Calculate amount of normals. int normalCount = (Offsets[2] - Offsets[1]) / 12; // Define new list to hold normals. Normals = new List <Vec3>(); // Loop through normals. for (int i = 0; i < normalCount; i++) { // Read normal and add it to the normal list. Normals.Add(br.ReadVec3()); } // Go to mp's triangle data offset. br.Goto(Offsets[2]); // Calculate amount of triangles. int triangleDataCount = (Offsets[3] - Offsets[2]) / 24; // Define new list to hold triangle data. TriangleData = new List <TriangleData>(); // Loop through triangles. for (int i = 0; i < triangleDataCount; i++) { // Read triangle and add it to the triangle data list. TriangleData.Add(new TriangleData(br)); } // Go to mp's triangle group offset. br.Goto(Offsets[3]); // Define new list to hold triangle groups. TriangleGroups = new List <TriangleGroup>(); // Make sure first ushort is 0xFFFF. if (br.ReadU16() != 0xFFFF) { throw new FormatException("Start of triangle groups section was not 0xFFFF!"); } // We'll read triangle groups as long as we're not entering the next section. while (br.Position() < Offsets[4] - 2) { // Read group and add it to the groups list. TriangleGroups.Add(new TriangleGroup(br)); } // Make sure last ushort is 0xFFFF. if (br.ReadU16() != 0xFFFF) { throw new FormatException("End of triangle groups section was not 0xFFFF!"); } // Go to mp's grid index offset. br.Goto(Offsets[4]); // Calculate amount of grid index entries. (Offset 5 is a duplicate of offset 4) int gridIndexCount = (Offsets[6] - Offsets[4]) / 8; // Define new list to hold grid indices. GridIndices = new List <GridIndex>(); // Loop through grid indices. for (int i = 0; i < gridIndexCount; i++) { GridIndices.Add(new GridIndex(br)); } // Go to mp's unknown offset. br.Goto(Offsets[6]); // Define new list to hold unknown data. Unknowns = new List <Unknown>(); // We'll read unknowns as long as we're not reading padding EOF. while (br.Position() < br.GetStream().Length) { // Check if next byte is 0xFF. (More data) if (br.Read() == 0xFF) { // Jump back a byte, since we checked for data. br.Sail(-1); // Read unknown and add it to the unknowns list. Unknowns.Add(new Unknown(br)); } else { // We've reached padding, stop reading. break; } } }