private static void WriteFileHeader(BinderFile file, BinaryWriterEx bw, int index, Binder.Format format) { bw.WriteByte((byte)file.Flags); bw.WriteByte(0); bw.WriteByte(0); bw.WriteByte(0); bw.ReserveInt32($"CompressedSize{index}"); bw.ReserveUInt32($"FileData{index}"); if (Binder.HasID(format)) { bw.WriteInt32(file.ID); } if (Binder.HasName(format)) { bw.ReserveUInt32($"FileName{index}"); } if (Binder.HasUncompressedSize(format)) { bw.WriteInt32(file.Bytes.Length); } }
private void Write(BinaryWriterEx bhdWriter, BinaryWriterEx bdtWriter) { bhdWriter.WriteASCII("BHF3"); bhdWriter.WriteFixStr(BHDTimestamp, 8); bhdWriter.WriteByte((byte)Format); bhdWriter.WriteByte(0); bhdWriter.WriteByte(0); bhdWriter.WriteByte(0); bhdWriter.BigEndian = Binder.ForceBigEndian(Format); bhdWriter.WriteInt32(Files.Count); bhdWriter.WriteInt32(0); bhdWriter.WriteInt32(0); bhdWriter.WriteInt32(0); bdtWriter.WriteASCII("BDF3"); bdtWriter.WriteFixStr(BDTTimestamp, 8); bdtWriter.WriteInt32(0); for (int i = 0; i < Files.Count; i++) { BinderFile file = Files[i]; bhdWriter.WriteByte(0x40); bhdWriter.WriteByte(0); bhdWriter.WriteByte(0); bhdWriter.WriteByte(0); bhdWriter.WriteInt32(file.Bytes.Length); bhdWriter.WriteUInt32((uint)bdtWriter.Position); bhdWriter.WriteInt32(i); bhdWriter.ReserveUInt32($"FileName{i}"); if (Binder.HasUncompressedSize(Format)) { bhdWriter.WriteInt32(file.Bytes.Length); } bdtWriter.WriteBytes(file.Bytes); bdtWriter.Pad(0x10); } for (int i = 0; i < Files.Count; i++) { BinderFile file = Files[i]; bhdWriter.FillUInt32($"FileName{i}", (uint)bhdWriter.Position); bhdWriter.WriteShiftJIS(file.Name, true); } }
private static void WriteFileData(BinderFile file, BinaryWriterEx bw, int index) { if (file.Bytes.Length > 0) { bw.Pad(0x10); } bw.FillUInt32($"FileData{index}", (uint)bw.Position); int compressedSize = file.Bytes.Length; if (Binder.IsCompressed(file.Flags)) { compressedSize = SFUtil.WriteZlib(bw, 0x9C, file.Bytes); } else { bw.WriteBytes(file.Bytes); } bw.FillInt32($"CompressedSize{index}", compressedSize); }
private static void WriteFileName(BinderFile file, BinaryWriterEx bw, int index) { bw.FillUInt32($"FileName{index}", (uint)bw.Position); bw.WriteShiftJIS(file.Name, true); }
internal BinderFileHeader(BinderFile file) : this(file.Flags, file.ID, file.Name, -1, -1, -1) { CompressionType = file.CompressionType; }
/// <summary> /// Writes BND4 data to a BinaryWriterEx. /// </summary> internal override void Write(BinaryWriterEx bw) { bw.BigEndian = BigEndian; bw.WriteASCII("BND4"); bw.WriteBoolean(Flag1); bw.WriteBoolean(Flag2); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(0x10000); bw.WriteInt32(Files.Count); bw.WriteInt64(0x40); bw.WriteFixStr(Timestamp, 8); bw.WriteInt64(Binder.FileHeaderSize(Format)); bw.ReserveInt64("DataStart"); bw.WriteBoolean(Unicode); bw.WriteByte((byte)Format); bw.WriteByte(Extended); bw.WriteByte(0); bw.WriteInt32(0); if (Extended == 4) { bw.ReserveInt64("HashGroups"); } else { bw.WriteInt64(0); } for (int i = 0; i < Files.Count; i++) { WriteFile(Files[i], bw, i, Format); } if (Binder.HasName(Format)) { for (int i = 0; i < Files.Count; i++) { BinderFile file = Files[i]; bw.FillUInt32($"FileName{i}", (uint)bw.Position); if (Unicode) { bw.WriteUTF16(file.Name, true); } else { bw.WriteShiftJIS(file.Name, true); } } } if (Extended == 4) { uint groupCount = 0; for (uint p = (uint)Files.Count / 7; p <= 100000; p++) { if (SFUtil.IsPrime(p)) { groupCount = p; break; } } if (groupCount == 0) { throw new InvalidOperationException("Hash group count not determined in BND4."); } var hashLists = new List <PathHash> [groupCount]; for (int i = 0; i < groupCount; i++) { hashLists[i] = new List <PathHash>(); } for (int i = 0; i < Files.Count; i++) { var pathHash = new PathHash(i, Files[i].Name); uint group = pathHash.Hash % groupCount; hashLists[group].Add(pathHash); } for (int i = 0; i < groupCount; i++) { hashLists[i].Sort((ph1, ph2) => ph1.Hash.CompareTo(ph2.Hash)); } var hashGroups = new List <HashGroup>(); var pathHashes = new List <PathHash>(); int count = 0; foreach (List <PathHash> hashList in hashLists) { int index = count; foreach (PathHash pathHash in hashList) { pathHashes.Add(pathHash); count++; } hashGroups.Add(new HashGroup(index, count - index)); } bw.Pad(0x8); bw.FillInt64("HashGroups", bw.Position); bw.ReserveInt64("PathHashes"); bw.WriteUInt32(groupCount); bw.WriteInt32(0x00080810); foreach (HashGroup hashGroup in hashGroups) { hashGroup.Write(bw); } // No padding after section 1 bw.FillInt64("PathHashes", bw.Position); foreach (PathHash pathHash in pathHashes) { pathHash.Write(bw); } } bw.FillInt64("DataStart", bw.Position); for (int i = 0; i < Files.Count; i++) { BinderFile file = Files[i]; if (file.Bytes.LongLength > 0) { bw.Pad(0x10); } bw.FillUInt32($"FileData{i}", (uint)bw.Position); int compressedSize = file.Bytes.Length; if (Binder.IsCompressed(file.Flags)) { if (Format == Binder.Format.x2E) { byte[] bytes = DCX.Compress(file.Bytes, DCX.Type.DemonsSoulsEDGE); bw.WriteBytes(bytes); compressedSize = bytes.Length; } else { compressedSize = SFUtil.WriteZlib(bw, 0x9C, file.Bytes); } } else { bw.WriteBytes(file.Bytes); } bw.FillInt64($"CompressedSize{i}", compressedSize); } }
/// <summary> /// Reads file data according to the given header. /// </summary> public byte[] ReadFile(BinderFileHeader fileHeader) { BinderFile file = fileHeader.ReadFileData(DataBR); return(file.Bytes); }