Пример #1
0
        /// <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));
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
 /// <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));
 }