/* * Reads pack header from the given reader. */ public static PFHeader ReadHeader(BinaryReader reader) { PFHeader header; string packIdentifier = new string (reader.ReadChars(4)); header = new PFHeader(packIdentifier); int packType = reader.ReadInt32(); header.PrecedenceByte = (byte)packType; // header.Type = (PackType)packType; header.Version = reader.ReadInt32(); int replacedPackFilenameLength = reader.ReadInt32(); reader.BaseStream.Seek(0x10L, SeekOrigin.Begin); header.FileCount = reader.ReadUInt32(); UInt32 indexSize = reader.ReadUInt32(); header.DataStart = header.Length + indexSize; if (header.PackIdentifier == "PFH4" || header.PackIdentifier == "PFH5") { header.Unknown = reader.ReadUInt32(); } // go to correct position reader.BaseStream.Seek(header.Length, SeekOrigin.Begin); for (int i = 0; i < header.Version; i++) { header.ReplacedPackFileNames.Add(IOFunctions.TheadUnsafeReadZeroTerminatedAscii(reader)); } header.DataStart += replacedPackFilenameLength; return(header); }
/* * Decode pack file at the given path. */ public PackFile Open(string packFullPath) { PackFile file; long sizes = 0; using (var reader = new BinaryReader(new FileStream(packFullPath, FileMode.Open), Encoding.ASCII)) { PFHeader header = ReadHeader(reader); file = new PackFile(packFullPath, header); OnHeaderLoaded(header); long offset = file.Header.DataStart; for (int i = 0; i < file.Header.FileCount; i++) { uint size = reader.ReadUInt32(); sizes += size; if (file.Header.HasAdditionalInfo) { header.AdditionalInfo = reader.ReadInt64(); } string packedFileName = IOFunctions.ReadZeroTerminatedAscii(reader); // this is easier because we can use the Path methods // under both Windows and Unix packedFileName = packedFileName.Replace('\\', Path.DirectorySeparatorChar); PackedFile packed = new PackedFile(file.Filepath, packedFileName, offset, size); file.Add(packed); offset += size; this.OnPackedFileLoaded(packed); } } this.OnFinishedLoading(file); file.IsModified = false; return(file); }
/* * Find next file entry and return true if there is one, otherwise false. */ public bool MoveNext() { currentFileIndex++; if (currentFileIndex > header.FileCount) { return(false); } uint size = reader.ReadUInt32(); if (Header.HasAdditionalInfo) { header.AdditionalInfo = reader.ReadInt64(); } try { string packedFileName = IOFunctions.ReadZeroTerminatedAscii(reader); // this is easier because we can use the Path methods // under both Windows and Unix packedFileName = packedFileName.Replace('\\', Path.DirectorySeparatorChar); currentFile = new PackedFile(filepath, packedFileName, offset, size); offset += size; return(true); } catch (Exception ex) { Console.WriteLine("Failed enumeration of {2}/{3} file in {0}: {1}", Path.GetFileName(filepath), ex, currentFileIndex, header.FileCount); Console.WriteLine("Current position in file: {0}; last succesful file: {1}", reader.BaseStream.Position, Current.FullPath); } return(false); }
/* * Find next file entry and return true if there is one, otherwise false. */ public bool MoveNext() { currentFileIndex++; if (currentFileIndex > header.FileCount) { return(false); } uint size = reader.ReadUInt32(); //FIXME this is wrong, different PFH versions have different length additionalInfo //TODO this is mostly duplicated with PackFileCodec. Reducing code duplication would be wise. if (Header.HasAdditionalInfo) { header.AdditionalInfo = reader.ReadUInt32(); } if (Header.PackIdentifier == "PFH5") { reader.ReadByte(); } try { string packedFileName = IOFunctions.TheadUnsafeReadZeroTerminatedAscii(reader); // this is easier because we can use the Path methods // under both Windows and Unix packedFileName = packedFileName.Replace('\\', Path.DirectorySeparatorChar); currentFile = new PackedFile(filepath, packedFileName, offset, size); offset += size; return(true); } catch (Exception ex) { Console.WriteLine("Failed enumeration of {2}/{3} file in {0}: {1}", Path.GetFileName(filepath), ex, currentFileIndex, header.FileCount); Console.WriteLine("Current position in file: {0}; last succesful file: {1}", reader.BaseStream.Position, Current.FullPath); } return(false); }