diff --git a/src/Andre/SoulsFormats/SoulsFormats/Formats/DCX.cs b/src/Andre/SoulsFormats/SoulsFormats/Formats/DCX.cs index b5f36b03f..c56628562 100644 --- a/src/Andre/SoulsFormats/SoulsFormats/Formats/DCX.cs +++ b/src/Andre/SoulsFormats/SoulsFormats/Formats/DCX.cs @@ -180,13 +180,13 @@ private static byte[] DecompressDCXZSTD(BinaryReaderEx br) br.AssertInt32(0x4C); br.AssertASCII("DCS\0"); - int uncompressedSize = br.ReadInt32(); + br.ReadInt32(); // uncompressed size int compressedSize = br.ReadInt32(); br.AssertASCII("DCP\0"); br.AssertASCII("ZSTD"); br.AssertInt32(0x20); - br.AssertByte(0x15); + br.ReadByte(); // compression level br.AssertByte(0); br.AssertByte(0); br.AssertByte(0); @@ -477,8 +477,7 @@ internal static void Compress(Span data, BinaryWriterEx bw, Type type) CompressDCXKRAK(data, bw, 9); else if (type == Type.ZSTD) { - // Temporary until proper ZSTD re-compression settings are discovered - CompressDCPDFLT(data, bw); + CompressDCXZSTD(data, bw); } else if (type == Type.Unknown) throw new ArgumentException("You cannot compress a DCX with an unknown type."); @@ -486,29 +485,34 @@ internal static void Compress(Span data, BinaryWriterEx bw, Type type) throw new NotImplementedException("Compression for the given type is not implemented."); } - private static void CompressDCXZSTD(Span data, BinaryWriterEx bw) + private static void CompressDCXZSTD(Span data, BinaryWriterEx bw, int compressionLevel = 15) { - // TODO: just a stub for future implementation - /* + byte[] compressed = SFUtil.WriteZstd(data, compressionLevel); + bw.WriteASCII("DCX\0"); + bw.WriteInt32(0x11000); + bw.WriteInt32(0x18); + bw.WriteInt32(0x24); + bw.WriteInt32(0x44); + bw.WriteInt32(0x4C); + bw.WriteASCII("DCS\0"); + bw.WriteUInt32((uint)data.Length); + bw.WriteUInt32((uint)compressed.Length); + bw.WriteASCII("DCP\0"); bw.WriteASCII("ZSTD"); bw.WriteInt32(0x20); - bw.WriteInt32(0x9000000); + bw.WriteByte((byte)compressionLevel); + bw.WriteByte(0); + bw.WriteByte(0); + bw.WriteByte(0); 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.WriteZstd(bw, 3, data); - bw.FillInt32("CompressedSize", compressedSize); - + bw.WriteInt32(0x10100); bw.WriteASCII("DCA\0"); bw.WriteInt32(8); - */ + bw.WriteBytes(compressed); + bw.Pad(0x10); } private static void CompressDCPDFLT(Span data, BinaryWriterEx bw) diff --git a/src/Andre/SoulsFormats/SoulsFormats/Util/SFUtil.cs b/src/Andre/SoulsFormats/SoulsFormats/Util/SFUtil.cs index 81226efb9..46ad73192 100644 --- a/src/Andre/SoulsFormats/SoulsFormats/Util/SFUtil.cs +++ b/src/Andre/SoulsFormats/SoulsFormats/Util/SFUtil.cs @@ -327,6 +327,14 @@ public static byte[] ReadZlib(BinaryReaderEx br, int compressedSize) return decompressedStream.ToArray(); } } + public static byte[] WriteZstd(Span data, int compressionLevel) + { + var options = new CompressionOptions(null, new Dictionary { { ZSTD_cParameter.ZSTD_c_contentSizeFlag, 0 }, { ZSTD_cParameter.ZSTD_c_windowLog, 16 } }, compressionLevel); + using (var compressor = new Compressor(options)) + { + return compressor.Wrap(data); + } + } public static byte[] ReadZstd(BinaryReaderEx br, int compressedSize) { byte[] compressed = br.ReadBytes(compressedSize);