/// <summary> /// Method for reading RGBA32 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[] ReadRGBA32(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 subblock 1 y. for (int yx = 0; yx < 4; yx++) { // Loop through subblock 1 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)); // Store decoded Alpha, Red subblock data in buffer. decoded[offset + 3] = br.Read(); decoded[offset + 2] = br.Read(); } } // Loop through subblock 2 y. for (int yx = 0; yx < 4; yx++) { // Loop through subblock 2 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)); // Store decoded Green, Blue subblock data in buffer. decoded[offset + 1] = br.Read(); decoded[offset + 0] = br.Read(); } } } } // Return the texture as RGBA. return(decoded); }
/// <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 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 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> /// 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)); } }
/// <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 vertex. /// </summary> /// <param name="br">The binaryreader to read with.</param> public Vertex(DhBinaryReader br, Attributes attributes, bool useNbt) { // Each vertex will always hold 26 indices. (Null = unused) Indices = new short?[26]; // Get all the attributes from GX attributes. var indices = Enum.GetValues(typeof(Attributes)); // Loop through GX attributes. for (int i = 0; i < indices.Length; i++) { // Make sure this attribute is present. if (attributes.HasFlag((Attributes)(1 << i))) { // Read the current index. Indices[i] = br.ReadS16(); // Check if we're reading normals and nbt is enabled. if (i == 10 && useNbt) { // Set bitangent/tangent indices. (TODO - Fix the indices here...) //Indices[24] = br.ReadS16(); //Indices[25] = br.ReadS16(); br.Skip(4); // Thanks to Astral-C for the tip of just throwing these away. (Until support is added) } } } }
/// <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); } }
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 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(); } }
public static byte[] DecodeData(DhBinaryReader br, ushort width, ushort height, TextureFormat format) { switch (format) { case TextureFormat.I4: return(ReadI4(br, width, height)); case TextureFormat.I8: return(ReadI8(br, width, height)); case TextureFormat.IA4: return(ReadIA4(br, width, height)); case TextureFormat.IA8: return(ReadIA8(br, width, height)); case TextureFormat.RGB5A3: return(ReadRGB5A3(br, width, height)); case TextureFormat.RGB565: return(ReadRGB565(br, width, height)); case TextureFormat.RGBA32: return(ReadRGBA32(br, width, height)); case TextureFormat.CMPR: return(ReadCMPR(br, width, height)); default: throw new NotImplementedException(string.Format("[BTI] {0} is not a supported texture format!", format)); } }
/// <summary> /// Read a single primitive vertex from BIN. /// </summary> /// <param name="br">Binary Reader to use.</param> public BinPrimitiveVertex(DhBinaryReader br, byte useNBT, int uvCount, BinBatchAttributes attributes) { // Read Matrix Index. MatrixIndex = br.ReadS16(); // Check position attribute. if (attributes.HasFlag(BinBatchAttributes.Position)) { // Read Position Index. PositionIndex = br.ReadS16(); } // Check normal attribute. if (attributes.HasFlag(BinBatchAttributes.Normal)) { // Read Normal Index. NormalIndex = br.ReadS16(); // Check UseNBT flag. if (useNBT == 1) { // Read BiNormal Index. BiNormalIndex = br.ReadS16(); // Read Tangent Index. TangentIndex = br.ReadS16(); } } // Define ColorIndex array to hold ColorIndex values. ColorIndex = new short[2]; // Check color2 attribute. if (attributes.HasFlag(BinBatchAttributes.Color0)) { // Read the Color1 value. ColorIndex[0] = br.ReadS16(); } // Check color1 attribute. if (attributes.HasFlag(BinBatchAttributes.Color1)) { // Read the Color1 value. ColorIndex[1] = br.ReadS16(); } // Define UVIndex array to hold UVIndex values. UVIndex = new short[8]; // Loop through texCoords. for (int i = 0; i < uvCount; i++) { // Check texCoordX attribute. if (attributes.HasFlag((BinBatchAttributes)(1 << (13 + i)))) { // Read the current UVIndex value. UVIndex[i] = br.ReadS16(); } } }
public MDLDrawElement(DhBinaryReader br, List <MDLMaterial> materials, List <MDLShape> shapes) { MaterialIndex = br.ReadS16(); ShapeIndex = br.ReadS16(); Material = materials[MaterialIndex]; Shape = shapes[ShapeIndex]; }
/// <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(); }
public BinGraphObjectPart(DhBinaryReader br) { // Read shader index. ShaderIndex = br.ReadS16(); // Read batch index. BatchIndex = br.ReadS16(); }
/// <summary> /// Read a single texture coordinate from BIN. /// </summary> /// <param name="br">Binary Reader to use.</param> public BinTextureCoordinate(DhBinaryReader br) { // Read X-Coordinate. X = br.ReadF32(); // Read Y-Coordinate. Y = br.ReadF32(); }
/// <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(); }
/// <summary> /// Read a single keyframe from TMB. /// </summary> /// <param name="br">The binary reader to read with.</param> /// <param name="dataCount">The amount of floats in this keyframe.</param> public TIMKeyFrame(DhBinaryReader br, ushort dataCount) { // Read time. Time = br.ReadF32(); // Read keyframe data. Data = br.ReadF32s(dataCount - 1).ToList(); }
/// <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); }
public MDLSampler(DhBinaryReader br) { TextureIndex = br.ReadU16(); UnknownIndex = br.ReadU16(); WrapU = (WrapMode)br.ReadU8(); WrapV = (WrapMode)br.ReadU8(); MinFilter = br.ReadU8(); MagFilter = br.ReadU8(); }
/// <summary> /// Method for reading I4 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[] ReadI4(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 < (width / 8); y++) { // Loop through blocks x. for (int x = 0; x < (height / 8); x++) { // Loop through pixels in block y. for (int yx = 0; yx < 8; yx++) { // Loop through pixels in block x. for (int xy = 0; xy < 8; xy += 2) { // Determine if pixel is oob (x || y). if ((y * 8 + yx >= height) || (x * 8 + xy >= width)) { // Skip. continue; } // Read current pixel. byte pixel = br.Read(); // Calculate RGBA data. byte r1 = (byte)(((pixel & 0xF0) >> 4) * 0x11); byte g1 = (byte)(((pixel & 0xF0) >> 4) * 0x11); byte b1 = (byte)(((pixel & 0xF0) >> 4) * 0x11); byte a1 = 0xFF; byte r2 = (byte)((pixel & 0x0F) * 0x11); byte g2 = (byte)((pixel & 0x0F) * 0x11); byte b2 = (byte)((pixel & 0x0F) * 0x11); byte a2 = 0xFF; // Calculate offset for decoded data. uint offset = (uint)(4 * (width * ((y * 8) + yx) + (x * 8) + xy)); // Store decoded data in buffer. decoded[offset + 0] = r1; decoded[offset + 1] = g1; decoded[offset + 2] = b1; decoded[offset + 3] = a1; decoded[offset + 4] = r2; decoded[offset + 5] = g2; decoded[offset + 6] = b2; decoded[offset + 7] = a2; } } } } // Return the texture as RGBA. return(decoded); }
/// <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); }
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 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); }
/// <summary> /// Method for converting the BTI into a Bitmap. /// </summary> /// <returns>The BTI as a Bitmap.</returns> public Bitmap ToBitmap() { DhBinaryReader br = new DhBinaryReader(Data, DhEndian.Big); byte[] data = BTIUtils.DecodeData(br, Width, Height, Format); Bitmap bmp = new Bitmap(Width, Height); Rectangle rect = new Rectangle(0, 0, Width, Height); BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); IntPtr ptr = bmpData.Scan0; Marshal.Copy(data, 0, ptr, data.Length); bmp.UnlockBits(bmpData); return(bmp); }
public MDLMaterial(DhBinaryReader br, List <MDLSampler> samplers) { DiffuseColor = br.ReadClr4(); Unknown1 = br.ReadS16(); AlphaFlag = br.ReadU8(); TevStageCount = br.ReadU8(); Unknown2 = br.ReadU8(); br.Skip(23); TevStages = new List <MDLTevStage>(); for (int i = 0; i < 8; i++) { TevStages.Add(new MDLTevStage(br)); } }
/// <summary> /// Method for reading IA4 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 byte[] containing RGBA data.</returns> private static byte[] ReadIA4(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 / 8); 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 < 8; xy++) { // Determine if pixel is oob (x || y). if ((x * 8 + xy >= width) || (y * 4 + yx >= height)) { // Skip. continue; } // Read current pixel. byte value = br.Read(); // Calculate alpha and luminosity values. byte alpha = (byte)(((value & 0xF0) >> 4) * 0x11); byte luminosity = (byte)((value & 0x0F) * 0x11); // Calculate offset for decoded data. uint offset = (uint)(4 * (width * ((y * 4) + yx) + (x * 8) + xy)); // Store decoded data in buffer. decoded[offset + 0] = luminosity; decoded[offset + 1] = luminosity; decoded[offset + 2] = luminosity; decoded[offset + 3] = alpha; } } } } // Return the texture as RGBA. return(decoded); }
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); }