Beispiel #1
0
 public void DeleteEntry(int Index)
 {
     try
     {
         FileStream fs       = new FileStream(FileName, FileMode.Open, FileAccess.Read);
         int        tocIndex = findTOCIndex();
         if (tocIndex == -1)
         {
             return;
         }
         MemoryStream m = DecompressEntry(tocIndex, fs);
         fs.Close();
         FileEntryStruct e    = Files[Index];
         string          toc  = Encoding.UTF8.GetString(m.ToArray(), 0, (int)m.Length);
         string          file = e.FileName + "\r\n";
         toc = toc.Replace(file, "");
         ReplaceEntry(Encoding.ASCII.GetBytes(toc), tocIndex);
         List <FileEntryStruct> l = new List <FileEntryStruct>();
         l.AddRange(Files);
         l.RemoveAt(Index);
         Files = l.ToArray();
         Header.FileCount--;
         ReBuild();
     }
     catch (Exception ex)
     {
         Debug.WriteLine("ERROR DELETING ENTRY FROM SFAR TOC\n" + ex.Message);
     }
 }
Beispiel #2
0
        public void DeleteEntries(List <int> Index)
        {
            Index.Sort();
            Index.Reverse();
            FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read);
            int        f  = FindTOC();

            if (f == -1)
            {
                return;
            }
            MemoryStream m   = DecompressEntry(f, fs);
            string       toc = Encoding.UTF8.GetString(m.ToArray(), 0, (int)m.Length);

            fs.Close();
            for (int i = 0; i < Index.Count; i++)
            {
                FileEntryStruct e    = Files[Index[i]];
                string          file = e.FileName + "\r\n";
                toc = toc.Replace(file, "");
            }
            ReplaceEntry(Encoding.ASCII.GetBytes(toc), f);
            List <FileEntryStruct> l = new List <FileEntryStruct>();

            l.AddRange(Files);
            for (int i = 0; i < Index.Count; i++)
            {
                l.RemoveAt(Index[i]);
                Header.FileCount--;
            }
            Files = l.ToArray();
            ReBuild();
        }
Beispiel #3
0
        public void Serialize(SerializingFile con)
        {
            if (con.isLoading)
            {
                Header = new HeaderStruct();
            }
            Header.Serialize(con);
            con.Seek((int)Header.EntryOffset, SeekOrigin.Begin);
            for (int i = 0; i < Header.FileCount; i++)
            {
                //Debug.WriteLine($"Serialize sfar file {i} at 0x{con.Memory.Position:X8}");
                var feStruct = new FileEntryStruct();
                feStruct.Serialize(con, Header);
                Files.Add(feStruct);
                //Debug.WriteLine($"Data offset for {i}: 0x{Files[i].DataOffset:X8} (0x{Files[i].RealDataOffset:X8}), header at 0x{pos:X8}");
            }

            //var ordered = Files.OrderBy(x => x.DataOffset).ToList();
            //foreach (var f in ordered)
            //{
            //    Debug.WriteLine($"0x{f.DataOffset:X8} (0x{f.RealDataOffset:X8}), header at {f.MyOffset:X8}");
            //}
            //var firstfile = Files.MinBy(x => x.RealDataOffset);

            if (con.isLoading)
            {
                ReadFileNames();
            }
        }
Beispiel #4
0
 public void DeleteEntry(int Index)
 {
     try
     {
         FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read);
         Debug.WriteLine("Searching TOC...");
         int f = FindTOC();
         if (f == -1)
         {
             return;
         }
         Debug.WriteLine("Found TOC, deleting line...");
         MemoryStream m = DecompressEntry(f, fs);
         fs.Close();
         FileEntryStruct e    = Files[Index];
         string          toc  = Encoding.UTF8.GetString(m.ToArray(), 0, (int)m.Length);
         string          file = e.FileName + "\r\n";
         toc = toc.Replace(file, "");
         Debug.WriteLine("Replacing TOC...");
         ReplaceEntry(Encoding.ASCII.GetBytes(toc), f);
         Debug.WriteLine("Deleting Entry from Filelist...");
         List <FileEntryStruct> l = new List <FileEntryStruct>();
         l.AddRange(Files);
         l.RemoveAt(Index);
         Files.ReplaceAll(l);
         Header.FileCount--;
         Debug.WriteLine("Rebuilding...");
         ReBuild();
         Debug.WriteLine("Done.");
     }
     catch (Exception ex)
     {
         Debug.WriteLine("ERROR\n" + ex.Message);
     }
 }
Beispiel #5
0
        public MemoryStream DecompressEntry(int Index)
        {
            MemoryStream    result = new MemoryStream();
            FileEntryStruct e      = Files[Index];
            uint            count  = 0;

            byte[]     inputBlock;
            byte[]     outputBlock = new byte[Header.MaxBlockSize];
            long       left        = e.RealUncompressedSize;
            FileStream fs          = new FileStream(MyFileName, FileMode.Open, FileAccess.Read);

            fs.Seek(e.BlockOffsets[0], SeekOrigin.Begin);
            byte[] buff;
            if (e.BlockSizeIndex == 0xFFFFFFFF)
            {
                buff = new byte[e.RealUncompressedSize];
                fs.Read(buff, 0, buff.Length);
                result.Write(buff, 0, buff.Length);
            }
            else
            {
                while (left > 0)
                {
                    uint compressedBlockSize = (uint)e.BlockSizes[count];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = Header.MaxBlockSize;
                    }
                    if (compressedBlockSize == Header.MaxBlockSize || compressedBlockSize == left)
                    {
                        buff = new byte[compressedBlockSize];
                        fs.Read(buff, 0, buff.Length);
                        result.Write(buff, 0, buff.Length);
                        left -= compressedBlockSize;
                    }
                    else
                    {
                        var uncompressedBlockSize = (uint)Math.Min(left, Header.MaxBlockSize);
                        if (compressedBlockSize < 5)
                        {
                            throw new Exception("compressed block size smaller than 5");
                        }
                        inputBlock = new byte[compressedBlockSize];
                        fs.Read(inputBlock, 0, (int)compressedBlockSize);
                        uint actualUncompressedBlockSize = uncompressedBlockSize;
                        uint actualCompressedBlockSize   = compressedBlockSize;
                        outputBlock = SevenZipHelper.Decompress(inputBlock, (int)actualUncompressedBlockSize);
                        if (outputBlock.Length != actualUncompressedBlockSize)
                        {
                            throw new Exception("Decompression Error");
                        }
                        result.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                        left -= uncompressedBlockSize;
                    }
                    count++;
                }
            }
            fs.Close();
            return(result);
        }
        public void ReplaceEntry(byte[] FileIN, int Index)
        {
            string     DLCPath = MyFileName;
            FileStream fs      = new FileStream(DLCPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);

            fs.Seek(0, SeekOrigin.End);
            uint offset = (uint)fs.Length;

            fs.Write(FileIN, 0, FileIN.Length);
            FileEntryStruct e = Files[Index];

            e.BlockSizes       = new ushort[0];
            e.BlockOffsets     = new long[1];
            e.BlockOffsets[0]  = offset;
            e.BlockSizeIndex   = 0xFFFFFFFF;
            e.DataOffset       = offset;
            e.UncompressedSize = (uint)FileIN.Length;
            fs.Seek(e.MyOffset, 0);
            fs.Write(e.Hash, 0, 16);
            fs.Write(BitConverter.GetBytes(0xFFFFFFFF), 0, 4);
            fs.Write(BitConverter.GetBytes(FileIN.Length), 0, 4);
            fs.WriteByte(e.UncompressedSizeAdder);
            fs.Write(BitConverter.GetBytes(offset), 0, 4);
            fs.WriteByte(0);
            Files[Index] = e;
            fs.Close();
        }
        public List <byte[]> GetBlocks(int Index)
        {
            List <byte[]>   res   = new List <byte[]>();
            FileEntryStruct e     = Files[Index];
            uint            count = 0;

            byte[]     inputBlock;
            byte[]     outputBlock = new byte[Header.MaxBlockSize];
            long       left        = e.RealUncompressedSize;
            FileStream fs          = new FileStream(MyFileName, FileMode.Open, FileAccess.Read);

            fs.Seek(e.BlockOffsets[0], SeekOrigin.Begin);
            byte[] buff;
            if (e.BlockSizeIndex == 0xFFFFFFFF)
            {
                buff = new byte[e.RealUncompressedSize];
                fs.Read(buff, 0, buff.Length);
                res.Add(buff);
                fs.Close();
                return(res);
            }
            else
            {
                while (left > 0)
                {
                    uint compressedBlockSize = (uint)e.BlockSizes[count];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = Header.MaxBlockSize;
                    }
                    if (compressedBlockSize == Header.MaxBlockSize || compressedBlockSize == left)
                    {
                        buff = new byte[compressedBlockSize];
                        fs.Read(buff, 0, buff.Length);
                        res.Add(buff);
                        left -= compressedBlockSize;
                    }
                    else
                    {
                        var uncompressedBlockSize = (uint)Math.Min(left, Header.MaxBlockSize);
                        if (compressedBlockSize < 5)
                        {
                            DebugLog.PrintLn("DLCPACKAGE::GETBLOCKS ERROR: compressed block size smaller than 5");
                            break;
                        }
                        inputBlock = new byte[compressedBlockSize];
                        fs.Read(inputBlock, 0, (int)compressedBlockSize);
                        res.Add(inputBlock);
                        left -= uncompressedBlockSize;
                    }
                    count++;
                }
            }
            fs.Close();
            return(res);
        }
Beispiel #8
0
 public void DeleteEntry(List <int> Index)
 {
     try
     {
         Index.Sort();
         Index.Reverse();
         FileStream fs = new FileStream(MyFileName, FileMode.Open, FileAccess.Read);
         //DebugLog.PrintLn("Searching TOC...");
         int f = FindTOC();
         if (f == -1)
         {
             return;
         }
         //DebugLog.PrintLn("Found TOC, deleting lines...");
         MemoryStream m   = DecompressEntry(f, fs);
         string       toc = Encoding.UTF8.GetString(m.ToArray(), 0, (int)m.Length);
         fs.Close();
         for (int i = 0; i < Index.Count; i++)
         {
             FileEntryStruct e    = Files[Index[i]];
             string          file = e.FileName + "\r\n";
             toc = toc.Replace(file, "");
         }
         //DebugLog.PrintLn("Replacing TOC...");
         ReplaceEntry(Encoding.ASCII.GetBytes(toc), f);
         //DebugLog.PrintLn("Deleting Entry from Filelist...");
         List <FileEntryStruct> l = new List <FileEntryStruct>();
         l.AddRange(Files);
         for (int i = 0; i < Index.Count; i++)
         {
             l.RemoveAt(Index[i]);
             Header.FileCount--;
         }
         Files = l.ToArray();
         //DebugLog.PrintLn("Rebuilding...");
         ReBuild();
         //DebugLog.PrintLn("Done.");
     }
     catch (Exception ex)
     {
         //DebugLog.PrintLn("ERROR\n" + ex.Message);
     }
 }
Beispiel #9
0
        /// <summary>
        /// Appends a file to the index and accompanying data file.
        /// </summary>
        /// <param name="directory">The directory that will be stored in the index.</param>
        /// <param name="fileName">The filename that will be stored in the index.</param>
        /// <param name="bytesToWrite">Byte array of the file to add.</param>
        /// <param name="fileTime">File time to set to the file.</param>
        /// <returns>Returns true if the operation was successful.</returns>
        public override bool AddFile(String directory, String fileName, byte[] bytesToWrite, DateTime?fileTime = null)
        {
            if (bytesToWrite == null || bytesToWrite.Length == 0)
            {
                throw new ArgumentNullException("bytesToWrite", "Bytes to write cannot be empty!");
            }

            bool doCompress = NoCompressionExt.All(extentsion => !fileName.EndsWith(extentsion));

            if (fileTime == null)
            {
                fileTime = DateTime.Now;
            }

            FileEntryStruct fileStruct = new FileEntryStruct
            {
                StartToken         = Token.Info,
                SizeUncompressed   = bytesToWrite.Length,
                SizeCompressed     = doCompress ? 1 : 0,
                FileTime           = fileTime.Value.ToFileTime(),
                NameHash           = Crypt.GetStringSHA1UInt32(fileName),
                DirectoryHash      = Crypt.GetStringSHA1UInt32(directory),
                First4BytesOfFile  = FileTools.ByteArrayToInt32(bytesToWrite, 0),
                Second4BytesOfFile = FileTools.ByteArrayToInt32(bytesToWrite, 4),
                EndToken           = Token.Info,
            };

            PackFileEntry fileEntry = new FileEntry(fileStruct);

            fileEntry.Directory = directory;
            fileEntry.Name      = fileName;

            Files.Add(fileEntry);

            _AddFileToDat(bytesToWrite, fileEntry);

            // todo: create new applicable file entry object as well?
            // todo: remove existing file bytes if applicable...

            return(true);
        }
Beispiel #10
0
        public void ReplaceEntry(byte[] newData, int entryIndex)
        {
            FileStream      fs = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            FileEntryStruct e  = Files[entryIndex];

            if (e.BlockSizeTableIndex == 0xFFFFFFFF && e.RealUncompressedSize == newData.Length)
            {
                //overwrite existing data, but only if already uncompressed!
                fs.Seek(e.RealDataOffset, SeekOrigin.Begin);
            }
            else
            {
                // It won't fit. Append it to the end instead
                fs.Seek(0, SeekOrigin.End);
            }

            uint offset = (uint)fs.Position;

            //append data
            fs.Write(newData, 0, newData.Length);

            //uncompressed entry
            e.BlockSizes          = new ushort[0];
            e.BlockOffsets        = new long[1];
            e.BlockOffsets[0]     = offset;
            e.BlockSizeTableIndex = 0xFFFFFFFF;
            e.DataOffset          = offset;
            e.UncompressedSize    = (uint)newData.Length;

            fs.Seek(e.MyOffset, 0);
            fs.Write(e.Hash, 0, 16);
            fs.Write(BitConverter.GetBytes(0xFFFFFFFF), 0, 4);
            fs.Write(BitConverter.GetBytes(newData.Length), 0, 4);
            fs.WriteByte(e.UncompressedSizeAdder);
            fs.Write(BitConverter.GetBytes(offset), 0, 4);
            fs.WriteByte(0);
            Files[entryIndex] = e;
            fs.Close();
        }
Beispiel #11
0
        /// <summary>
        /// Appends a file to the index and accompanying data file.
        /// </summary>
        /// <param name="directory">The directory that will be stored in the index.</param>
        /// <param name="fileName">The filename that will be stored in the index.</param>
        /// <param name="bytesToWrite">Byte array of the file to add.</param>
        /// <param name="fileTime">File time to set to the file.</param>
        /// <returns>Returns true if the operation was successful.</returns>
        public override bool AddFile(String directory, String fileName, byte[] bytesToWrite, DateTime ?fileTime = null)
        {
            if (bytesToWrite == null || bytesToWrite.Length == 0) throw new ArgumentNullException("bytesToWrite", "Bytes to write cannot be empty!");

            bool doCompress = NoCompressionExt.All(extentsion => !fileName.EndsWith(extentsion));
            if (fileTime == null) fileTime = DateTime.Now;

            FileEntryStruct fileStruct = new FileEntryStruct
            {
                StartToken = Token.Info,
                SizeUncompressed = bytesToWrite.Length,
                SizeCompressed = doCompress ? 1 : 0,
                FileTime = fileTime.Value.ToFileTime(),
                NameHash = Crypt.GetStringSHA1UInt32(fileName),
                DirectoryHash = Crypt.GetStringSHA1UInt32(directory),
                First4BytesOfFile = FileTools.ByteArrayToInt32(bytesToWrite, 0),
                Second4BytesOfFile = FileTools.ByteArrayToInt32(bytesToWrite, 4),
                EndToken = Token.Info,
            };

            PackFileEntry fileEntry = new FileEntry(fileStruct);
            fileEntry.Directory = directory;
            fileEntry.Name = fileName;

            Files.Add(fileEntry);

            _AddFileToDat(bytesToWrite, fileEntry);

            // todo: create new applicable file entry object as well?
            // todo: remove existing file bytes if applicable...

            return true;
        }
Beispiel #12
0
 public void AddFileQuick(string filein, string path)
 {
     BitConverter.IsLittleEndian = true;
     string DLCPath = MyFileName;
     FileStream fs = new FileStream(DLCPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
     byte[] FileIN = File.ReadAllBytes(filein);
     //Create Entry
     List<FileEntryStruct> tmp = new List<FileEntryStruct>(Files);
     FileEntryStruct e = new FileEntryStruct();
     e.FileName = path;
     e.BlockOffsets = new long[0];
     e.Hash = ComputeHash(path);
     e.BlockSizeIndex = 0xFFFFFFFF;
     e.UncompressedSize = (uint)FileIN.Length;
     e.UncompressedSizeAdder = 0;
     tmp.Add(e);
     e = new FileEntryStruct();
     Files = tmp.ToArray();
     //
     //Find TOC
     DebugOutput.PrintLn("Searching TOC...");
     int f = FindTOC();
     if (f == -1)
         return;
     DebugOutput.PrintLn("Found TOC, adding line...");
     MemoryStream m = DecompressEntry(f, fs);
     //
     //Update TOC
     WriteString(m, path);
     m.WriteByte(0xD);
     m.WriteByte(0xA);
     //
     //Append new FileTable
     int count = (int)Header.FileCount +1;
     long oldsize = fs.Length;
     long offset  = oldsize;
     DebugOutput.PrintLn("File End Offset : 0x" + offset.ToString("X10"));
     fs.Seek(oldsize, 0);
     Header.EntryOffset = (uint)offset;
     for (int i = 0; i < count; i++)
     {
         e = Files[i];
         fs.Write(e.Hash, 0, 16);
         fs.Write(BitConverter.GetBytes(e.BlockSizeIndex), 0, 4);
         fs.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
         fs.WriteByte(e.UncompressedSizeAdder);
         fs.Write(BitConverter.GetBytes(e.DataOffset), 0, 4);
         fs.WriteByte(e.DataOffsetAdder);
     }
     offset += count * 0x1E;
     DebugOutput.PrintLn("Table End Offset : 0x" + offset.ToString("X10"));
     Header.BlockTableOffset = (uint)offset;
     //
     //Append blocktable
     for (int i = 0; i < count; i++)
     {
         e = Files[i];
         if (e.BlockSizeIndex != 0xFFFFFFFF && i != f)
             foreach(ushort u in e.BlockSizes)
                 fs.Write(BitConverter.GetBytes(u), 0, 2);
     }
     offset = fs.Length;
     DebugOutput.PrintLn("Block Table End Offset : 0x" + offset.ToString("X10"));
     long dataoffset = offset;
     fs.Write(FileIN, 0, FileIN.Length);
     offset += FileIN.Length;
     DebugOutput.PrintLn("New Data End Offset : 0x" + offset.ToString("X10"));
     //
     //Append TOC
     long tocoffset = offset;
     fs.Write(m.ToArray(), 0, (int)m.Length);
     offset = fs.Length;
     DebugOutput.PrintLn("New TOC Data End Offset : 0x" + offset.ToString("X10"));
     //update filetable
     fs.Seek(oldsize, 0);
     uint blocksizeindex = 0;
     for (int i = 0; i < count; i++)
     {
         e = Files[i];
         fs.Write(e.Hash, 0, 16);
         if (e.BlockSizeIndex == 0xFFFFFFFF || i==f)
             fs.Write(BitConverter.GetBytes((int)-1), 0, 4);
         else
         {
             fs.Write(BitConverter.GetBytes(blocksizeindex), 0, 4);
             e.BlockSizeIndex = (uint)blocksizeindex;
             blocksizeindex += (uint)e.BlockSizes.Length;
             Files[i] = e;
         }
         if (i == f)
         {
             fs.Write(BitConverter.GetBytes(m.Length), 0, 4);
             fs.WriteByte(0);
             fs.Write(BitConverter.GetBytes(tocoffset), 0, 4);
             byte b = (byte)((tocoffset & 0xFF00000000) >> 32);
             fs.WriteByte(b);
         }
         else if (i == count - 1)
         {
             fs.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
             fs.WriteByte(0);
             fs.Write(BitConverter.GetBytes(dataoffset), 0, 4);
             byte b = (byte)((dataoffset & 0xFF00000000) >> 32);
             fs.WriteByte(b);
         }
         else
         {
             fs.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
             fs.WriteByte(e.UncompressedSizeAdder);
             fs.Write(BitConverter.GetBytes(e.DataOffset), 0, 4);
             fs.WriteByte(e.DataOffsetAdder);
         }
     }
     //Update Header
     fs.Seek(0xC, 0);
     fs.Write(BitConverter.GetBytes(Header.EntryOffset), 0, 4);
     fs.Write(BitConverter.GetBytes(count), 0, 4);
     fs.Write(BitConverter.GetBytes(Header.BlockTableOffset), 0, 4);
     //
     fs.Close();
 }
Beispiel #13
0
        public void AddFileQuick(string filein, string path)
        {
            string     DLCPath = FileName;
            FileStream fs      = new FileStream(DLCPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);

            byte[] FileIN = File.ReadAllBytes(filein);
            //Create Entry
            List <FileEntryStruct> tmp = new List <FileEntryStruct>(Files);
            FileEntryStruct        e   = new FileEntryStruct();

            e.FileName              = path;
            e.BlockOffsets          = new long[0];
            e.Hash                  = ComputeHash(path);
            e.BlockSizeTableIndex   = 0xFFFFFFFF;
            e.UncompressedSize      = (uint)FileIN.Length;
            e.UncompressedSizeAdder = 0;
            tmp.Add(e);
            e = new FileEntryStruct();
            Files.ReplaceAll(tmp);
            //
            //Find TOC
            Debug.WriteLine("Searching TOC...");
            int f = FindTOC();

            if (f == -1)
            {
                return;
            }
            Debug.WriteLine("Found TOC, adding line...");
            MemoryStream m = DecompressEntry(f, fs);

            //
            //Update TOC
            WriteString(m, path);
            m.WriteByte(0xD);
            m.WriteByte(0xA);
            //
            //Append new FileTable
            int  count   = (int)Header.FileCount + 1;
            long oldsize = fs.Length;
            long offset  = oldsize;

            Debug.WriteLine("File End Offset : 0x" + offset.ToString("X10"));
            fs.Seek(oldsize, 0);
            Header.EntryOffset = (uint)offset;
            for (int i = 0; i < count; i++)
            {
                e = Files[i];
                fs.Write(e.Hash, 0, 16);
                fs.Write(BitConverter.GetBytes(e.BlockSizeTableIndex), 0, 4);
                fs.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
                fs.WriteByte(e.UncompressedSizeAdder);
                fs.Write(BitConverter.GetBytes(e.DataOffset), 0, 4);
                fs.WriteByte(e.DataOffsetAdder);
            }
            offset += count * 0x1E;
            Debug.WriteLine("Table End Offset : 0x" + offset.ToString("X10"));
            Header.BlockTableOffset = (uint)offset;
            //
            //Append blocktable
            for (int i = 0; i < count; i++)
            {
                e = Files[i];
                if (e.BlockSizeTableIndex != 0xFFFFFFFF && i != f)
                {
                    foreach (ushort u in e.BlockSizes)
                    {
                        fs.Write(BitConverter.GetBytes(u), 0, 2);
                    }
                }
            }
            offset = fs.Length;
            Debug.WriteLine("Block Table End Offset : 0x" + offset.ToString("X10"));
            long dataoffset = offset;

            fs.Write(FileIN, 0, FileIN.Length);
            offset += FileIN.Length;
            Debug.WriteLine("New Data End Offset : 0x" + offset.ToString("X10"));
            //
            //Append TOC
            long tocoffset = offset;

            fs.Write(m.ToArray(), 0, (int)m.Length);
            offset = fs.Length;
            Debug.WriteLine("New TOC Data End Offset : 0x" + offset.ToString("X10"));
            //update filetable
            fs.Seek(oldsize, 0);
            uint blocksizeindex = 0;

            for (int i = 0; i < count; i++)
            {
                e = Files[i];
                fs.Write(e.Hash, 0, 16);
                if (e.BlockSizeTableIndex == 0xFFFFFFFF || i == f)
                {
                    fs.Write(BitConverter.GetBytes(-1), 0, 4);
                }
                else
                {
                    fs.Write(BitConverter.GetBytes(blocksizeindex), 0, 4);
                    e.BlockSizeTableIndex = blocksizeindex;
                    blocksizeindex       += (uint)e.BlockSizes.Length;
                    Files[i] = e;
                }
                if (i == f)
                {
                    fs.Write(BitConverter.GetBytes(m.Length), 0, 4);
                    fs.WriteByte(0);
                    fs.Write(BitConverter.GetBytes(tocoffset), 0, 4);
                    byte b = (byte)((tocoffset & 0xFF00000000) >> 32);
                    fs.WriteByte(b);
                }
                else if (i == count - 1)
                {
                    fs.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
                    fs.WriteByte(0);
                    fs.Write(BitConverter.GetBytes(dataoffset), 0, 4);
                    byte b = (byte)((dataoffset & 0xFF00000000) >> 32);
                    fs.WriteByte(b);
                }
                else
                {
                    fs.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
                    fs.WriteByte(e.UncompressedSizeAdder);
                    fs.Write(BitConverter.GetBytes(e.DataOffset), 0, 4);
                    fs.WriteByte(e.DataOffsetAdder);
                }
            }
            //Update Header
            fs.Seek(0xC, 0);
            fs.Write(BitConverter.GetBytes(Header.EntryOffset), 0, 4);
            fs.Write(BitConverter.GetBytes(count), 0, 4);
            fs.Write(BitConverter.GetBytes(Header.BlockTableOffset), 0, 4);
            //
            fs.Close();
        }
Beispiel #14
0
        public MemoryStream DecompressEntry(FileEntryStruct e)
        {
            //Debug.WriteLine("Decompressing " + e.FileName);
            MemoryStream result = new MemoryStream();
            uint         count  = 0;

            byte[]     inputBlock;
            long       left = e.RealUncompressedSize;
            FileStream fs   = new FileStream(FileName, FileMode.Open, FileAccess.Read);

            fs.Seek(e.BlockOffsets[0], SeekOrigin.Begin);
            byte[] buff;
            if (e.BlockSizeTableIndex == 0xFFFFFFFF)
            {
                buff = new byte[e.RealUncompressedSize];
                fs.Read(buff, 0, buff.Length);
                result.Write(buff, 0, buff.Length);
            }
            else
            {
                while (left > 0)
                {
                    uint compressedBlockSize = e.BlockSizes[count];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = Header.MaxBlockSize;
                    }
                    if (compressedBlockSize == Header.MaxBlockSize || compressedBlockSize == left)
                    {
                        //uncompressed?
                        buff = new byte[compressedBlockSize];
                        fs.Read(buff, 0, buff.Length);

                        result.Write(buff, 0, buff.Length);
                        left -= compressedBlockSize;
                    }
                    else
                    {
                        var uncompressedBlockSize = (uint)Math.Min(left, Header.MaxBlockSize);
                        if (compressedBlockSize < 5)
                        {
                            throw new Exception("compressed block size smaller than 5");
                        }

                        inputBlock = new byte[compressedBlockSize];
                        //Debug.WriteLine($"Decompressing at 0x{fs.Position:X8}");
                        fs.Read(inputBlock, 0, (int)compressedBlockSize);
                        uint actualUncompressedBlockSize = uncompressedBlockSize;
                        if (Header.CompressionScheme == "amzl" /* PC */ || Header.CompressionScheme == "lzma" /* PS3 (it doesn't appear to actually be LZMA!), WiiU */)
                        {
                            //if (Header.CompressionScheme == "lzma")
                            //{
                            //PS3 - This doesn't work. I'm not sure what kind of LZMA this uses but it has seemingly no header
                            //var attachedHeader = new byte[inputBlock.Length + 5];
                            //attachedHeader[0] = 0x5D;
                            ////attachedHeader[1] = (byte) (Header.Version >> 24);
                            ////attachedHeader[2] = (byte)(Header.Version >> 16);
                            ////attachedHeader[3] = (byte)(Header.Version >> 8);
                            ////attachedHeader[4] = (byte) Header.Version;
                            //attachedHeader[1] = (byte)Header.Version;
                            //attachedHeader[2] = (byte)(Header.Version >> 8);
                            //attachedHeader[3] = (byte)(Header.Version >> 16);
                            //attachedHeader[4] = (byte)(Header.Version >> 24);
                            //Buffer.BlockCopy(inputBlock,0,attachedHeader,5, inputBlock.Length);
                            //inputBlock = attachedHeader;
                            //}

                            var outputBlock = LZMA.Decompress(inputBlock, actualUncompressedBlockSize);
                            if (outputBlock.Length != actualUncompressedBlockSize)
                            {
                                throw new Exception("SFAR LZMA Decompression Error");
                            }
                            result.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                            left -= uncompressedBlockSize;
                            //continue;
                        }

                        if (Header.CompressionScheme == "lzx") //Xbox
                        {
                            var outputBlock  = new byte[actualUncompressedBlockSize];
                            var decompResult = LZX.Decompress(inputBlock, (uint)inputBlock.Length, outputBlock);
                            if (decompResult != 0)
                            {
                                throw new Exception("SFAR LZX Decompression Error");
                            }
                            result.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                            left -= uncompressedBlockSize;
                        }
                    }
                    count++;
                }
            }
            fs.Close();
            result.Position = 0;
            return(result);
        }
Beispiel #15
0
        public void ReBuild()
        {
            string     path = Path.Combine(Path.GetDirectoryName(FileName), Path.GetFileNameWithoutExtension(FileName) + ".tmp");
            FileStream fs   = new FileStream(path, FileMode.Create, FileAccess.Write);

            Debug.WriteLine("Creating Header Dummy...");
            for (int i = 0; i < 8; i++)
            {
                fs.Write(BitConverter.GetBytes(0), 0, 4);
            }
            Header.EntryOffset = 0x20;
            Debug.WriteLine("Creating File Table...");
            for (int i = 0; i < Header.FileCount; i++)
            {
                FileEntryStruct e = Files[i];
                fs.Write(e.Hash, 0, 16);
                fs.Write(BitConverter.GetBytes(e.BlockSizeTableIndex), 0, 4);
                fs.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
                fs.WriteByte(e.UncompressedSizeAdder);
                fs.Write(BitConverter.GetBytes(e.DataOffset), 0, 4);
                fs.WriteByte(e.DataOffsetAdder);
            }
            Header.BlockTableOffset = (uint)fs.Position;
            Debug.WriteLine("Creating Block Table...");
            for (int i = 0; i < Header.FileCount; i++)
            {
                if (Files[i].BlockSizeTableIndex != 0xFFFFFFFF)
                {
                    foreach (ushort u in Files[i].BlockSizes)
                    {
                        fs.Write(BitConverter.GetBytes(u), 0, 2);
                    }
                }
            }
            Header.DataOffset = (uint)fs.Position;
            Debug.WriteLine("Appending Files...");
            uint pos = (uint)fs.Position;

            for (int i = 0; i < Header.FileCount; i++)
            {
                List <byte[]>   blocks = GetBlocks(i);
                FileEntryStruct e      = Files[i];
                Debug.WriteLine("Rebuilding \"" + e.FileName + "\" (" + (i + 1) + "/" + Header.FileCount + ") " + BytesToString(e.UncompressedSize) + " ...");
                e.DataOffset      = pos;
                e.DataOffsetAdder = 0;
                for (int j = 0; j < blocks.Count; j++)
                {
                    MemoryStream m = new MemoryStream(blocks[j]);
                    fs.Write(m.ToArray(), 0, (int)m.Length);
                    pos += (uint)m.Length;
                }
                Files[i] = e;
            }
            Debug.WriteLine("Updating FileTable...");
            fs.Seek(0x20, 0);
            pos = (uint)fs.Position;
            uint blocksizeindex = 0;

            for (int i = 0; i < Header.FileCount; i++)
            {
                FileEntryStruct e = Files[i];
                fs.Write(e.Hash, 0, 16);
                if (e.BlockSizeTableIndex != 0xFFFFFFFF)
                {
                    fs.Write(BitConverter.GetBytes(blocksizeindex), 0, 4);
                    e.BlockSizeTableIndex = blocksizeindex;
                    blocksizeindex       += (uint)e.BlockSizes.Length;
                }
                else
                {
                    fs.Write(BitConverter.GetBytes(0xFFFFFFFF), 0, 4);
                }
                fs.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
                fs.WriteByte(e.UncompressedSizeAdder);
                fs.Write(BitConverter.GetBytes(e.DataOffset), 0, 4);
                fs.WriteByte(e.DataOffsetAdder);
                e.MyOffset = pos;
                Files[i]   = e;
                pos       += 0x1E;
            }
            fs.Seek(0, 0);
            Debug.WriteLine("Rebuilding Header...");
            //magic
            fs.Write(BitConverter.GetBytes(0x53464152), 0, 4);
            fs.Write(BitConverter.GetBytes(Header.Version), 0, 4);
            fs.Write(BitConverter.GetBytes(Header.DataOffset), 0, 4);
            fs.Write(BitConverter.GetBytes(Header.EntryOffset), 0, 4);
            fs.Write(BitConverter.GetBytes(Header.FileCount), 0, 4);
            fs.Write(BitConverter.GetBytes(Header.BlockTableOffset), 0, 4);
            fs.Write(BitConverter.GetBytes(Header.MaxBlockSize), 0, 4);
            foreach (char c in Header.CompressionScheme)
            {
                fs.WriteByte((byte)c);
            }
            fs.Close();
            File.Delete(FileName);
            File.Move(path, FileName);
        }
Beispiel #16
0
        public MemoryStream DecompressEntry(int index, FileStream fs)
        {
            FileEntryStruct e = Files[index];
            //MemoryStream result = new MemoryStream((int)e.RealUncompressedSize);
            MemoryStream result = MixinHandler.MixinMemoryStreamManager.GetStream();
            uint         count  = 0;

            byte[] inputBlock;
            byte[] outputBlock = new byte[Header.MaxBlockSize];
            long   left        = e.RealUncompressedSize;

            fs.Seek(e.BlockOffsets[0], SeekOrigin.Begin);
            byte[] buff;
            if (e.BlockSizeIndex == 0xFFFFFFFF)
            {
                buff = new byte[e.RealUncompressedSize];
                fs.Read(buff, 0, buff.Length);
                result.Write(buff, 0, buff.Length);
            }
            else
            {
                //Compressed
                while (left > 0)
                {
                    uint compressedBlockSize = e.BlockSizes[count];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = Header.MaxBlockSize;
                    }
                    if (compressedBlockSize == Header.MaxBlockSize || compressedBlockSize == left)
                    {
                        buff = new byte[compressedBlockSize];
                        fs.Read(buff, 0, buff.Length);
                        result.Write(buff, 0, buff.Length);
                        left -= compressedBlockSize;
                    }
                    else
                    {
                        var uncompressedBlockSize = (uint)Math.Min(left, Header.MaxBlockSize);
                        if (compressedBlockSize < 5)
                        {
                            throw new Exception("compressed block size smaller than 5");
                        }
                        inputBlock = new byte[compressedBlockSize];
                        fs.Read(inputBlock, 0, (int)compressedBlockSize);
                        uint actualUncompressedBlockSize = uncompressedBlockSize;
                        uint actualCompressedBlockSize   = compressedBlockSize;

                        outputBlock = SevenZipHelper.LZMA.Decompress(inputBlock, actualUncompressedBlockSize);
                        if (outputBlock.Length != actualUncompressedBlockSize)
                        {
                            throw new Exception("Decompression Error");
                        }
                        result.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                        left -= uncompressedBlockSize;
                    }
                    count++;
                }
            }
            return(result);
        }
 public FileEntry(FileEntryStruct fileEntryStruct)
 {
     _fileEntryStruct = fileEntryStruct;
 }
        public MemoryStream DecompressEntry(int Index, FileStream fs)
        {
            MemoryStream    result = new MemoryStream();
            FileEntryStruct e      = Files[Index];
            uint            count  = 0;

            byte[] inputBlock;
            byte[] outputBlock = new byte[Header.MaxBlockSize];
            long   left        = e.RealUncompressedSize;

            fs.Seek(e.BlockOffsets[0], SeekOrigin.Begin);
            byte[] buff;
            if (e.BlockSizeIndex == 0xFFFFFFFF)
            {
                buff = new byte[e.RealUncompressedSize];
                fs.Read(buff, 0, buff.Length);
                result.Write(buff, 0, buff.Length);
            }
            else
            {
                while (left > 0)
                {
                    uint compressedBlockSize = (uint)e.BlockSizes[count];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = Header.MaxBlockSize;
                    }
                    if (compressedBlockSize == Header.MaxBlockSize || compressedBlockSize == left)
                    {
                        buff = new byte[compressedBlockSize];
                        fs.Read(buff, 0, buff.Length);
                        result.Write(buff, 0, buff.Length);
                        left -= compressedBlockSize;
                    }
                    else
                    {
                        var uncompressedBlockSize = (uint)Math.Min(left, Header.MaxBlockSize);
                        if (compressedBlockSize < 5)
                        {
                            DebugLog.PrintLn("DLCPACKAGE::DECOMPRESSENTRY ERROR:compressed block size smaller than 5");
                            break;
                        }
                        inputBlock = new byte[compressedBlockSize];
                        fs.Read(inputBlock, 0, (int)compressedBlockSize);
                        uint actualUncompressedBlockSize = uncompressedBlockSize;
                        uint actualCompressedBlockSize   = compressedBlockSize;
                        outputBlock = SevenZipHelper.Decompress(inputBlock, (int)actualUncompressedBlockSize);
                        if (outputBlock.Length != actualUncompressedBlockSize)
                        {
                            DebugLog.PrintLn("DLCPACKAGE::DECOMPRESSENTRY ERROR:Decompression Error");
                            break;
                        }
                        result.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                        left -= uncompressedBlockSize;
                    }
                    count++;
                }
            }
            fs.Close();
            return(result);
        }
Beispiel #19
0
        public void AddFileQuick(string onDiskNewFile, string inArchivePath)
        {
            byte[] newFileBytes;
            if (Path.GetExtension(onDiskNewFile).ToLower() == @".pcc" && FileName.EndsWith(@"Patch_001.sfar", StringComparison.InvariantCultureIgnoreCase))
            {
                //Use the decompressed bytes - SFARs can't store compressed packages apparently!
                var package = MEPackageHandler.OpenMEPackage(onDiskNewFile);
                newFileBytes = package.saveToStream().ToArray();
            }
            else
            {
                newFileBytes = File.ReadAllBytes(onDiskNewFile);
            }

            FileStream sfarStream = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            //Create Entry
            List <FileEntryStruct> tmp = new List <FileEntryStruct>(Files);
            FileEntryStruct        e   = new FileEntryStruct();

            e.FileName              = inArchivePath;
            e.BlockOffsets          = new long[0];
            e.Hash                  = ComputeHash(inArchivePath);
            e.BlockSizeIndex        = 0xFFFFFFFF;
            e.UncompressedSize      = (uint)newFileBytes.Length;
            e.UncompressedSizeAdder = 0;
            tmp.Add(e);
            Files = tmp.ToArray();


            //
            //Find TOC
            int f = findTOCIndex();

            if (f == -1)
            {
                return;
            }
            MemoryStream tocMemory = DecompressEntry(f, sfarStream);

            //
            //No idea what most of the rest of this stuff is so i probably shouldn't change it
            //Update TOC
            tocMemory.WriteStringASCII(inArchivePath);
            tocMemory.WriteByte(0xD);
            tocMemory.WriteByte(0xA);


            //
            //Append new FileTable
            int  count   = (int)Header.FileCount + 1;
            long oldsize = sfarStream.Length;
            long offset  = oldsize;

            //Debug.WriteLine("File End Offset : 0x" + offset.ToString("X10"));
            sfarStream.Seek(oldsize, 0);
            Header.EntryOffset = (uint)offset;
            for (int i = 0; i < count; i++)
            {
                e = Files[i];
                sfarStream.Write(e.Hash, 0, 16);
                sfarStream.Write(BitConverter.GetBytes(e.BlockSizeIndex), 0, 4);
                sfarStream.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
                sfarStream.WriteByte(e.UncompressedSizeAdder);
                sfarStream.Write(BitConverter.GetBytes(e.DataOffset), 0, 4);
                sfarStream.WriteByte(e.DataOffsetAdder);
            }
            offset += count * 0x1E;
            //Debug.WriteLine("Table End Offset : 0x" + offset.ToString("X10"));
            Header.BlockTableOffset = (uint)offset;
            //
            //Append blocktable
            for (int i = 0; i < count; i++)
            {
                e = Files[i];
                if (e.BlockSizeIndex != 0xFFFFFFFF && i != f)
                {
                    foreach (ushort u in e.BlockSizes)
                    {
                        sfarStream.Write(BitConverter.GetBytes(u), 0, 2);
                    }
                }
            }
            offset = sfarStream.Length;
            //Debug.WriteLine("Block Table End Offset : 0x" + offset.ToString("X10"));
            long dataoffset = offset;

            sfarStream.Write(newFileBytes, 0, newFileBytes.Length);
            offset += newFileBytes.Length;
            //Debug.WriteLine("New Data End Offset : 0x" + offset.ToString("X10"));
            //
            //Append TOC
            long tocoffset = offset;

            sfarStream.Write(tocMemory.ToArray(), 0, (int)tocMemory.Length);
            offset = sfarStream.Length;
            //Debug.WriteLine("New TOC Data End Offset : 0x" + offset.ToString("X10"));
            //update filetable
            sfarStream.Seek(oldsize, 0);
            uint blocksizeindex = 0;

            for (int i = 0; i < count; i++)
            {
                e = Files[i];
                sfarStream.Write(e.Hash, 0, 16);
                if (e.BlockSizeIndex == 0xFFFFFFFF || i == f)
                {
                    sfarStream.Write(BitConverter.GetBytes(-1), 0, 4);
                }
                else
                {
                    sfarStream.Write(BitConverter.GetBytes(blocksizeindex), 0, 4);
                    e.BlockSizeIndex = blocksizeindex;
                    blocksizeindex  += (uint)e.BlockSizes.Length;
                    Files[i]         = e;
                }
                if (i == f)
                {
                    sfarStream.Write(BitConverter.GetBytes(tocMemory.Length), 0, 4);
                    sfarStream.WriteByte(0);
                    sfarStream.Write(BitConverter.GetBytes(tocoffset), 0, 4);
                    byte b = (byte)((tocoffset & 0xFF00000000) >> 32);
                    sfarStream.WriteByte(b);
                }
                else if (i == count - 1)
                {
                    sfarStream.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
                    sfarStream.WriteByte(0);
                    sfarStream.Write(BitConverter.GetBytes(dataoffset), 0, 4);
                    byte b = (byte)((dataoffset & 0xFF00000000) >> 32);
                    sfarStream.WriteByte(b);
                }
                else
                {
                    sfarStream.Write(BitConverter.GetBytes(e.UncompressedSize), 0, 4);
                    sfarStream.WriteByte(e.UncompressedSizeAdder);
                    sfarStream.Write(BitConverter.GetBytes(e.DataOffset), 0, 4);
                    sfarStream.WriteByte(e.DataOffsetAdder);
                }
            }
            //Update Header
            sfarStream.Seek(0xC, 0);
            sfarStream.Write(BitConverter.GetBytes(Header.EntryOffset), 0, 4);
            sfarStream.Write(BitConverter.GetBytes(count), 0, 4);
            sfarStream.Write(BitConverter.GetBytes(Header.BlockTableOffset), 0, 4);
            //
            sfarStream.Close();
        }
Beispiel #20
0
 public FileEntry(FileEntryStruct fileEntryStruct)
 {
     _fileEntryStruct = fileEntryStruct;
 }