/// <inheritdoc/> public async Task <NefsArchive> ReadArchiveAsync( string headerFilePath, ulong headerOffset, ulong headerPart6Offset, string dataFilePath, NefsProgress p) { // Validate header path if (!this.FileSystem.File.Exists(headerFilePath)) { throw new FileNotFoundException($"File not found: {headerFilePath}."); } // Validate data path if (!this.FileSystem.File.Exists(dataFilePath)) { throw new FileNotFoundException($"File not found: {dataFilePath}."); } // Read the header INefsHeader header = null; using (var stream = this.FileSystem.File.OpenRead(headerFilePath)) { header = await this.ReadHeaderAsync(stream, headerOffset, headerPart6Offset, p); } // Create items from header var items = header.CreateItemList(dataFilePath, p); // Create the archive return(new NefsArchive(header, items)); }
/// <summary> /// Reads the header from an input stream. /// </summary> /// <param name="originalStream">The stream to read from.</param> /// <param name="offset">The offset to the header from the beginning of the stream.</param> /// <param name="part6Offset"> /// The offset to the start of part 6 data from the beginning of the stream. /// </param> /// <param name="p">Progress info.</param> /// <returns>The loaded header.</returns> internal async Task <INefsHeader> ReadHeaderAsync(Stream originalStream, ulong offset, ulong part6Offset, NefsProgress p) { Stream stream; Stream part6Stream; INefsHeader header = null; NefsHeaderIntro intro = null; using (p.BeginTask(0.2f, "Reading header intro")) { // Decrypt header if needed (intro, stream) = await this.ReadHeaderIntroAsync(originalStream, offset, p); } // For now, assume that if the header is encrypted, then the part 6 data is not // separated. We've only seen encrypted headers in some nefs 2.0 archives (i.e., DLC content). part6Stream = intro.IsEncrypted ? stream : originalStream; using (p.BeginTask(0.8f)) { if (intro.NefsVersion == 0x20000) { // 2.0.0 Log.LogInformation("Detected NeFS version 2.0."); header = await this.Read20HeaderAsync(stream, 0, part6Stream, part6Offset, intro, p); } else if (intro.NefsVersion == 0x10600) { // 1.6.0 Log.LogInformation("Detected NeFS version 1.6."); header = await this.Read16HeaderAsync(stream, 0, part6Stream, part6Offset, intro, p); } else { Log.LogInformation($"Detected unkown NeFS version {intro.NefsVersion}."); header = await this.Read20HeaderAsync(stream, 0, part6Stream, part6Offset, intro, p); } } // The header stream must be disposed stream.Dispose(); return(header); }
/// <summary> /// Initializes a new instance of the <see cref="NefsArchive"/> class. /// </summary> /// <param name="header">The archive's header.</param> /// <param name="items">List of items for this archive.</param> public NefsArchive(INefsHeader header, NefsItemList items) { this.Header = header ?? throw new ArgumentNullException(nameof(header)); this.Items = items ?? throw new ArgumentNullException(nameof(items)); }