private void WriteIndex(IBuffer buffer, HdrIndex index)
 {
     buffer.Position = index.Position;
     buffer.WriteCString(index.Name);
     buffer.Position = index.Position + 260;
     buffer.WriteInt32(index.Length);
     buffer.WriteInt32(index.Offset);
 }
        public HdrArchive Read(string sourcePath)
        {
            byte[]         hdrFile          = ReadFile(sourcePath);
            IBuffer        buffer           = BufferProvider.Provide(hdrFile);
            HdrHeader      header           = ReadHeader(buffer);
            List <HdrFile> files            = new List <HdrFile>();
            int            folderIndexStart = header.IndexOffset;
            int            totalFiles       = 0;
            int            currentFile      = 0;

            for (int i = 0; i < header.FolderCount; i++)
            {
                buffer.Position = folderIndexStart + i * IndexBlockSize;
                HdrIndex folderIndex = ReadIndex(buffer);
                buffer.Position = folderIndex.Offset;
                for (int j = 0; j < folderIndex.Length; j++)
                {
                    HdrIndex fileIndex = ReadIndex(buffer);
                    int      offset    = fileIndex.Offset;
                    int      lenght    = fileIndex.Length;
                    string   ext;
                    if (Path.HasExtension(fileIndex.Name))
                    {
                        ext = Path.GetExtension(fileIndex.Name);
                        switch (ext)
                        {
                        case ".pts":
                            // PTS-Files are PNG files with the first 4byte beeing lengt of the data.
                            // We already know the length from the index.
                            // offset += 4;
                            // lenght -= 4;
                            break;
                        }
                    }
                    else
                    {
                        ext = "";
                    }
                    HdrFile file = new HdrFile();
                    file.FileExtension    = ext;
                    file.FileName         = fileIndex.Name;
                    file.HdrDirectoryPath = folderIndex.Name;
                    file.HdrFullPath      = folderIndex.Name + fileIndex.Name;
                    file.Data             = buffer.GetBytes(offset, lenght);
                    file.Offset           = offset;
                    file.Length           = lenght;
                    file.Extension        = ext;
                    files.Add(file);
                    currentFile++;
                }
                totalFiles += folderIndex.Length;
                OnProgressChanged(totalFiles, currentFile);
            }
            return(new HdrArchive(files, header));
        }
        private HdrIndex ReadIndex(IBuffer data)
        {
            HdrIndex index = new HdrIndex();

            index.Position = data.Position;
            index.Name     = data.ReadCString();
            data.Position  = index.Position + 260;
            index.Length   = data.ReadInt32();
            index.Offset   = data.ReadInt32();
            return(index);
        }
        public void Write(HdrArchive archive, string destinationPath)
        {
            Dictionary <string, List <HdrFile> > folderDictionary = new Dictionary <string, List <HdrFile> >();
            List <string> orderedKeys = new List <string>();

            foreach (HdrFile file in archive.Files)
            {
                if (archive.Header.ArchiveType == HdrArchiveType.Tro)
                {
                    string[] folderNameParts = file.HdrDirectoryPath.Split('\\');
                    string   folderName      = "";
                    for (int i = 0; i < folderNameParts.Length; i++)
                    {
                        if (!string.IsNullOrEmpty(folderNameParts[i]))
                        {
                            folderName += folderNameParts[i] + '\\';
                            if (!folderDictionary.ContainsKey(folderName))
                            {
                                folderDictionary.Add(folderName, new List <HdrFile>());
                                orderedKeys.Add(folderName);
                            }
                        }
                    }
                }
                if (folderDictionary.ContainsKey(file.HdrDirectoryPath))
                {
                    folderDictionary[file.HdrDirectoryPath].Add(file);
                }
                else
                {
                    folderDictionary.Add(file.HdrDirectoryPath, new List <HdrFile>()
                    {
                        file
                    });
                    orderedKeys.Add(file.HdrDirectoryPath);
                }
            }
            orderedKeys.Sort((s1, s2) => string.Compare(s1, s2, StringComparison.InvariantCultureIgnoreCase));
            IBuffer buffer               = BufferProvider.Provide();
            int     totalFiles           = archive.Files.Count;
            int     currentFile          = 0;
            int     folderIndexStart     = archive.Header.IndexOffset;
            int     fileIndexStart       = folderIndexStart + folderDictionary.Count * IndexBlockSize;
            int     contentStart         = fileIndexStart + IndexBlockSize * archive.Files.Count;
            int     currentFolderIndex   = 0;
            int     currentFileIndex     = 0;
            int     currentContentLength = 0;

            foreach (string key in orderedKeys)
            {
                HdrIndex folderIndex = new HdrIndex();
                folderIndex.Name     = key;
                folderIndex.Length   = folderDictionary[key].Count;
                folderIndex.Position = folderIndexStart + currentFolderIndex;
                if (folderIndex.Length > 0)
                {
                    folderIndex.Offset = fileIndexStart + currentFileIndex;
                }
                else
                {
                    folderIndex.Offset = 0;
                }
                WriteIndex(buffer, folderIndex);
                foreach (HdrFile file in folderDictionary[key])
                {
                    HdrIndex fileIndex = new HdrIndex();
                    fileIndex.Name     = file.FileName;
                    fileIndex.Length   = file.Data.Length;
                    fileIndex.Position = fileIndexStart + currentFileIndex;
                    fileIndex.Offset   = contentStart + currentContentLength;
                    WriteIndex(buffer, fileIndex);
                    buffer.WriteBytes(file.Data, 0, fileIndex.Offset, fileIndex.Length);
                    currentFileIndex     += IndexBlockSize;
                    currentContentLength += file.Data.Length;
                    currentFile++;
                }
                currentFolderIndex += IndexBlockSize;
                OnProgressChanged(totalFiles, currentFile);
            }
            HdrHeader header = new HdrHeader();

            header.ContentOffset = contentStart;
            header.Created       = archive.Header.Created;
            header.FolderCount   = folderDictionary.Count;
            header.Format        = Hdr;
            header.Unknown0      = archive.Header.Unknown0;
            header.IndexOffset   = folderIndexStart;
            buffer.Position      = 0;
            WriteHeader(buffer, header);
            WriteFile(buffer.GetAllBytes(), destinationPath);
        }