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