public static void Decompress(string filename) { using (var file = new FileStream("comp1.bin", FileMode.Open)) { using (var compStream = new ZstandardStream(file, CompressionMode.Decompress, true)) { using (var fileOut = new FileStream("comp1.bin.dec", FileMode.Create)) { compStream.CopyStream(fileOut, 0xc1f0); } } } }
public void ExtractFileIndex(int index, string outDir, IProgressReport progress, StringBuilder sb = null) { FileListTab file = Table20.FileList[index]; string name = file.Path.GetText(); DirectoryListTab dir = file.Directory; DirectoryOffsetTable dirOffset = dir.DirOffset; FileOffsetTab offsetInfo = file.FileOffset; bool isLink = false; long offset = Header.Field10 + dirOffset.Offset + file.FileOffset.Offset * 4; string path; if (name != null) { path = Path.Combine(outDir, name); } else if (file.Parent.HasText()) { path = Path.Combine(outDir, file.Parent.GetText(), index.ToString()); } else { path = Path.Combine(outDir, "_", index.ToString()); } if (file.IsLink) { isLink = true; while (file.IsLink) { file = file.FileOffset.File; } dir = file.Directory; dirOffset = dir.DirOffset; offsetInfo = file.FileOffset; offset = Header.Field10 + dirOffset.Offset + offsetInfo.Offset * 4; } if (offsetInfo.Flag3) { dirOffset = offsetInfo.LinkedDirOffset; offsetInfo = offsetInfo.LinkedOffset; offset = Header.Field10 + dirOffset.Offset + offsetInfo.Offset * 4; } //sb?.AppendLine($"{name}, 0x{file.Flags:x2}, 0x{dirOffset.Offset:x}, 0x{file.FileOffset.Offset:x}, 0x{offset:x}, 0x{file.FileOffset.SizeCompressed:x}, 0x{file.FileOffset.Size:x}, 0x{file.FileOffset.Flags:x2}, 0x{file.FileOffset.LinkFileIndex:x}, {file.Flag1}, {file.Flag9}, {file.Flag17}, {file.IsLink}, {file.Flag21}, {file.FileOffset.IsCompressed}, {file.FileOffset.Flag3}, {file.FileOffset.Flag4}, {file.FileOffset.Flag5}, {file.FileOffset.Flag6},"); //return; try { //if (isLink) return; Directory.CreateDirectory(Path.GetDirectoryName(path)); using (var fileOut = new FileStream(path, FileMode.Create, FileAccess.ReadWrite)) //using (var fileOut = Stream.Null) { Stream.Position = offset; if (offsetInfo.Size == 0) { return; } if (offsetInfo.SizeCompressed == 0 || offsetInfo.SizeCompressed == offsetInfo.Size) { Stream.CopyStream(fileOut, offsetInfo.Size); } else { using (var compStream = new ZstandardStream(Stream, CompressionMode.Decompress, true)) { compStream.CopyStream(fileOut, offsetInfo.Size); } } } sb?.AppendLine($"{name}, 0x{file.Flags:x2}, 0x{dirOffset.Offset:x}, 0x{offsetInfo.Offset:x}, 0x{offset:x}, 0x{offsetInfo.SizeCompressed:x}, 0x{offsetInfo.Size:x}, 0x{offsetInfo.Flags:x2}, 0x{offsetInfo.LinkFileIndex:x}, {file.Flag1}, {file.Flag9}, {file.Flag17}, {file.IsLink}, {file.Flag21}, {offsetInfo.IsCompressed}, {offsetInfo.Flag3}, {offsetInfo.Flag4}, {offsetInfo.Flag5}, {offsetInfo.Flag6}, "); } catch (InvalidDataException) { progress?.LogMessage($"File index 0x{file.Index:x5} Offset 0x{offset:x9}: Can't decompress {path}"); try { File.Delete(path); sb?.AppendLine($"{name}, 0x{file.Flags:x2}, 0x{dirOffset.Offset:x}, 0x{offsetInfo.Offset:x}, 0x{offset:x}, 0x{offsetInfo.SizeCompressed:x}, 0x{offsetInfo.Size:x}, 0x{offsetInfo.Flags:x2}, 0x{offsetInfo.LinkFileIndex:x}, {file.Flag1}, {file.Flag9}, {file.Flag17}, {file.IsLink}, {file.Flag21}, {offsetInfo.IsCompressed}, {offsetInfo.Flag3}, {offsetInfo.Flag4}, {offsetInfo.Flag5}, {offsetInfo.Flag6}, X"); var badPath = Path.Combine(outDir, "bad", index.ToString()); Directory.CreateDirectory(Path.GetDirectoryName(badPath)); using (var fileOut = new FileStream(badPath, FileMode.Create, FileAccess.ReadWrite)) { Stream.Position = offset; var info = file.FileOffset; if (info.Size == 0) { return; } Stream.CopyStream(fileOut, info.Size); } } catch (Exception) { } } catch (Exception) { progress?.LogMessage($"File index 0x{file.Index:x5}: Bad path {path}"); try { File.Delete(path); } catch (Exception) { } } }