AmaroK86.MassEffect3.DLCEditor.Execute C# (CSharp) Метод

Execute() публичный Метод

public Execute ( string outputFile ) : void
outputFile string
Результат void
        public void Execute(string outputFile)
        {
#endif
            var inputPath = dlcBase.fileName;
            if (!File.Exists(inputPath))
                throw new FileNotFoundException("Error: the input file doesn't exists");

            /*string filePathToReplace = selectedFile;
            string fileToReplace = Path.GetFileName(filePathToReplace);
            FileNameHash fileToReplaceHash = new FileNameHash();*/

            string outputFileName = Path.GetFileNameWithoutExtension(inputPath);

            int inPointerBlockSize = 0;
            int outPointerEntry = 0x20;
            int outPointerEntryFileList = 0;
            int outPointerBlockSize = 0;
            int outPointerData = 0;

            int blocksToRemove = 0;
            int blocksToAdd = 0;

            using (FileStream input = File.OpenRead(inputPath),
                   output = File.OpenWrite(outputFile))
            {
                string dlcFileList = "";
                int outNumOfEntries = 0;
                //recreating the file list
                foreach (var kvp in listComplete)
                {
                    if (kvp.Value != action.delete)
                    {
                        outNumOfEntries++;
                        if (kvp.Key == DLCBase.fileListHash)
                            continue;
                        switch (kvp.Value)
                        {
                            case action.copy:
                            case action.replace:
                                dlcFileList += dlcBase.fileList[kvp.Key].fileName + Environment.NewLine;
                                break;
                            case action.add:
                                dlcFileList += listAdd[kvp.Key].fileName + Environment.NewLine;
                                break;
                        }
                    }
                }
                blocksToRemove += dlcBase.fileList[DLCBase.fileListHash].blockSizeArray.Length;
                blocksToAdd += (int)Math.Ceiling(dlcFileList.Length / (double)DLCBase.MaximumBlockSize);

                foreach (var kvp in listAdd)
                {
                    string fPath = kvp.Value.filePath;
                    if ((Path.GetExtension(fPath) != ".bik" &&
                         Path.GetExtension(fPath) != ".afc"))
                        blocksToAdd += (int)Math.Ceiling(DLCPack.Getsize(kvp.Value.filePath) / (double)DLCBase.MaximumBlockSize);
                }

                foreach (var kvp in listReplace)
                {
                    if (dlcBase.fileList[kvp.Key].blockSizeIndex != -1)
                    {
                        blocksToRemove += dlcBase.fileList[kvp.Key].blockSizeArray.Length;
                        blocksToAdd += (int)Math.Ceiling(DLCPack.Getsize(kvp.Value) / (double)DLCBase.MaximumBlockSize);
                    }
                }

                foreach (var kvp in listDelete)
                {
                    if (dlcBase.fileList[kvp.Key].blockSizeIndex != -1)
                        blocksToRemove += dlcBase.fileList[kvp.Key].blockSizeArray.Length;
                }

                var inputBlock = new byte[DLCBase.MaximumBlockSize];
                var outputBlock = new byte[DLCBase.MaximumBlockSize];
                //writing header of new sfar file
                input.Seek(0, 0);
                input.Read(inputBlock, 0, 32);
                output.Write(inputBlock, 0, 32);

                //getting initial blocks and data offsets
                inPointerBlockSize = 0x20 + (dlcBase.fileList.Count * 0x1E);
                outPointerBlockSize = 0x20 + outNumOfEntries * 0x1E;
                input.Seek(8, 0);
                int inDataOffset = input.ReadValueS32();
                int outBlockCount = ((inDataOffset - inPointerBlockSize) / 2) - blocksToRemove + blocksToAdd;
                outPointerData = outPointerBlockSize + (outBlockCount * 2);

                //writing new header's values
                output.Seek(8, 0);
                output.WriteValueS32(outPointerData);

                output.Seek(16, 0);
                output.WriteValueS32(outNumOfEntries);

                output.Seek(20, 0);
                output.WriteValueS32(outPointerBlockSize);

                if (verbose)
                {
                    Console.WriteLine("num entries: {0}", outNumOfEntries);
                    Console.WriteLine("data offset: {0:X8}", inDataOffset);
                    Console.WriteLine("blocks to remove: {0}", blocksToRemove);
                    Console.WriteLine("blocks to add: {0}", blocksToAdd);
                    Console.WriteLine("old block offset: {0:X8}", inPointerBlockSize);
                    Console.WriteLine("new block offset: {0:X8}", outPointerBlockSize);
                    Console.WriteLine("old block count: {0}", (inDataOffset - inPointerBlockSize) / 2);
                    Console.WriteLine("new block count: {0}", outBlockCount);
                    Console.WriteLine("pointer data: {0:X8}\n", outPointerData);
                }

                int numBlocks;
                int outDataOffset;
                int blockIndexCounter = 0;
                int outBlockIndex = 0;
                int fileSize = 0;

                int outInitialDataOffset = outPointerData;
                int outInitialBlockOffset = outPointerBlockSize;

                foreach (var kvp in listComplete)
                {
                    count++;

                    if (kvp.Value == action.delete)
                        continue;

                    if (kvp.Key == DLCBase.fileListHash)
                    {
                        //Console.WriteLine("File List Found at {0:X8}", outPointerEntry);
                        outPointerEntryFileList = outPointerEntry;
                        outPointerEntry += 0x1E;
                        continue;
                    }

                    sfarFile entry;
                    FileNameHash hashEntry = kvp.Key;

                    if (kvp.Value == action.add)
                    {
                        string fPath = listAdd[kvp.Key].filePath;
                        entry = new sfarFile();
                        entry.nameHash = kvp.Key;
                        entry.dataOffset = new long[1];
                        fileSize = (int)DLCPack.Getsize(fPath);
                        if ((Path.GetExtension(fPath) == ".bik" ||
                             Path.GetExtension(fPath) == ".afc"))
                            entry.blockSizeIndex = -1;
                    }
                    else
                    {
                        entry = dlcBase.fileList[kvp.Key];
                        fileSize = (int)entry.uncompressedSize;
                    }

                    outDataOffset = outPointerData;
                    outBlockIndex = blockIndexCounter;

                    /*#if (WITH_GUI)
                                        int perc = (int)Math.Ceiling((float)count++ / (float)listComplete.Count * 100);
                                        if (perc > highPerc)
                                        {
                                            highPerc = perc;
                                            if (perc > 100)
                                                perc = 100;
                                            worker.ReportProgress(perc);
                                        }
                    #endif*/

                    switch (kvp.Value)
                    {
                        case action.copy:
                            if (worker != null)
                                worker.ReportProgress(0, count + "/" + listComplete.Count + ": Copying " + Path.GetFileName(entry.fileName));
                            if (entry.blockSizeIndex == -1)
                            {
                                inDataOffset = (int)entry.dataOffset[0];
                                input.Seek(inDataOffset, 0);
                                inputBlock = new byte[fileSize];
                                input.Read(inputBlock, 0, fileSize);

                                output.Seek(outPointerData, 0);
                                output.Write(inputBlock, 0, fileSize);
                                outPointerData += fileSize;

                                outBlockIndex = entry.blockSizeIndex;
                            }
                            else
                            {
                                numBlocks = (int)Math.Ceiling(fileSize / (double)DLCBase.MaximumBlockSize);
                                inDataOffset = (int)entry.dataOffset[0];
                                for (int i = 0; i < numBlocks; i++)
                                {
                                    uint blockSize = entry.blockSizeArray[i];
                                    if ((ushort)blockSize != entry.blockSizeArray[i])
                                        throw new Exception("different blocksizes");
                                    blockSize = blockSize == 0 ? DLCBase.MaximumBlockSize : blockSize;

                                    inputBlock = new byte[blockSize];
                                    input.Seek(inDataOffset, 0);
                                    input.Read(inputBlock, 0, (int)blockSize);
                                    inDataOffset += (int)blockSize;

                                    output.Seek(outPointerBlockSize, 0);
                                    if (blockSize == DLCBase.MaximumBlockSize)
                                        output.WriteValueU16(0);
                                    else
                                        output.WriteValueU16((ushort)blockSize);
                                    if (outPointerBlockSize > outInitialDataOffset)
                                        throw new Exception("Block index offset values out of range,\n  last block: " + blockIndexCounter + "\n  Pointer Block: " + outPointerBlockSize.ToString("X8") + "\n  Data Offset: " + outInitialDataOffset.ToString("X8"));
                                    outPointerBlockSize += 2;

                                    output.Seek(outPointerData, 0);
                                    output.Write(inputBlock, 0, (int)blockSize);
                                    if (output.Position - outPointerData != blockSize)
                                    {
                                        Console.WriteLine("  diff position: {0}, blocksize: {1}", output.Position - outPointerData, blockSize);
                                        throw new Exception("error writing file");
                                    }
                                    outPointerData += (int)blockSize;
                                }
                                blockIndexCounter += numBlocks;
                            }
                            break;
                        case action.add:
                        case action.replace:
                            string selectedFile;
                            if (kvp.Value == action.replace)
                            {
                                selectedFile = listReplace[kvp.Key];
                                if (worker != null)
                                    worker.ReportProgress(0, count + "/" + listComplete.Count + ": Replacing " + Path.GetFileName(selectedFile));
                            }
                            else
                            {
                                selectedFile = listAdd[kvp.Key].filePath;
                                if (worker != null)
                                    worker.ReportProgress(0, count + "/" + listComplete.Count + ": Adding " + Path.GetFileName(selectedFile));
                            }
                            output.Seek(outPointerBlockSize, 0);
                            //compressing the replacing file
                            ushort[] blockSizeArray;

                            using (FileStream streamFile = new FileStream(selectedFile, FileMode.Open, FileAccess.Read))
                            {
                                fileSize = (int)streamFile.Length;
                                if ((Path.GetExtension(selectedFile) == ".bik" || Path.GetExtension(selectedFile) == ".afc") && entry.blockSizeIndex == -1)
                                {
                                    outBlockIndex = -1;
                                    output.Seek(outPointerData, SeekOrigin.Begin);
                                    output.WriteFromStream(streamFile, streamFile.Length);
                                    outPointerData += (int)streamFile.Length;
                                }
                                else
                                {
                                    byte[][] comprArr;
                                    DLCPack.CompressFile(streamFile, out blockSizeArray, out comprArr, Threads);

                                    for (int i = 0; i < blockSizeArray.Length; i++)
                                        output.WriteValueU16(blockSizeArray[i]);
                                    outPointerBlockSize += (blockSizeArray.Length * 2);
                                    blockIndexCounter += blockSizeArray.Length;

                                    output.Seek(outPointerData, SeekOrigin.Begin);
                                    int totallength = 0;
                                    for (int i = 0; i < comprArr.Length; i++)
                                    {
                                        output.WriteBytes(comprArr[i]);
                                        totallength += comprArr[i].Length;
                                    }
                                    //outPointerData += (int)streamFile.Length;
                                    outPointerData += totallength;
                                }
                            }
                            #region blah di blah
                            /*
                            FileStream streamFile = File.OpenRead(selectedFile);
                            if ((Path.GetExtension(selectedFile) == ".bik" ||
                                 Path.GetExtension(selectedFile) == ".afc") &&
                                entry.blockSizeIndex == -1)
                            {
                                streamFile.CopyTo(encStream);
                                outBlockIndex = -1;
                            }
                            else
                            {
                                //DLCPack.CompressFile(streamFile, out blockSizeArray, encStream, worker);
                                byte[][] comprArr;
                                DLCPack.CompressFile(streamFile, out blockSizeArray, out comprArr);

                                for (int i = 0; i < blockSizeArray.Length; i++)
                                {
                                    output.WriteValueU16(blockSizeArray[i]);
                                }
                                outPointerBlockSize += (blockSizeArray.Length * 2);
                                blockIndexCounter += blockSizeArray.Length;
                            }
                            output.Seek((long)outPointerData, 0);
                            encStream.WriteTo(output);
                            outPointerData += (int)encStream.Length;

                            fileSize = (int)streamFile.Length;
                            streamFile.Close();
                            */
                            #endregion
                            break;
                    }// end switch

                    if (worker != null)
                        worker.ReportProgress(100);

                    output.Seek(outPointerEntry, 0);
                    output.WriteValueU32(hashEntry.A.Swap());
                    output.WriteValueU32(hashEntry.B.Swap());
                    output.WriteValueU32(hashEntry.C.Swap());
                    output.WriteValueU32(hashEntry.D.Swap());
                    output.WriteValueS32(outBlockIndex);
                    output.WriteValueS32(fileSize);
                    output.WriteValueU8(0);
                    output.WriteValueS32(outDataOffset);
                    output.WriteValueU8(0);
                    outPointerEntry += 0x1E;
                    if (outPointerEntry > outInitialBlockOffset)
                    {
                        throw new Exception("Entry index offset values out of range");
                    }
                }// end of foreach

                //writing the file list entry, blocksizes & data
                outDataOffset = outPointerData;
                outBlockIndex = blockIndexCounter;
                {
                    MemoryStream streamRead = new MemoryStream(ASCIIEncoding.Default.GetBytes(dlcFileList));
                    ushort[] blockSizeArray;
                    MemoryStream encStream = new MemoryStream();
                    DLCPack.CompressFile(streamRead, out blockSizeArray, encStream);

                    output.Seek(outPointerBlockSize, 0);
                    for (int i = 0; i < blockSizeArray.Length; i++)
                    {
                        output.WriteValueU16(blockSizeArray[i]);
                    }
                    outPointerBlockSize += (blockSizeArray.Length * 2);
                    blockIndexCounter += blockSizeArray.Length;

                    output.Seek(outPointerData, 0);
                    encStream.WriteTo(output);
                    outPointerData += (int)encStream.Length;

                    fileSize = (int)streamRead.Length;

                    output.Seek(outPointerEntryFileList, 0);
                    output.WriteValueU32(DLCBase.fileListHash.A.Swap());
                    output.WriteValueU32(DLCBase.fileListHash.B.Swap());
                    output.WriteValueU32(DLCBase.fileListHash.C.Swap());
                    output.WriteValueU32(DLCBase.fileListHash.D.Swap());
                    output.WriteValueS32(outBlockIndex);
                    output.WriteValueS32(fileSize);
                    output.WriteValueU8(0x00);
                    output.WriteValueS32(outDataOffset);
                    output.WriteValueU8(0x00);
                    outPointerEntry = (int)output.Position;
                }

            }// end of using...

        }
    }

Same methods

DLCEditor::Execute ( string outputFile, BackgroundWorker worker = null, int Threads = 2 ) : void

Usage Example

Пример #1
0
        public static void RepackDLCs(bool MakeBackup = true)
        {
            if (!repackEnabled)
                return;
            String[] dlcupdates = GetFilesForRepacking();
            if (!Directory.Exists(GetDLCCachePath()))
                throw new FileNotFoundException("DLC Cache Path not found");
            if (dlcupdates.Length == 0)
            {
                DebugOutput.PrintLn("No updates found!");
                return;
            }

            List<String> tempdlcupdates = new List<string>();
            for (int i = 0; i < dlcupdates.Length; i++)
            {
                bool filefound = false;
                for (int j = 0; j < tempdlcupdates.Count; j++)
                {
                    if (String.Compare(dlcupdates[i], tempdlcupdates[j]) == 0)
                    {
                        filefound = true;
                        break;
                    }
                }
                if (!filefound)
                    tempdlcupdates.Add(dlcupdates[i]);
            }
            dlcupdates = tempdlcupdates.ToArray();

            DebugOutput.PrintLn("Repacking modified DLCs...");
            String DLCPath = Path.GetDirectoryName(listpath);
            string[] DLCs = Directory.EnumerateDirectories(DLCPath, "*", SearchOption.TopDirectoryOnly).ToArray();

            for (int i = 0; i < DLCs.Length; i++)
            {
                DirectoryInfo dinfo = new DirectoryInfo(DLCs[i]);
                FileInfo[] files = dinfo.GetFiles();
                List<String> updates = new List<string>();
                string commonname = Path.GetFileName(DLCs[i]);
                for (int j = 0; j < dlcupdates.Length; j++)
                {
                    if (Path.GetFileName(Path.GetDirectoryName(dlcupdates[j])) != commonname)
                        continue;

                    for (int k = 0; k < files.Length; k++)
                    {
                        if (String.Compare(files[k].Name, Path.GetFileName(dlcupdates[j]), true) == 0)
                        {
                            updates.Add(dlcupdates[j]);
                            break;
                        }
                    }
                }

                if (updates.Count <= 0)
                    continue;

                DebugOutput.PrintLn("DLC Updates found for " + commonname + ". Now fixing PCConsoleTOC.bin and repacking...");

                DLCBase dlcbase;
                try
                {
                    string[] tempdlc = Directory.GetFiles(Path.Combine(Path.GetDirectoryName(DLCPath), "DLC", commonname), "Default.sfar", SearchOption.AllDirectories);
                    if (tempdlc == null || tempdlc.Length == 0)
                        throw new FileNotFoundException("DLC File not found!");

                    // KFreon: Allow no backup file creation
                    if (MakeBackup)
                    {
                        if (!File.Exists(Path.ChangeExtension(tempdlc[0], ".bak")))
                        {
                            DebugOutput.PrintLn("DLC backup file not found. Creating...");
                            File.Copy(tempdlc[0], Path.ChangeExtension(tempdlc[0], ".bak"), true);
                        }
                    }
                    dlcbase = new DLCBase(tempdlc[0]);
                }
                catch (FileNotFoundException)
                {
                    DebugOutput.PrintLn("DLC File Not Found");
                    continue;
                }
                catch 
                { 
                    DebugOutput.PrintLn("DLC Opening failed");
                    continue;
                }

                DLCEditor editor = new DLCEditor(dlcbase);

                String tocpath = null;
                for (int j = 0; j < files.Length; j++)
                {
                    if (String.Compare(Path.GetFileName(files[j].Name), "PCConsoleTOC.bin", true) == 0)
                    {
                        DLCTocFix(files[j].FullName);
                        tocpath = files[j].FullName;
                        break;
                    }
                }

                for (int j = 0; j < updates.Count; j++)
                {
                    String tempname = dlcbase.getFullNameOfEntry(updates[j]);
                    if (tempname == null)
                        throw new FileNotFoundException("Filename not found in DLC's files");
                    editor.setReplaceFile(tempname, updates[j]);
                }

                // Also add toc.bin
                String temptoc = dlcbase.getFullNameOfEntry(tocpath);
                if (temptoc == null)
                    throw new FileNotFoundException("TOC not found in DLC's files");
                editor.setReplaceFile(temptoc, tocpath);

                editor.Execute(Path.ChangeExtension(dlcbase.fileName, ".new"), null, Properties.Settings.Default.NumThreads);
                if (File.Exists(Path.ChangeExtension(dlcbase.fileName, ".new")))
                {
                    File.Copy(Path.ChangeExtension(dlcbase.fileName, ".new"), dlcbase.fileName, true);
                    File.Delete(Path.ChangeExtension(dlcbase.fileName, ".new"));
                }
                DebugOutput.PrintLn("Finished updating " + commonname, true);
            }
            File.Delete(listpath); // Reset the repack file
        }