internal static void Compress(byte[] data, BinaryWriterEx bw, Type type) { bw.BigEndian = true; if (type == Type.Zlib) { SFUtil.WriteZlib(bw, 0xDA, data); } else if (type == Type.DCP_DFLT) { CompressDCPDFLT(data, bw); } else if (type == Type.DCX_EDGE) { CompressDCXEDGE(data, bw); } else if (type == Type.DCX_DFLT_10000_24_9 || type == Type.DCX_DFLT_10000_44_9 || type == Type.DCX_DFLT_11000_44_8 || type == Type.DCX_DFLT_11000_44_9) { CompressDCXDFLT(data, bw, type); } else if (type == Type.DCX_KRAK) { CompressDCXKRAK(data, bw); } else if (type == Type.Unknown) { throw new ArgumentException("You cannot compress a DCX with an unknown type."); } else { throw new NotImplementedException("Compression for the given type is not implemented."); } }
private static void CompressDCXDFLT(byte[] data, BinaryWriterEx bw, Type type) { bw.WriteASCII("DCX\0"); if (type == Type.DCX_DFLT_10000_24_9 || type == Type.DCX_DFLT_10000_44_9) { bw.WriteInt32(0x10000); } else if (type == Type.DCX_DFLT_11000_44_8 || type == Type.DCX_DFLT_11000_44_9) { bw.WriteInt32(0x11000); } bw.WriteInt32(0x18); bw.WriteInt32(0x24); if (type == Type.DCX_DFLT_10000_24_9) { bw.WriteInt32(0x24); bw.WriteInt32(0x2C); } else if (type == Type.DCX_DFLT_10000_44_9 || type == Type.DCX_DFLT_11000_44_8 || type == Type.DCX_DFLT_11000_44_9) { bw.WriteInt32(0x44); bw.WriteInt32(0x4C); } bw.WriteASCII("DCS\0"); bw.WriteInt32(data.Length); bw.ReserveInt32("CompressedSize"); bw.WriteASCII("DCP\0"); bw.WriteASCII("DFLT"); bw.WriteInt32(0x20); if (type == Type.DCX_DFLT_10000_24_9 || type == Type.DCX_DFLT_10000_44_9 || type == Type.DCX_DFLT_11000_44_9) { bw.WriteInt32(0x9000000); } else if (type == Type.DCX_DFLT_11000_44_8) { bw.WriteInt32(0x8000000); } bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0x00010100); bw.WriteASCII("DCA\0"); bw.WriteInt32(8); long compressedStart = bw.Position; SFUtil.WriteZlib(bw, 0xDA, data); bw.FillInt32("CompressedSize", (int)(bw.Position - compressedStart)); }
private static void CompressDCPDFLT(byte[] data, BinaryWriterEx bw) { bw.WriteASCII("DCP\0"); bw.WriteASCII("DFLT"); bw.WriteInt32(0x20); bw.WriteInt32(0x9000000); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0x00010100); bw.WriteASCII("DCS\0"); bw.WriteInt32(data.Length); bw.ReserveInt32("CompressedSize"); int compressedSize = SFUtil.WriteZlib(bw, 0xDA, data); bw.FillInt32("CompressedSize", compressedSize); bw.WriteASCII("DCA\0"); bw.WriteInt32(8); }
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); }
/// <summary> /// Serializes file data to a stream. /// </summary> protected override void Write(BinaryWriterEx bw) { BinaryWriterEx bwData = new BinaryWriterEx(false); bwData.WriteInt32(0); bwData.WriteInt32(Struct1s.Count); bwData.WriteInt32(Struct2s.Count); bwData.WriteInt32(0); foreach (Struct1 struct1 in Struct1s) { struct1.Write(bwData); } bwData.Pad(0x10); foreach (Struct2 struct2 in Struct2s) { struct2.Write(bwData); } bwData.Pad(0x10); bwData.WriteInt16(0); foreach (string str in Strings) { bwData.WriteUTF16(str, true); } bwData.Pad(0x10); byte[] data = bwData.FinishBytes(); bw.WriteASCII("ENFL"); bw.WriteInt32(0x10415); bw.ReserveInt32("CompressedSize"); bw.WriteInt32(data.Length); int compressedSize = SFUtil.WriteZlib(bw, 0xDA, data); bw.FillInt32("CompressedSize", compressedSize); }
internal void WriteData(BinaryWriterEx bw, int index, byte format) { if (Bytes.Length > 0) { bw.Pad(0x10); } bw.FillInt32($"FileData{index}", (int)bw.Position); byte[] bytes = Bytes; int compressedSize = bytes.Length; if (Flags == 0xC0) { compressedSize = SFUtil.WriteZlib(bw, 0x9C, bytes); } else { bw.WriteBytes(bytes); } bw.FillInt32($"CompressedSize{index}", bytes.Length); }
/// <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); if (Format == 0x0C) { bw.WriteInt64(0x18); } else if (Format == 0x70) { bw.WriteInt64(0x1C); } else { bw.WriteInt64(0x24); } bw.ReserveInt64("DataStart"); bw.WriteBoolean(Unicode); bw.WriteByte(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++) { Files[i].Write(bw, i, Format); } for (int i = 0; i < Files.Count; i++) { File file = Files[i]; bw.FillInt32($"FileName{i}", (int)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++) { File file = Files[i]; if (file.Bytes.LongLength > 0) { bw.Pad(0x10); } bw.FillInt32($"FileData{i}", (int)bw.Position); byte[] bytes = file.Bytes; int compressedSize = bytes.Length; if (file.Flags == 0x03 || file.Flags == 0xC0) { compressedSize = SFUtil.WriteZlib(bw, 0x9C, bytes); } else { bw.WriteBytes(bytes); } bw.FillInt64($"CompressedSize{i}", bytes.Length); } }