예제 #1
0
        //------------------------- GUI Treeview Functions --------------------------

        private void treeViewSfar_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeNode node = treeViewSfar.SelectedNode;

            if (node == null || isFolder(node))
            {
                return;
            }
            //prevents the image change
            node.SelectedImageIndex = node.ImageIndex;

            // if the program is extracting or replacing a file, it doesn't update the bottom status label
            if (!backgroundWorkerExtractFile.IsBusy && !backgroundWorkerEditFile.IsBusy)
            {
                toolStripStatusLabel.Text    = node.Name;
                toolStripStatusLabel.Visible = true;
            }

            if (!dlcBase.fileList.Contains(FileNameHash.Compute(node.Name)))
            {
                return;
            }

            //the hard part begins here!
            sfarFile entry = dlcBase.fileList[FileNameHash.Compute(node.Name)];
            int      fileBlockIndex;
            int      fileComprSize = 0;
            float    fileSize;
            string   strFileSize = "";

            fileBlockIndex       = entry.blockSizeIndex;
            textBoxFullName.Text = node.Name;
            textBoxHash.Text     = entry.nameHash.ToString();

            setSize(entry.uncompressedSize, out fileSize, ref strFileSize);
            textBoxUncSize.Text    = fileSize.ToString("0.0", CultureInfo.InvariantCulture);
            labelUncSizeBytes.Text = strFileSize;

            if (fileBlockIndex != -1)
            {
                for (int i = 0; i < entry.blockSizeArray.Length; i++)
                {
                    fileComprSize += entry.blockSizeArray[i];
                }

                setSize(fileComprSize, out fileSize, ref strFileSize);
                textBoxComprSize.Text    = fileSize.ToString("0.0", CultureInfo.InvariantCulture);
                labelComprSizeBytes.Text = strFileSize;
            }
            else
            {
                setSize(entry.uncompressedSize, out fileSize, ref strFileSize);
                textBoxComprSize.Text    = fileSize.ToString("0.0", CultureInfo.InvariantCulture);
                labelComprSizeBytes.Text = strFileSize;
            }
            textBoxEntry.Text      = "0x" + entry.entryOffset.ToString("X8");
            textBoxBlockIndex.Text = fileBlockIndex.ToString();
            textBoxDataOffset.Text = "0x" + entry.dataOffset[0].ToString("X8");
        }
예제 #2
0
        private void propertiesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode node    = treeViewSfar.SelectedNode;
            string   message = "";
            float    fileSize;
            float    comprRatio;
            string   strFileSize = "";

            if (isFile(node))
            {
                FileNameHash fileHash       = FileNameHash.Compute(node.Name);
                sfarFile     entry          = dlcBase.fileList[fileHash];
                int          compressedSize = 0;
                if (entry.blockSizeIndex != -1)
                {
                    foreach (int i in entry.blockSizeArray)
                    {
                        compressedSize += i;
                    }
                }
                else
                {
                    compressedSize = (int)entry.uncompressedSize;
                }

                message += "Full Path:      " + entry.fileName +
                           "\n\nHash file name: " + fileHash;

                setSize(entry.uncompressedSize, out fileSize, ref strFileSize);
                message += "\n\nFile size: " + fileSize.ToString("0.0", CultureInfo.InvariantCulture) + " " + strFileSize;
                message += " (" + entry.uncompressedSize.ToString("0,0", CultureInfo.InvariantCulture) + " Bytes)";

                setSize(compressedSize, out fileSize, ref strFileSize);
                message += "\n\nCompressed size: " + fileSize.ToString("0.0", CultureInfo.InvariantCulture) + " " + strFileSize;
                message += " (" + compressedSize.ToString("0,0", CultureInfo.InvariantCulture) + " Bytes)";

                comprRatio = compressedSize / (float)entry.uncompressedSize * 100;
                message   += "\n\nCompression Ratio: " + comprRatio.ToString("0.#") + "%";

                MessageBox.Show(message, "Properties - " + node.Text, MessageBoxButtons.OK, MessageBoxIcon.None);
            }
        }
예제 #3
0
            //int highPerc = 0;
#else
        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((double)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((double)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((double)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 + ((int)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((long)inDataOffset, 0);
                                inputBlock = new byte[fileSize];
                                input.Read(inputBlock, 0, fileSize);

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

                                outBlockIndex = entry.blockSizeIndex;
                            }
                            else
                            {
                                numBlocks = (int)Math.Ceiling((double)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((long)inDataOffset, 0);
                                    input.Read(inputBlock, 0, (int)blockSize);
                                    inDataOffset += (int)blockSize;

                                    output.Seek((long)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((long)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((long)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((long)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((long)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((long)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((long)outPointerBlockSize, 0);
                    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)streamRead.Length;

                    output.Seek((long)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((int)fileSize);
                    output.WriteValueU8(0x00);
                    output.WriteValueS32(outDataOffset);
                    output.WriteValueU8(0x00);
                    outPointerEntry = (int)output.Position;
                }

            }// end of using...

        }
예제 #4
0
        private void extractToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode node = treeViewSfar.SelectedNode;

            extractFileDialog.FileName = node.Text;
            List <sfarFile> listFiles = new List <sfarFile>();

            //add selected file(s) to the extraction list
            if (isFile(node) && extractFileDialog.ShowDialog() == DialogResult.OK)
            {
                sfarFile entry = dlcBase.fileList[FileNameHash.Compute(node.Name)];
                listFiles.Add(entry);
            }
            else if (isFolder(node) && extractFolderDialog.ShowDialog() == Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogResult.Ok)
            {
                foreach (sfarFile entry in dlcBase.fileList)
                {
                    string fileName = entry.fileName;
                    int    indexStr;
                    if (fileName == null)
                    {
                        continue;
                    }
                    indexStr = fileName.IndexOf(node.Text);
                    if (indexStr != -1)
                    {
                        listFiles.Add(entry);
                    }
                }
            }
            else // safety else, hopefully never enters
            {
                return;
            }

            toolStripProgressBar.Visible = true;
            toolStripStatusLabel.Visible = true;

            try
            {
                //main extraction
                backgroundWorkerExtractFile.RunWorkerAsync(new object[2] {
                    listFiles, node
                });
                while (backgroundWorkerExtractFile.IsBusy)
                {
                    // Keep UI messages moving, so the form remains
                    // responsive during the asynchronous operation.
                    if (backgroundWorkerExtractFile.CancellationPending)
                    {
                        return;
                    }
                    else
                    {
                        Application.DoEvents();
                    }
                }

                toolStripStatusLabel.Text = "Done.";

                if (isFile(node))
                {
                    MessageBox.Show("File " + node.Text + " has been successfully extracted.", "Extraction success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show("All files from folder " + node.Text + " have been successfully extracted.", "Extraction success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }

                toolStripProgressBar.Visible = false;
            }
            catch (Exception exc)
            {
                MessageBox.Show("An error occurred while extracting " + node.Text + ":\n" + exc.Message, "Exception Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }