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