ME3Explorer.Unreal.DLCPackage.DecompressEntryAsync C# (CSharp) Method

DecompressEntryAsync() public method

public DecompressEntryAsync ( int index, Stream output ) : Task
index int
output Stream
return Task
        public async Task DecompressEntryAsync(int index, Stream output)
        {
            var entry = Files[index];
            using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.None, 4096, useAsync: true))
            {
                fs.Seek(entry.BlockOffsets[0], SeekOrigin.Begin);

                //not compressed
                if (entry.BlockSizeIndex == 0xFFFFFFFF)
                {
                    var uncompressed = new byte[entry.RealUncompressedSize];
                    await fs.ReadAsync(uncompressed, 0, uncompressed.Length).ConfigureAwait(continueOnCapturedContext: false);
                    await output.WriteAsync(uncompressed, 0, uncompressed.Length).ConfigureAwait(continueOnCapturedContext: false);

                    return;
                }

                var decompressor = new TransformBlock<InputBlock, byte[]>(
                    input => input.IsCompressed
                        ? SevenZipHelper.Decompress(input.Data, input.UncompressedSize)
                        : input.Data
                    , new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded }
                    );

                var outputWriter = new ActionBlock<byte[]>(
                    data => output.Write(data, 0, data.Length)
                    );

                decompressor.LinkTo(outputWriter, new DataflowLinkOptions { PropagateCompletion = true });

                uint count = 0;
                long left = entry.RealUncompressedSize;
                while (left > 0)
                {
                    uint compressedBlockSize = entry.BlockSizes[count];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = Header.MaxBlockSize;
                    }

                    if (compressedBlockSize == Header.MaxBlockSize ||
                        compressedBlockSize == left)
                    {
                        left -= compressedBlockSize;
                        var uncompressedData = new byte[compressedBlockSize];
                        await fs.ReadAsync(uncompressedData, 0, uncompressedData.Length).ConfigureAwait(continueOnCapturedContext: false);
                        decompressor.Post(new InputBlock(uncompressedData, InputBlock.Uncompressed));
                    }
                    else
                    {
                        var uncompressedBlockSize = Math.Min(left, Header.MaxBlockSize);
                        left -= uncompressedBlockSize;
                        if (compressedBlockSize < 5)
                        {
                            throw new Exception("compressed block size smaller than 5");
                        }

                        var compressedData = new byte[compressedBlockSize];
                        await fs.ReadAsync(compressedData, 0, (int)compressedBlockSize).ConfigureAwait(continueOnCapturedContext: false);

                        decompressor.Post(new InputBlock(compressedData, uncompressedBlockSize));
                    }
                    count++;
                }

                decompressor.Complete();
                await outputWriter.Completion;
            }
        }

Usage Example

Esempio n. 1
0
        public static void unpackSFAR(DLCPackage dlc)
        {
            if (dlc == null || dlc.Files == null)
                return;
            string[] patt = { "pcc", "bik", "tfc", "afc", "cnd", "tlk", "bin", "dlc" };
            string file = dlc.FileName;                   //full path
            string t1 = Path.GetDirectoryName(file);        //cooked
            string t2 = Path.GetDirectoryName(t1);          //DLC_Name
            string t3 = Path.GetDirectoryName(t2);          //DLC
            string t4 = Path.GetDirectoryName(t3);          //BioGame
            string gamebase = Path.GetDirectoryName(t4);    //Mass Effect3
            DebugOutput.PrintLn("Extracting DLC with gamebase : " + gamebase);
            DebugOutput.PrintLn("DLC name : " + t2);
            if (dlc.Files.Length > 1)
            {
                List<int> Indexes = new List<int>();
                for (int i = 0; i < dlc.Files.Length; i++)
                {
                    string DLCpath = dlc.Files[i].FileName;
                    for (int j = 0; j < patt.Length; j++)
                        if (DLCpath.ToLower().EndsWith(patt[j].Trim().ToLower()) && patt[j].Trim().ToLower() != "")
                        {
                            string relPath = GetRelativePath(DLCpath);
                            string outpath = gamebase + relPath;
                            DebugOutput.PrintLn("Extracting file #" + i.ToString("d4") + ": " + outpath);
                            if (!Directory.Exists(Path.GetDirectoryName(outpath)))
                                Directory.CreateDirectory(Path.GetDirectoryName(outpath));

                            if (!File.Exists(outpath))
                                using (FileStream fs = new FileStream(outpath, FileMode.Create))
                                    dlc.DecompressEntryAsync(i, fs).Wait();
                            Indexes.Add(i);
                            Application.DoEvents();
                            break;
                        }
                }
                dlc.DeleteEntries(Indexes);
            }

            // AutoTOC
            AutoTOC.prepareToCreateTOC(t2 + "\\PCConsoleTOC.bin");
            DebugOutput.PrintLn("DLC Done.");
        }
All Usage Examples Of ME3Explorer.Unreal.DLCPackage::DecompressEntryAsync