/* * Notify pack fully decoded. */ private void OnFinishedLoading(PackFile pack) { if (this.PackFileLoaded != null) { this.PackFileLoaded(pack); } }
/* * 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); }
/* * Save the given pack file to its current path. * Because some of its entries might still be drawing their data from the original pack, * we cannot just write over it. * Create a temp file, write into that, then delete the original and move the temp. */ public void Save(PackFile packFile) { string tempFile = Path.GetTempFileName(); WriteToFile(tempFile, packFile); if (File.Exists(packFile.Filepath)) { File.Delete(packFile.Filepath); } File.Move(tempFile, packFile.Filepath); }
/* * Encodes given pack file to given path. */ public void WriteToFile(string FullPath, PackFile packFile) { using (BinaryWriter writer = new BinaryWriter(new FileStream(FullPath, FileMode.Create), Encoding.ASCII)) { writer.Write(packFile.Header.PackIdentifier.ToCharArray()); writer.Write((int)packFile.Header.PrecedenceByte); writer.Write((int)packFile.Header.Version); writer.Write(packFile.Header.ReplacedFileNamesLength); UInt32 indexSize = 0; List <PackedFile> toWrite = new List <PackedFile> ((int)packFile.Header.FileCount); foreach (PackedFile file in packFile.Files) { if (!file.Deleted) { indexSize += (uint)file.FullPath.Length + 5; if (packFile.Header.PackIdentifier == "PFH5") { indexSize += 1; } if (packFile.Header.HasAdditionalInfo) { indexSize += 4; } toWrite.Add(file); } } writer.Write(toWrite.Count); writer.Write(indexSize); // File Time if (packFile.Header.PackIdentifier == "PFH2" || packFile.Header.PackIdentifier == "PFH3") { Int64 fileTime = DateTime.Now.ToFileTimeUtc(); writer.Write(fileTime); } else if (packFile.Header.PackIdentifier == "PFH4" || packFile.Header.PackIdentifier == "PFH5") { // hmmm writer.Write(packFile.Header.Unknown); } // Write File Names stored from opening the file foreach (string replacedPack in packFile.Header.ReplacedPackFileNames) { writer.Write(replacedPack.ToCharArray()); writer.Write((byte)0); } // pack entries are stored alphabetically in pack files toWrite.Sort(new PackedFileNameComparer()); // write file list string separatorString = "" + Path.DirectorySeparatorChar; foreach (PackedFile file in toWrite) { writer.Write((int)file.Size); if (packFile.Header.HasAdditionalInfo) { writer.Write(packFile.Header.AdditionalInfo); } // pack pathes use backslash, we replaced when reading string packPath = file.FullPath.Replace(separatorString, "\\"); if (packFile.Header.PackIdentifier == "PFH5") { writer.Write((byte)0); } writer.Write(packPath.ToCharArray()); writer.Write('\0'); } foreach (PackedFile file in toWrite) { if (file.Size > 0) { byte[] bytes = file.Data; writer.Write(bytes); } } } }