/// <summary>
        /// Updates the archive with the modified files
        /// </summary>
        /// <param name="archive">The loaded archive data</param>
        /// <param name="outputFileStream">The file stream for the updated archive</param>
        /// <param name="files">The import data for the archive files</param>
        public void UpdateArchive(object archive, Stream outputFileStream, IEnumerable <IArchiveImportData> files)
        {
            RL.Logger?.LogInformationSource($"A CNT archive is being repacked...");

            // Get the archive data
            var data = archive.CastTo <OpenSpaceCntData>();

            // Create the file generator
            using var fileGenerator = new ArchiveFileGenerator <OpenSpaceCntFileEntry>();

            // Set the current pointer position to the header size
            var pointer = data.GetHeaderSize(Settings);

            // Disable checksum
            data.IsChecksumUsed = false;
            data.DirChecksum    = 0;

            // NOTE: We can't disable the XOR key entirely as that would disable it for the file bytes too, which would require them all to be decrypted
            // Reset XOR keys
            data.XORKey = 0;

            // Load each file
            foreach (var importData in files)
            {
                // Get the file entry
                var file = importData.FileEntryData.CastTo <OpenSpaceCntFileEntry>();

                // Reset checksum and XOR key
                file.Checksum = 0;
                file.XORKey   = 0;

                // Add to the generator
                fileGenerator.Add(file, () =>
                {
                    // Get the file bytes to write to the archive
                    var bytes = importData.GetData(file);

                    // Set the pointer
                    file.Pointer = pointer;

                    // Update the pointer by the file size
                    pointer += file.Size;

                    return(bytes);
                });
            }

            // Write the files
            data.WriteArchiveContent(outputFileStream, fileGenerator);

            outputFileStream.Position = 0;

            // Serialize the data
            BinarySerializableHelpers.WriteToStream(data, outputFileStream, Settings, RCPServices.App.GetBinarySerializerLogger());

            RL.Logger?.LogInformationSource($"The CNT archive has been repacked");
        }
Esempio n. 2
0
        /// <summary>
        /// Updates the archive with the modified files
        /// </summary>
        /// <param name="archive">The loaded archive data</param>
        /// <param name="outputFileStream">The file stream for the updated archive</param>
        /// <param name="files">The import data for the archive files</param>
        public void UpdateArchive(object archive, Stream outputFileStream, IEnumerable <IArchiveImportData> files)
        {
            RL.Logger?.LogInformationSource($"An IPK archive is being repacked...");

            // Get the archive data
            var data = archive.CastTo <UbiArtIpkData>();

            // Create the file generator
            using var fileGenerator = new ArchiveFileGenerator <UbiArtIPKFileEntry>();

            // Keep track of the current pointer position
            ulong currentOffset = 0;

            // Handle each file
            foreach (var importData in files)
            {
                // Get the file
                var file = importData.FileEntryData.CastTo <UbiArtIPKFileEntry>();

                // Reset the offset array to always contain 1 item
                file.Offsets = new ulong[]
                {
                    file.Offsets?.FirstOrDefault() ?? 0
                };

                // Set the count
                file.OffsetCount = (uint)file.Offsets.Length;

                // Add to the generator
                fileGenerator.Add(file, () =>
                {
                    // Get the file bytes to write to the archive
                    var bytes = importData.GetData(file);

                    // Set the offset
                    file.Offsets[0] = currentOffset;

                    // Increase by the file size
                    currentOffset += file.ArchiveSize;

                    return(bytes);
                });
            }

            // Set the base offset
            data.BaseOffset = data.GetHeaderSize(Settings);

            // Write the files
            data.WriteArchiveContent(outputFileStream, fileGenerator, Config.ShouldCompress(data));

            outputFileStream.Position = 0;

            // Serialize the data
            BinarySerializableHelpers.WriteToStream(data, outputFileStream, Settings, RCPServices.App.GetBinarySerializerLogger());

            RL.Logger?.LogInformationSource($"The IPK archive has been repacked");
        }
        /// <summary>
        /// Loads the archive
        /// </summary>
        public void LoadArchive()
        {
            RL.Logger?.LogInformationSource($"The archive {DisplayName} is being loaded");

            // Clear existing items
            ClearAndDisposeItems();

            // Load the archive data
            ArchiveData = Manager.LoadArchive(ArchiveFileStream);

            // Load the archive
            var data = Manager.LoadArchiveData(ArchiveData, ArchiveFileStream);

            // Dispose the current generator
            ArchiveFileGenerator?.Dispose();

            // Save the generator
            ArchiveFileGenerator = data.Generator;

            // Add each directory
            foreach (var dir in data.Directories)
            {
                // Check if it's the root directory
                if (dir.DirectoryName == String.Empty)
                {
                    // Add the files
                    Files.AddRange(dir.Files.Select(x => new ArchiveFileViewModel(x, this)));

                    continue;
                }

                // Keep track of the previous item
                ArchiveDirectoryViewModel prevItem = this;

                // Enumerate each sub directory
                foreach (string subDir in dir.DirectoryName.Trim(Manager.PathSeparatorCharacter).Split(Manager.PathSeparatorCharacter))
                {
                    // Set the previous item and create the item if it doesn't already exist
                    prevItem = prevItem.FindItem(x => x.ID == subDir) ?? prevItem.Add(subDir);
                }

                // Add the files
                prevItem.Files.AddRange(dir.Files.Select(x => new ArchiveFileViewModel(x, this)));
            }
        }
        public override void Dispose()
        {
            // Cancel refreshing thumbnails
            ExplorerDialogViewModel.CancelRefreshingThumbnails = true;

            // Dispose base class
            base.Dispose();

            // Dispose the stream
            ArchiveFileStream?.Dispose();

            // Dispose every directory
            ClearAndDisposeItems();

            // Dispose the generator
            ArchiveFileGenerator?.Dispose();

            RL.Logger?.LogInformationSource($"The archive {DisplayName} has been disposed");
        }