/* * Query if p2 obsoletes p1. * Will return true if p1 is contained in any obsoleted file list in a pack obsoleted by p2, * otherwise false. */ bool Obsoletes(string p1, string p2) { PFHeader p1Header = nameToHeader[p1]; if (p1Header.ReplacedPackFileNames.Count == 0) { return(false); } bool result = p1Header.ReplacedPackFileNames.Contains(Path.GetFileName(p2)); if (!result) { foreach (string name in p1Header.ReplacedPackFileNames) { string otherCandidate; if (nameToPath.TryGetValue(name, out otherCandidate)) { result = Obsoletes(otherCandidate, p2); } if (result) { break; } } } return(result); }
/* * 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); }
/* * Notify pack header having been decoded. */ private void OnHeaderLoaded(PFHeader header) { if (this.HeaderLoaded != null) { this.HeaderLoaded(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); }
/* * Enumerator for pack at given file path. */ public PackFileEnumerator(string path) { filepath = path; reader = new BinaryReader(File.OpenRead(path)); header = PackFileCodec.ReadHeader(reader); startPosition = reader.BaseStream.Position; Reset(); }
/* * Create pack file at the given path with the given header. */ public PackFile(string path, PFHeader h) { header = h; Filepath = path; Root = new VirtualDirectory() { Name = Path.GetFileName(path) }; DirAdded(Root); }
public PackLoadOrder(ICollection <string> files) { foreach (string file in files) { try { PFHeader header = PackFileCodec.ReadHeader(file); nameToHeader.Add(file, header); nameToPath.Add(Path.GetFileName(file), file); } catch { } // couldn't read header probably; just ignore the file } }
/* * Query if a pack file is provided by CA. */ public static bool IsDbCaPack(string filename) { foreach (string exclude in EXCLUDE_PREFIXES) { if (Path.GetFileName(filename).StartsWith(exclude)) { return(true); } } bool result = false; try { PFHeader pack = PackFileCodec.ReadHeader(filename); result = (pack.Type != PackType.Patch) && (pack.Type != PackType.Release); } catch {} // not a valid pack: not a CA pack return(result); }
/* * Compare the two strings by interpreting them as pack file paths and * establishing the load order between those. */ public override int Compare(string p1, string p2) { // sort by type PFHeader p1Header = nameToHeader[p1]; PFHeader p2Header = nameToHeader[p2]; int index1 = p1Header.LoadOrder; // Ordered.IndexOf(p1Header.Type); int index2 = p2Header.LoadOrder; // Ordered.IndexOf(p2Header.Type); int result = index2 - index1; // same type? Check obsoletion path if (result == 0) { if (Obsoletes(p1, p2)) { result = -1; } else if (Obsoletes(p2, p1)) { result = 1; } } return(result); }
/* * Create a header from the given one. */ public PFHeader(PFHeader toCopy) : this(toCopy.identifier) { Type = toCopy.Type; ReplacedPackFileNames.AddRange(toCopy.ReplacedPackFileNames); }