/// <summary> /// Reads a subfile from file table metadata. /// </summary> /// <param name="reader">The .ppx file reader.</param> public static ArchiveFileSource ReadFromTable(BinaryReader reader, ExtendedArchive archive) { ArchiveFileSource file = new ArchiveFileSource(); file.BaseArchive = archive; ushort len = reader.ReadUInt16(); file.ArchiveName = Encoding.Unicode.GetString(reader.ReadBytes(len)); len = reader.ReadUInt16(); file.Name = Encoding.Unicode.GetString(reader.ReadBytes(len)); len = reader.ReadUInt16(); file.EmulatedName = Encoding.Unicode.GetString(reader.ReadBytes(len)); file.Type = (ArchiveFileType)reader.ReadUInt16(); file.Md5 = reader.ReadBytes(16); file.ChunkID = reader.ReadUInt32(); file.Offset = reader.ReadUInt64(); file.Size = (uint)reader.ReadUInt64(); return(file); }
internal ExtendedHeader(BinaryReader reader) { ushort strlen = reader.ReadUInt16(); Title = Encoding.Unicode.GetString(reader.ReadBytes((int)strlen)); uint number = reader.ReadUInt32(); uint headerlength = reader.ReadUInt32(); int ses = (int)headerlength; List <ArchiveFileSource> dupes = new List <ArchiveFileSource>(); for (int i = 0; i < number; i++) { var file = new ArchiveFileSource(reader); if (file.Compression == ArchiveFileCompression.Duplicate) { dupes.Add(file); } else { files.Add(file); } } foreach (var file in dupes) { var original = files.First(x => Enumerable.SequenceEqual(x.Md5, file.Md5) && !x.Flags.HasFlag(ArchiveFileFlags.Duplicate)); files.Add(original.Dedupe(file)); } }
/// <summary> /// Reads from a .ppx file. /// </summary> /// <param name="Filename">The filename of the .ppx file.</param> protected void ReadFromFile(string Filename) { this.Filename = Filename; using (FileStream arc = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read)) using (BinaryReader reader = new BinaryReader(arc)) { string magic = Encoding.ASCII.GetString(reader.ReadBytes(4)); //Check magic if (Magic != magic) { throw new PpexException("Supplied file is not an extended PP archive.", PpexException.PpexErrorCode.FileNotPPXArchive); } //Check version ushort version = reader.ReadUInt16(); if (version != Version) { throw new PpexException($"Supplied extended PP archive is of version {version}; was expecting version {Version}", PpexException.PpexErrorCode.IncorrectVersionNumber); } //Read the title ushort strlen = reader.ReadUInt16(); Title = Encoding.Unicode.GetString(reader.ReadBytes((int)strlen)); //Read chunk and file headers TableInfoOffset = (ulong)arc.Position; ChunkTableOffset = reader.ReadUInt64(); FileTableOffset = reader.ReadUInt64(); reader.BaseStream.Position = (long)ChunkTableOffset; uint number = reader.ReadUInt32(); for (int i = 0; i < number; i++) { var chunk = ExtendedArchiveChunk.ReadFromTable(reader, this); chunks.Add(chunk); } reader.BaseStream.Position = (long)FileTableOffset; number = reader.ReadUInt32(); for (int i = 0; i < number; i++) { var source = ArchiveFileSource.ReadFromTable(reader, this); RawFiles.Add(source); Files.Add(new ArchiveSubfile(source)); } } }
internal ArchiveFileSource Dedupe(ArchiveFileSource dupe) { dupe._crc = _crc; dupe._md5 = _md5; dupe._size = _size; dupe.length = length; dupe.offset = offset; dupe.ArchiveFilename = ArchiveFilename; dupe.Compression = Compression; dupe.Type = Type; dupe.Flags |= ArchiveFileFlags.Duplicate; //was originally a duplicate return(dupe); }
public static ISubfile Create(ArchiveFileSource source, string Archive) { switch (source.Type) { case ArchiveFileType.Audio: return(new Xgg.XggSubfile(source, source.Name, Archive)); case ArchiveFileType.Image: return(new ImageSubfile(source, source.Name, Archive)); case ArchiveFileType.Raw: return(new RawSubfile(source, source.Name, Archive)); default: return(null); } }
public ArchiveSubfile(ArchiveFileSource source) { RawSource = source; }