Example #1
0
        public void fullRePack(string inPath, string outPath, string DLCName, MainWindow mainWindow, Installer installer)
        {
            if (sfarFile != null)
            {
                throw new Exception();
            }

            if (!Directory.Exists(inPath))
            {
                throw new Exception("Directory not found: " + inPath);
            }

            List <byte[]> hashList     = new List <byte[]>();
            List <string> srcFilesList = Directory.GetFiles(inPath, "*.*", SearchOption.AllDirectories).ToList();

            srcFilesList.RemoveAll(s => s.ToLowerInvariant().Contains("default.sfar"));
            using (FileStream outputFile = new FileStream(inPath + @"\TOC", FileMode.Create, FileAccess.Write))
            {
                for (int i = 0; i < srcFilesList.Count(); i++)
                {
                    int    pos      = srcFilesList[i].IndexOf("\\BIOGame\\DLC\\", StringComparison.OrdinalIgnoreCase);
                    string filename = srcFilesList[i].Substring(pos).Replace('\\', '/');
                    hashList.Add(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(filename.ToLowerInvariant())));
                    outputFile.WriteStringASCII(filename + Environment.NewLine);
                }
            }

            hashList.Add(FileListHash);
            srcFilesList.Add(inPath + @"\TOC");

            Directory.CreateDirectory(Path.GetDirectoryName(outPath));
            using (FileStream outputFile = new FileStream(outPath, FileMode.Create, FileAccess.Write))
            {
                long numBlockSizes      = 0;
                int  curBlockSizesIndex = 0;
                long dataOffset         = HeaderSize + EntryHeaderSize * (srcFilesList.Count());
                long sizesArrayOffset   = dataOffset;
                for (int i = 0; i < srcFilesList.Count(); i++)
                {
                    if (srcFilesList[i].EndsWith(".bik", StringComparison.OrdinalIgnoreCase) ||
                        srcFilesList[i].EndsWith(".afc", StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }
                    long fileLen   = new FileInfo(srcFilesList[i]).Length;
                    long numBlocks = (fileLen + MaxBlockSize - 1) / MaxBlockSize;
                    dataOffset    += numBlocks * sizeof(ushort);
                    numBlockSizes += numBlocks;
                }

                List <FileEntry> filesList     = new List <FileEntry>();
                ushort[]         blockSizes    = new ushort[numBlockSizes];
                long             curDataOffset = dataOffset;
                outputFile.JumpTo(dataOffset);
                for (int i = 0; i < srcFilesList.Count(); i++)
                {
                    if (mainWindow != null)
                    {
                        mainWindow.updateStatusLabel2("File " + (i + 1) + " of " + srcFilesList.Count() + " - " + Path.GetFileName(srcFilesList[i]));
                    }
                    if (installer != null)
                    {
                        installer.updateStatusPrepare("Compressing DLC... " + (i + 1) + " of " + srcFilesList.Count);
                    }
                    FileEntry file      = new FileEntry();
                    Stream    inputFile = new FileStream(srcFilesList[i], FileMode.Open, FileAccess.Read);
                    long      fileLen   = new FileInfo(srcFilesList[i]).Length;
                    file.dataOffset   = curDataOffset;
                    file.uncomprSize  = fileLen;
                    file.filenameHash = hashList[i];
                    if (srcFilesList[i].EndsWith(".bik", StringComparison.OrdinalIgnoreCase) ||
                        srcFilesList[i].EndsWith(".afc", StringComparison.OrdinalIgnoreCase))
                    {
                        outputFile.WriteFromStream(inputFile, fileLen);
                        file.compressedBlockSizesIndex = -1;
                    }
                    else
                    {
                        List <byte[]> uncompressedBlockBuffers = new List <byte[]>();
                        List <byte[]> compressedBlockBuffers   = new List <byte[]>();
                        file.compressedBlockSizesIndex = curBlockSizesIndex;
                        file.numBlocks = (uint)((file.uncomprSize + MaxBlockSize - 1) / MaxBlockSize);
                        for (int k = 0; k < file.numBlocks; k++)
                        {
                            long uncompressedBlockSize = MaxBlockSize;
                            if (k == (file.numBlocks - 1)) // last block
                            {
                                uncompressedBlockSize = file.uncomprSize - (MaxBlockSize * k);
                            }
                            uncompressedBlockBuffers.Add(inputFile.ReadToBuffer((int)uncompressedBlockSize));
                            compressedBlockBuffers.Add(null);
                        }

                        Parallel.For(0, file.numBlocks, k =>
                        {
                            compressedBlockBuffers[(int)k] = SevenZipHelper.LZMA.Compress(uncompressedBlockBuffers[(int)k], 9);
                            if (compressedBlockBuffers[(int)k].Length == 0)
                            {
                                throw new Exception();
                            }
                        });

                        for (int k = 0; k < file.numBlocks; k++, curBlockSizesIndex++)
                        {
                            if (compressedBlockBuffers[k].Length >= (int)MaxBlockSize)
                            {
                                outputFile.WriteFromBuffer(uncompressedBlockBuffers[k]);
                                blockSizes[curBlockSizesIndex] = 0;
                            }
                            else if (compressedBlockBuffers[k].Length >= uncompressedBlockBuffers[k].Length)
                            {
                                outputFile.WriteFromBuffer(uncompressedBlockBuffers[k]);
                                blockSizes[curBlockSizesIndex] = (ushort)uncompressedBlockBuffers[k].Length;
                            }
                            else
                            {
                                outputFile.WriteFromBuffer(compressedBlockBuffers[k]);
                                blockSizes[curBlockSizesIndex] = (ushort)compressedBlockBuffers[k].Length;
                            }
                        }
                    }
                    curDataOffset = outputFile.Position;
                    filesList.Add(file);
                    inputFile.Close();
                }

                if (blockSizes.Count() != curBlockSizesIndex)
                {
                    throw new Exception();
                }

                outputFile.SeekBegin();
                outputFile.WriteUInt32(SfarTag);
                outputFile.WriteUInt32(SfarVersion);
                outputFile.WriteUInt32((uint)dataOffset);
                outputFile.WriteUInt32(HeaderSize);
                outputFile.WriteUInt32((uint)filesList.Count);
                outputFile.WriteUInt32((uint)sizesArrayOffset);
                outputFile.WriteUInt32((uint)MaxBlockSize);
                outputFile.WriteUInt32(LZMATag);

                filesList.Sort(new FileArrayComparer());
                for (int i = 0; i < filesList.Count; i++)
                {
                    outputFile.WriteFromBuffer(filesList[i].filenameHash);
                    outputFile.WriteInt32(filesList[i].compressedBlockSizesIndex);
                    outputFile.WriteUInt32((uint)filesList[i].uncomprSize);
                    outputFile.WriteByte((byte)(filesList[i].uncomprSize >> 32));
                    outputFile.WriteUInt32((uint)filesList[i].dataOffset);
                    outputFile.WriteByte((byte)(filesList[i].dataOffset >> 32));
                }

                if (outputFile.Position != sizesArrayOffset)
                {
                    throw new Exception();
                }

                for (int i = 0; i < blockSizes.Count(); i++)
                {
                    outputFile.WriteUInt16(blockSizes[i]);
                }

                if (outputFile.Position != dataOffset)
                {
                    throw new Exception();
                }
            }
            File.Delete(inPath + @"\TOC");
        }
Example #2
0
        static public void unpackAllDLC(MainWindow mainWindow, Installer installer)
        {
            if (!Directory.Exists(GameData.DLCData))
            {
                if (mainWindow != null)
                {
                    MessageBox.Show("No DLCs need to be extracted.");
                }
                return;
            }

            List <string> sfarFiles = Directory.GetFiles(GameData.DLCData, "Default.sfar", SearchOption.AllDirectories).ToList();

            for (int i = 0; i < sfarFiles.Count; i++)
            {
                if (File.Exists(Path.Combine(Path.GetDirectoryName(sfarFiles[i]), "Mount.dlc")))
                {
                    sfarFiles.RemoveAt(i--);
                }
            }
            if (sfarFiles.Count() == 0)
            {
                if (mainWindow != null)
                {
                    MessageBox.Show("No DLCs need to be extracted.");
                }
                return;
            }

            long diskFreeSpace = Misc.getDiskFreeSpace(GameData.GamePath);
            long diskUsage     = 0;

            for (int i = 0; i < sfarFiles.Count; i++)
            {
                diskUsage += new FileInfo(sfarFiles[i]).Length;
            }
            diskUsage = (long)(diskUsage * 2.5);
            if (diskUsage > diskFreeSpace)
            {
                if (mainWindow != null)
                {
                    MessageBox.Show("You have not enough disk space remaining. You need about " + Misc.getBytesFormat(diskUsage) + " free.");
                }
                return;
            }

            string tmpDlcDir = Path.Combine(GameData.GamePath, "BIOGame", "DLCTemp");

            if (Directory.Exists(tmpDlcDir))
            {
                Directory.Delete(tmpDlcDir, true);
            }
            Directory.CreateDirectory(tmpDlcDir);
            string originInstallFiles = Path.Combine(GameData.DLCData, "__metadata");

            if (Directory.Exists(originInstallFiles))
            {
                Directory.Move(originInstallFiles, tmpDlcDir + "\\__metadata");
            }
            for (int i = 0; i < sfarFiles.Count; i++)
            {
                string DLCname = Path.GetFileName(Path.GetDirectoryName(Path.GetDirectoryName(sfarFiles[i])));
                string outPath = Path.Combine(tmpDlcDir, DLCname);
                Directory.CreateDirectory(outPath);
                ME3DLC dlc = new ME3DLC(mainWindow);
                if (mainWindow != null)
                {
                    mainWindow.updateStatusLabel("SFAR extracting - DLC " + (i + 1) + " of " + sfarFiles.Count);
                }
                if (installer != null)
                {
                    installer.updateStatusPrepare("Extracting DLC ... " + (i + 1) + " of " + sfarFiles.Count);
                }
                dlc.extract(sfarFiles[i], outPath);
            }

            sfarFiles = Directory.GetFiles(GameData.DLCData, "Default.sfar", SearchOption.AllDirectories).ToList();
            for (int i = 0; i < sfarFiles.Count; i++)
            {
                if (File.Exists(Path.Combine(Path.GetDirectoryName(sfarFiles[i]), "Mount.dlc")))
                {
                    string source = Path.GetDirectoryName(Path.GetDirectoryName(sfarFiles[i]));
                    Directory.Move(source, tmpDlcDir + "\\" + Path.GetFileName(source));
                }
            }

            Directory.Delete(GameData.DLCData, true);
            Directory.Move(tmpDlcDir, GameData.DLCData);
        }
Example #3
0
        public void extract(string SFARfilename, string outPath, bool ipc, ref int currentProgress, int totalNumber)
        {
            if (!File.Exists(SFARfilename))
            {
                throw new Exception("filename missing");
            }

            if (mainWindow != null)
            {
                mainWindow.updateStatusLabel2("Loading SFAR...");
            }
            byte[] buffer = File.ReadAllBytes(SFARfilename);

            File.Delete(SFARfilename);
            using (FileStream outputFile = new FileStream(SFARfilename, FileMode.Create, FileAccess.Write))
            {
                outputFile.WriteUInt32(SfarTag);
                outputFile.WriteUInt32(SfarVersion);
                outputFile.WriteUInt32(HeaderSize);
                outputFile.WriteUInt32(HeaderSize);
                outputFile.WriteUInt32(0);
                outputFile.WriteUInt32(HeaderSize);
                outputFile.WriteUInt32((uint)MaxBlockSize);
                outputFile.WriteUInt32(LZMATag);
            }

            using (MemoryStream stream = new MemoryStream(buffer))
            {
                loadHeader(stream);

                int lastProgress = -1;
                for (int i = 0; i < filesCount; i++, currentProgress++)
                {
                    if (filenamesIndex == i)
                    {
                        continue;
                    }
                    if (filesList[i].filenamePath == null)
                    {
                        throw new Exception("filename missing");
                    }

                    if (mainWindow != null)
                    {
                        mainWindow.updateStatusLabel2("File " + (i + 1) + " of " + filesList.Count() + " - " + Path.GetFileName(filesList[i].filenamePath));
                    }
                    if (installer != null)
                    {
                        installer.updateStatusPrepare("Unpacking DLC " + ((currentProgress + 1) * 100 / totalNumber) + "%");
                    }
                    if (ipc)
                    {
                        int newProgress = (100 * currentProgress) / totalNumber;
                        if (lastProgress != newProgress)
                        {
                            Console.WriteLine("[IPC]TASK_PROGRESS " + newProgress);
                            Console.Out.Flush();
                            lastProgress = newProgress;
                        }
                    }

                    int    pos      = filesList[i].filenamePath.IndexOf("\\BIOGame\\DLC\\", StringComparison.OrdinalIgnoreCase);
                    string filename = filesList[i].filenamePath.Substring(pos + ("\\BIOGame\\DLC\\").Length).Replace('/', '\\');
                    string dir      = Path.GetDirectoryName(outPath);
                    Directory.CreateDirectory(Path.GetDirectoryName(dir + filename));
                    using (FileStream outputFile = new FileStream(dir + filename, FileMode.Create, FileAccess.Write))
                    {
                        stream.JumpTo(filesList[i].dataOffset);
                        if (filesList[i].compressedBlockSizesIndex == -1)
                        {
                            outputFile.WriteFromStream(stream, filesList[i].uncomprSize);
                        }
                        else
                        {
                            List <byte[]> uncompressedBlockBuffers = new List <byte[]>();
                            List <byte[]> compressedBlockBuffers   = new List <byte[]>();
                            List <long>   blockBytesLeft           = new List <long>();
                            long          bytesLeft = filesList[i].uncomprSize;
                            for (int j = 0; j < filesList[i].numBlocks; j++)
                            {
                                blockBytesLeft.Add(bytesLeft);
                                int compressedBlockSize   = blockSizes[filesList[i].compressedBlockSizesIndex + j];
                                int uncompressedBlockSize = (int)Math.Min(bytesLeft, maxBlockSize);
                                if (compressedBlockSize == 0)
                                {
                                    compressedBlockSize = (int)maxBlockSize;
                                }
                                compressedBlockBuffers.Add(stream.ReadToBuffer(compressedBlockSize));
                                uncompressedBlockBuffers.Add(null);
                                bytesLeft -= uncompressedBlockSize;
                            }

                            Parallel.For(0, filesList[i].numBlocks, j =>
                            {
                                int compressedBlockSize   = blockSizes[filesList[i].compressedBlockSizesIndex + (int)j];
                                int uncompressedBlockSize = (int)Math.Min(blockBytesLeft[(int)j], maxBlockSize);
                                if (compressedBlockSize == 0 || compressedBlockSize == blockBytesLeft[(int)j])
                                {
                                    uncompressedBlockBuffers[(int)j] = compressedBlockBuffers[(int)j];
                                }
                                else
                                {
                                    uncompressedBlockBuffers[(int)j] = new SevenZipHelper.LZMA().Decompress(compressedBlockBuffers[(int)j], (uint)uncompressedBlockSize);
                                    if (uncompressedBlockBuffers[(int)j].Length == 0)
                                    {
                                        throw new Exception();
                                    }
                                }
                            });

                            for (int j = 0; j < filesList[i].numBlocks; j++)
                            {
                                outputFile.WriteFromBuffer(uncompressedBlockBuffers[j]);
                            }
                        }
                    }
                }
            }
        }