示例#1
0
        LPKWriter(uint file_count)
            : base()
        {
            m_Header = new LPKHeader(HashCount, file_count);
            m_HashEntries = new LPKHashEntry[m_Header.Hashcount];
            for (int i = 0; i < m_Header.Hashcount; i++)
                m_HashEntries[i] = null;

            m_BlockEntries = new LPKBlockEntry[m_Header.BlockCount];
            for (int i = 0; i < m_Header.BlockCount; i++)
                m_BlockEntries[i] = null;
        }
示例#2
0
        public LPK(string path)
        {
            if (path == null || path == string.Empty)
                Logging.Fatal("Path to packed file system cannot be empty.");
            if (!System.IO.File.Exists(path))
                Logging.Fatal("Path to packed file system must exist");

            m_Reader = InterXLib.Serialize.OpenReader(path);
            m_Header = new LPKHeader(m_Reader);

            m_HashEntries = new LPKHashEntry[m_Header.Hashcount];
            if (m_Header.HashTableSizeCompressed != 0)
            {
                byte[] hash_table_compressed = m_Reader.ReadBytes((int)m_Header.HashTableSizeCompressed);
                byte[] hash_table = Compression.LZF.Decompress(hash_table_compressed, (int)m_Header.Hashcount * LPKHashEntry.SizeInBytes);
                using (MemoryStream mem_stream = new MemoryStream(hash_table))
                {
                    BinaryFileReader reader = new BinaryFileReader(mem_stream);
                    for (int i = 0; i < m_Header.Hashcount; i++)
                        m_HashEntries[i] = new LPKHashEntry(reader);
                }
            }
            else
            {
                for (int i = 0; i < m_Header.Hashcount; i++)
                    m_HashEntries[i] = new LPKHashEntry(m_Reader);
            }

            m_BlockEntries = new LPKBlockEntry[m_Header.BlockCount];
            if (m_Header.HashTableSizeCompressed != 0)
            {
                byte[] block_table_compressed = m_Reader.ReadBytes((int)m_Header.BlockTableSizeCompressed);
                byte[] block_table = Compression.LZF.Decompress(block_table_compressed, (int)m_Header.BlockCount * LPKBlockEntry.SizeInBytes);
                using (MemoryStream mem_stream = new MemoryStream(block_table))
                {
                    BinaryFileReader reader = new BinaryFileReader(mem_stream);
                    for (int i = 0; i < m_Header.BlockCount; i++)
                        m_BlockEntries[i] = new LPKBlockEntry(reader);
                }
            }
            else
            {
                for (int i = 0; i < m_Header.BlockCount; i++)
                    m_BlockEntries[i] = new LPKBlockEntry(m_Reader);
            }
        }
示例#3
0
        public static void CreatePackedFileSystem(string in_directory_prefix, string in_directory, string out_file_path, bool compress_headers = true, bool allow_compression_of_files = true, uint hash_count = 0x1000)
        {
            string filelist_filename = "filelist.txt";
            string worklpk_filename = "work.lpk";

            // Create the local content processor
            Processors.AllProcessors processor = new Processors.AllProcessors();

            // get all files to include in this packed file system
            string basepath = AppDomain.CurrentDomain.BaseDirectory + in_directory_prefix;
            IEnumerable<string> all_files = InterXLib.Library.GetFilesInPath(basepath + in_directory + @"\").ToArray<string>();
            List<string> lstFilenames = new List<string>();
            lstFilenames.Add(filelist_filename);
            foreach (string file in all_files)
            {
                if (processor.ExcludeThisFileFromLPK(file))
                {
                    // exclude it... write out a list of files to exclude?
                }
                else
                {
                    lstFilenames.Add(file);
                }
            }

            // create the file system. It has num_files (first file is 'filelist.txt' which contains all files in the packed file system.
            LPKWriter fs = new LPKWriter((uint)(lstFilenames.Count));
            // open the work writer
            BinaryFileWriter work_file_contents = InterXLib.Serialize.OpenWriter(worklpk_filename);
            // list of any files that don't fit in the current system (their hash is already taken).
            List<OrphanedHash> orphaned_hashes = new List<OrphanedHash>();

            // create and save the 'filelist.txt' file. It should be the first file inserted into the hash array.
            if (lstFilenames.Count > 0)
            {
                StringBuilder sbFilelist = new StringBuilder();
                for (int i = 0; i < lstFilenames.Count; i++)
                {
                    if (sbFilelist.Length > 0)
                        sbFilelist.Append("\n");
                    string istr = lstFilenames[i];
                    if (istr.StartsWith(basepath))
                        istr = istr.Remove(0, basepath.Length);
                    sbFilelist.Append(istr);
                }
                File.WriteAllText(filelist_filename, sbFilelist.ToString());
            }

            // create all hashes and blocks and write the contents of the files out to a work file.
            for (int i = 0; i < lstFilenames.Count; i++)
            {
                string filename = lstFilenames[i];
                if (filename.StartsWith(basepath))
                    filename = filename.Remove(0, basepath.Length);
                filename = filename.ToLower();
                uint crc = CRC32.ComputeChecksum(filename);
                uint crc2 = CRC32.ComputeChecksumReverse(filename);
                LPKHashEntry entry = new LPKHashEntry(crc2, (uint)i, LPK.NoHash);

                if (fs.m_HashEntries[crc % hash_count] == null)
                    fs.m_HashEntries[crc % hash_count] = entry;
                else
                    orphaned_hashes.Add(new OrphanedHash(crc, entry));

                // write the data from the files to the work file.
                // if the data can be 'processed', write the processed data instead.
                uint ptr_to_file = (uint)work_file_contents.Position;
                byte[] file_data = System.IO.File.ReadAllBytes(lstFilenames[i]);
                Processors.ProcessedFile processed_file = null;

                if (processor.TryProcess(lstFilenames[i], file_data, allow_compression_of_files, out processed_file))
                {
                    if (processed_file.IsCompressed)
                    {
                        file_data = processed_file.CompressedData;
                        fs.m_BlockEntries[i] = new LPKBlockEntry(ptr_to_file, (uint)processed_file.ProcessedData.Length, (uint)processed_file.CompressedData.Length, 0);
                    }
                    else
                    {
                        file_data = processed_file.ProcessedData;
                        fs.m_BlockEntries[i] = new LPKBlockEntry(ptr_to_file, (uint)file_data.Length, 0, 0);
                    }
                    work_file_contents.Write(file_data);
                }
                else
                {
                    fs.m_BlockEntries[i] = new LPKBlockEntry(ptr_to_file, (uint)file_data.Length, 0, 0);
                    work_file_contents.Write(file_data);
                }
            }

            // place the orphaned hashes in the hash entries array.
            for (int i = 0; i < orphaned_hashes.Count; i++)
            {
                uint crc = orphaned_hashes[i].FirstHash;
                LPKHashEntry entry = orphaned_hashes[i].HashEntry;

                LPKHashEntry last_entry = fs.m_HashEntries[crc % hash_count];
                while (last_entry.NextHashInSequence != NoHash)
                {
                    last_entry = fs.m_HashEntries[last_entry.NextHashInSequence % hash_count];
                    // !!! Sanity check to see that we don't loop forever?
                }

                int next_hash_to_check = 0;
                // find the first open spot for the orphaned entry.
                for (int j = next_hash_to_check; j < hash_count; j++)
                {
                    if (fs.m_HashEntries[j] == null)
                    {
                        fs.m_HashEntries[j] = entry;
                        last_entry.NextHashInSequence = (uint)j;
                        next_hash_to_check = j + 1;
                        break;
                    }
                }
            }

            // close the work writer
            work_file_contents.Close();
            work_file_contents = null;

            // delete the filelist.
            System.IO.File.Delete(filelist_filename);

            // get the work file contents and then delete the work file.
            byte[] all_file_data = System.IO.File.ReadAllBytes(worklpk_filename);
            System.IO.File.Delete(worklpk_filename);

            while (System.IO.File.Exists(out_file_path))
            {
                try
                {
                    System.IO.File.Delete(out_file_path);
                }
                catch
                {
                    System.Threading.Thread.Sleep(1);
                }
            }
            BinaryFileWriter out_file_writer = InterXLib.Serialize.OpenWriter(out_file_path);
            fs.InternalSerializeHeaders(out_file_writer, compress_headers);
            out_file_writer.Write(all_file_data);

            out_file_writer.Close();
            out_file_writer = null;
        }
示例#4
0
 public OrphanedHash(uint first_hash, LPKHashEntry hash_entry)
 {
     FirstHash = first_hash;
     HashEntry = hash_entry;
 }
示例#5
0
        private BinaryFileReader InternalGetFileBinaryReader(LPKHashEntry hash, uint offset = 0, uint length = c_RetrieveAllData)
        {
            LPKBlockEntry block = m_BlockEntries[hash.BlockIndex];
            if (block.FileSizeCompressed == 0)
            {
                if (length == c_RetrieveAllData)
                    length = block.FileSize;

                if (offset + length > block.FileSize || offset < 0)
                    Logging.Fatal("Attempt to read outside of requested data block!");

                // add file pointer to offset.
                offset = offset + block.PtrFile + m_Header.PtrFiles;

                m_Reader.Position = offset;
                return m_Reader;
            }
            else
            {
                m_Reader.Position = m_Header.PtrFiles + block.PtrFile;
                byte[] compressed_data = m_Reader.ReadBytes((int)block.FileSizeCompressed);
                byte[] data = Compression.LZF.Decompress(compressed_data, (int)block.FileSize);
                MemoryStream mem_stream = new MemoryStream(data);
                return new BinaryFileReader(mem_stream);
            }
        }