/// <summary> /// Read the manifest stored in the file /// </summary> /// <returns> /// The list of entries in the manifest /// </returns> public List <TOCEntry> ReadManifest() { // Always reload the header before reading the manifest ReadHeader(); uint i = 0; TOC = new List <TOCEntry>(); for (i = 0; i < m_hdrPSHeader.TocEntries; i++) { TOC.Add(new TOCEntry(m_erReader.ReadBytes(16), m_erReader.ReadUInt32(), m_erReader.ReadUInt40(), m_erReader.ReadUInt40())); } // Extract the Manifest List UnpackedFile upfManifest = DecompressFile(0); m_lstTOCList = new List <string>(System.Text.Encoding.Default.GetString(upfManifest.BinaryFile).Split('\n')); m_lstTOCList.Insert(0, "manifest.txt"); // Insert an entry for the manifest name List <TOCEntry> lstTOC = TOC; TOC = new List <TOCEntry>(); for (i = 0; i < lstTOC.Count; i++) { TOC.Add(new TOCEntry(lstTOC[(int)i], m_lstTOCList[(int)i])); // Create a new TOC that includes the file name from the manifest } lstTOC = null; return(TOC); }
void WriteFile(UnpackedFile arcFile) { string outputFileName = m_strTestDirectories + @"\" + arcFile.FileName.Replace('/', '\\'); string outputFolder = outputFileName.Substring(0, outputFileName.LastIndexOf('\\')); Directory.CreateDirectory(outputFolder); File.WriteAllBytes(outputFileName, arcFile.BinaryFile); }
/// <summary> /// Decompress a pak file /// </summary> /// <param name="p_intManifestLocation">The position of the manifest in the pak file</param> /// <returns></returns> public UnpackedFile DecompressFile(int p_intManifestLocation) { if (p_intManifestLocation > (m_hdrPSHeader.TocEntries - 1)) { return(new UnpackedFile()); } byte[] outFile = null; m_erReader.BaseStream.Position = (long)TOC[p_intManifestLocation].StartOffset; // From manifest UInt16 isZipped = m_erReader.ReadUInt16(); m_erReader.BaseStream.Position -= 2; // Rewind 2 bytes ulong cBlockSize = m_hdrPSHeader.BlockSize; // Calculate the number of blocks the uncompressed file would consume (this is more data than needed for decompression) //ulong zBlocks = ((TOC[manifestLocation].originalSize - (TOC[manifestLocation].originalSize % cBlockSize)) / cBlockSize) // + (TOC[manifestLocation].originalSize % cBlockSize) == 0 ? 0u : 1u; ulong zBlocks = ((TOC[p_intManifestLocation].OriginalSize - (TOC[p_intManifestLocation].OriginalSize % cBlockSize)) / cBlockSize); if (TOC[p_intManifestLocation].OriginalSize % cBlockSize > 0) { zBlocks++; } if (isZipped == 0x78da || isZipped == 0x7801) // Stream is compressed { ulong fileSize = zBlocks * cBlockSize; // Only pass a part of the whole archive stream to be inflated. outFile = zlib_net.Inflate(m_erReader.ReadBytes((int)fileSize), (uint)zBlocks, (uint)cBlockSize, TOC[p_intManifestLocation].OriginalSize); } else { outFile = m_erReader.ReadBytes((int)TOC[p_intManifestLocation].OriginalSize); } if (TOC[p_intManifestLocation].OriginalSize != (ulong)outFile.LongLength) { throw new InvalidDataException(string.Format("Expected size: {0}, Actual size: {1}", TOC[p_intManifestLocation].OriginalSize, outFile.LongLength)); } var output = new UnpackedFile(); output.FileName = TOC[p_intManifestLocation].FileName; output.BinaryFile = outFile; var output2 = new UnpackedFile(TOC[p_intManifestLocation].FileName, outFile); return(output); }
/// <summary> /// Decompress a pak file /// </summary> /// <param name="p_intManifestLocation">The position of the manifest in the pak file</param> /// <returns></returns> public UnpackedFile DecompressFile(int p_intManifestLocation) { if (p_intManifestLocation > (m_hdrPSHeader.TocEntries - 1)) { return(new UnpackedFile()); } byte[] outFile = null; m_erReader.BaseStream.Position = (long)TOC[p_intManifestLocation].StartOffset; // From manifest UInt16 isZipped = m_erReader.ReadUInt16(); m_erReader.BaseStream.Position -= 2; // Rewind 2 bytes ulong cBlockSize = m_hdrPSHeader.BlockSize; ulong zBlocks = (uint)(Math.Ceiling(TOC[p_intManifestLocation].OriginalSize / (double)cBlockSize)); if (isZipped == 0x78da || isZipped == 0x7801) // Stream is compressed { ulong fileSize = zBlocks * cBlockSize; // Only pass a part of the whole archive stream to be inflated. outFile = ZlibUtils.Inflate(m_erReader.ReadBytes((int)fileSize), (uint)zBlocks, (uint)cBlockSize, TOC[p_intManifestLocation].OriginalSize); } else { outFile = m_erReader.ReadBytes((int)TOC[p_intManifestLocation].OriginalSize); } if (TOC[p_intManifestLocation].OriginalSize != (ulong)outFile.LongLength) { throw new InvalidDataException(string.Format("Expected size: {0}, Actual size: {1}", TOC[p_intManifestLocation].OriginalSize, outFile.LongLength)); } var output = new UnpackedFile(); output.FileName = TOC[p_intManifestLocation].FileName; output.BinaryFile = outFile; var output2 = new UnpackedFile(TOC[p_intManifestLocation].FileName, outFile); return(output); }