Ejemplo n.º 1
0
        public Result Add(EQArchiveFile File, bool ReplaceSimilarImage)
        {
            if (File == null)
            {
                return(Result.InvalidArgument);
            }

            EQArchiveFile _archiveFile;

            if (ReplaceSimilarImage)
            {
                _archiveFile = this.FindFileOrSimilarImage(Filename);
            }
            else
            {
                _archiveFile = this.FindFile(Filename);
            }

            if (_archiveFile != null)
            {
                // We already have a file that has a similar name. Import the new file AS that file, replacing it.

                this.Files.RemoveAt(this.Files.IndexOfValue(_archiveFile));

                File.Filename = _archiveFile.Filename;
            }

            this.Files[File.Filename.ToLower()] = File;

            this.IsDirty = true;

            return(File.Status);
        }
Ejemplo n.º 2
0
        public Result Remove(EQArchiveFile File)
        {
            if (File == null)
            {
                return(Result.FileNotFound);
            }

            this.Files.RemoveAt(this.Files.IndexOfValue(File));

            this.IsDirty = true;

            return(Result.OK);
        }
Ejemplo n.º 3
0
 public Result Add(EQArchiveFile File)
 {
     return this.Add(File, false);
 }
Ejemplo n.º 4
0
        public static EQArchive Load(string Filename, byte[] Contents)
        {
            if (Util.IsBlank(Filename) || (Contents == null))
            {
                // We got a bad filename, or the file is zero length, and thus not a PFS archive.

                return null;
            }

            Header _header = new Header();

            using (BinaryReader _input = new BinaryReader(new MemoryStream(Contents)))
            {
                try
                {
                    //
                    //   1. Read the file header
                    //

                    _header.IndexPointer = _input.ReadUInt32();
                    _header.MagicNumber = _input.ReadUInt32();
                    _header.VersionNumber = _input.ReadUInt32();
                }
                catch
                {
                    // Too small to be a PFS archive

                    return null;
                }

                if (_header.MagicNumber != _MagicNumber)
                {
                    // Not a PFS archive

                    return null;
                }

                EQArchive _archive = new EQArchive();
                _archive.Filename = Filename;
                _archive.SizeOnDisk = (UInt32)Contents.Length;

                try
                {
                    //
                    //   2. Read Index of File Pointers and Sizes in Archive
                    //

                    _input.BaseStream.Seek(_header.IndexPointer, SeekOrigin.Begin);

                    _header.EntryCount = _input.ReadUInt32();

                    if (_header.EntryCount == 0)
                    {
                        // Empty archive...?
                        _archive.Files = new SortedList<string, EQArchiveFile>();
                    }
                    else
                    {
                        _archive.Files = new SortedList<string, EQArchiveFile>((int)_header.EntryCount);
                    }

                    // Filename directory is the "file" at the end of the archive (with the highest FilePointer)
                    EQArchiveFile _directory = null;

                    // For verification later, which is optional, but will catch a malformed/corrupted archive.
                    Dictionary<UInt32, UInt32> _filenameCRCs = new Dictionary<UInt32, UInt32>();

                    // Files in a PFS archive tend to be stored by ascending order of FilenameCRC.
                    // However, the filename directory is sorted by FilePointer
                    SortedList<UInt32, EQArchiveFile> _files = new SortedList<UInt32, EQArchiveFile>();

                    for (UInt32 _index = 0; _index < _header.EntryCount; _index++)
                    {
                        EQArchiveFile _file = new EQArchiveFile();
                        UInt32 _filenameCRC = _input.ReadUInt32();
                        _file.FilePointer = _input.ReadUInt32();
                        _file.Size.Uncompressed = _input.ReadUInt32();
                        _filenameCRCs.Add(_file.FilePointer, _filenameCRC);

                        if ((_directory == null) || (_file.FilePointer > _directory.FilePointer))
                        {
                            _directory = _file;
                        }

                        _files.Add(_file.FilePointer, _file);
                    }

                    if ((_input.BaseStream.Length - _input.BaseStream.Position) >= 9)
                    {
                        // PFS Footer

                        char[] _token = _input.ReadChars(5);

                        if (new String(_token).Equals("STEVE"))
                        {
                            // Valid Footer Token

                            _header.DateStamp = _input.ReadUInt32();
                        }
                    }

                    //
                    //   3. Read the compressed file entries (each split into compressed chunks)
                    //

                    foreach (EQArchiveFile _file in _files.Values)
                    {
                        // Seek to entry position in stream
                        _input.BaseStream.Seek(_file.FilePointer, SeekOrigin.Begin);

                        UInt32 _totalUncompressedBytes = _file.Size.Uncompressed;
                        _file.Size.Uncompressed = 0;

                        while ((_file.Size.Uncompressed < _totalUncompressedBytes) && (_input.BaseStream.Position < _input.BaseStream.Length))
                        {
                            UInt32 _blockSizeCmp = _input.ReadUInt32();
                            UInt32 _blockSizeUnc = _input.ReadUInt32();

                            // Sanity Check 1: Uncompressed data larger than what we were told?
                            if ((_blockSizeUnc + _file.Size.Uncompressed) > _totalUncompressedBytes)
                            {
                                throw new Exception();
                            }

                            // Sanity Check 2: Compressed data goes past the end of the file?
                            if ((_input.BaseStream.Position + _blockSizeCmp) > _input.BaseStream.Length)
                            {
                                throw new Exception();
                            }

                            _file.AddChunk(new EQArchiveFile.Chunk(Contents, (UInt32)_input.BaseStream.Position, _blockSizeCmp, _blockSizeUnc, true));

                            _input.BaseStream.Position += _blockSizeCmp;
                        }
                    }

                    //
                    //    4. Unpack and parse the directory of filenames from the "file" at the end of the archive (highest FilePointer)
                    //

                    // Remove directory from file entries in archive. We'll have to rebuild it when saving the archive anyway.
                    _files.Remove(_directory.FilePointer);
                    _header.EntryCount--;

                    // Load filenames from directory
                    BinaryReader _dirStream = new BinaryReader(new MemoryStream(_directory.GetContents()));

                    UInt32 _filenameCount = _dirStream.ReadUInt32();

                    if (_filenameCount > _header.EntryCount)
                    {
                        // If we somehow have more filenames than entries in the archive, ignore the glitched extras

                        _filenameCount = _header.EntryCount;
                    }

                    _archive.Files = new SortedList<string, EQArchiveFile>();

                    foreach (EQArchiveFile _file in _files.Values)
                    {
                        Int32 _len = _dirStream.ReadInt32();
                        char[] _inputname = _dirStream.ReadChars(_len);
                        UInt32 _crc = GetFilenameCRC(_inputname);

                        if (_crc != _filenameCRCs[_file.FilePointer])
                        {
                            // Filename doesn't match with what we were given in Step 2

                            // This happens in gequip.s3d. We are ignoring it.

                            //throw new Exception();
                        }

                        _file.Filename = new string(_inputname, 0, _len - 1);

                        _archive.Files.Add(_file.Filename.ToLower(), _file);
                    }

                    // All entries loaded and filenames read from directory.

                    _archive.Status = Result.OK;
                }
                catch
                {
                    _archive.Status = Result.MalformedFile;
                }

                return _archive;
            }
        }
Ejemplo n.º 5
0
        private void formMain_DragDrop(object sender, DragEventArgs e)
        {
            ShellFileGroup _newFiles = null;
            string[] _newFilenames = null;
            int _numFiles;

            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                _newFilenames = (string[])e.Data.GetData(DataFormats.FileDrop);
                _numFiles = _newFilenames.Length;
            }
            else if (e.Data.GetDataPresent("FileContents"))
            {
                _newFiles = ShellFileGroup.FromClipboard(e.Data);
                _numFiles = _newFiles.Files.Count;
            }
            else
            {
                return;
            }

            if (_numFiles == 1)
            {
                // Dragged a single file in. Might want to do something special.

                ShellFileGroup.ShellFile _newFile = (_newFiles == null) ? null : _newFiles.Files[0];
                string _newFilename = (_newFile == null) ? _newFilenames[0] : _newFile.Name;

                if (Util.IsArchive(_newFilename))
                {
                    // It's a new archive. Load it up (with confirmation if unsaved changes)!

                    LoadArchive(_newFilename);

                    return;
                }

                ListViewItem _item = listView1.HitTest(listView1.PointToClient(new Point(e.X, e.Y))).Item;

                if (_item != null)
                {
                    // User dragged a new file onto an existing item. If both files are textures, or otherwise
                    // have the same extension, they may be wanting to replace the old file with the new one.

                    formReplaceDialog _confirm;

                    if (System.IO.Path.GetExtension(_item.Text).Equals(System.IO.Path.GetExtension(_newFilename), StringComparison.CurrentCultureIgnoreCase) ||
                        (Util.IsImage(_item.Text) && Util.IsImage(_newFilename)))
                    {
                        EQArchiveFile _old = (EQArchiveFile)_item.Tag;
                        EQArchiveFile _new;

                        if (_newFile != null)
                        {
                            _new = new EQArchiveFile(_newFile.Name, _newFile.Contents);
                        }
                        else
                        {
                            _new = new EQArchiveFile(_newFilename);
                        }

                        if (_new.GetImage() == null)
                        {
                            if (Util.IsImage(_new.Filename))
                            {
                                _new.SetThumbnail(itemThumbsLarge.Images[1]);
                            }
                            else if (FileTypes.ContainsKey(System.IO.Path.GetExtension(_new.Filename).ToLower()))
                            {
                                _new.SetThumbnail(itemThumbsLarge.Images[2]);
                            }
                            else
                            {
                                _new.SetThumbnail(itemThumbsLarge.Images[0]);
                            }
                        }
                        else
                        {
                            _new.SetThumbnail(GetSquareImage(_new.GetImage()));
                        }

                        _confirm = new formReplaceDialog();
                        _confirm.OldFile = _old;
                        _confirm.NewFile = _new;

                        switch (_confirm.ShowDialog(this))
                        {
                            case DialogResult.Yes:
                                ReplaceFile(_item, _new);
                                Status_Changed(true);
                                return;
                            case DialogResult.No:
                                // Separate file
                                if (CurrentArchive == null)
                                {
                                    LoadArchive("");
                                    ImportFile(_new);
                                    return;
                                }

                                // We'll have to change the filename to avoid overwriting.
                                string _newName = _new.Filename;

                                while (CurrentArchive.FindFileOrSimilarImage(_newName) != null)
                                {
                                    _newName = System.IO.Path.GetFileNameWithoutExtension(_newName) + " (New)" + System.IO.Path.GetExtension(_newName);
                                }

                                ImportFileAs(_new.Filename, _new.GetContents(), _newName);
                                Status_Changed(true);
                                return;
                            case DialogResult.Cancel:
                                // Ignore new file.
                                return;
                        }
                    }
                }
            }

            if (_newFiles == null)
            {
                ImportFiles(_newFilenames);
            }
            else
            {
                ImportFiles(_newFiles);
            }

            Status_Changed(true);
        }
Ejemplo n.º 6
0
        public bool ReplaceFile(ListViewItem OldItem, EQArchiveFile NewFile)
        {
            if ((OldItem == null) || (NewFile == null))
            {
                return false;
            }

            NewFile.Filename = OldItem.Text;

            return ImportFile(NewFile, true);
        }
Ejemplo n.º 7
0
 public bool ReplaceFile(string Filename, EQArchiveFile NewFile)
 {
     try
     {
         return ReplaceFile(listView1.Items[Filename.ToLower()], NewFile);
     }
     catch
     {
         return false;
     }
 }
Ejemplo n.º 8
0
        public Result Save()
        {
            if ((this.FilePath == "") || (this.Filename == "(Untitled)") || (this.Filename == ""))
            {
                return Result.InvalidArgument;
            }

            Result _result = Result.OK;

            try
            {
                using (BinaryWriter _file = new BinaryWriter(File.Create(this.FilePath + @"\" + this.Filename)))
                {
                    //
                    //    Step 1 - Get an order of files by filename CRC, per standard PFS archive practice.
                    //

                    SortedList<UInt32, EQArchiveFile> _filesByCRC = new SortedList<UInt32, EQArchiveFile>();

                    foreach (EQArchiveFile _entry in this.Files.Values)
                    {
                        _filesByCRC.Add(GetFilenameCRC(_entry.Filename), _entry);
                    }

                    //
                    //    Step 2 - Build the directory of filenames and compress it for adding at the end of the archive
                    //

                    EQArchiveFile _directory = new EQArchiveFile();

                    byte[] _directoryBytes = new byte[16 * 1024];

                    using (BinaryWriter _stream = new BinaryWriter(new MemoryStream(_directoryBytes)))
                    {
                        UInt32 _directorySize = 0;

                        _stream.Write((UInt32)this.Files.Count);

                        foreach (EQArchiveFile _entry in _filesByCRC.Values)
                        {
                            _stream.Write((UInt32)_entry.Filename.Length + 1);
                            foreach (char _c in _entry.Filename)
                            {
                                _stream.Write(_c);
                            }
                            _stream.Write('\0');
                        }

                        _directorySize = (UInt32)_stream.BaseStream.Position;

                        Array.Resize<byte>(ref _directoryBytes, (int)_directorySize);

                        _directory.SetContents(_directoryBytes);
                    }

                    //
                    //    Step 3 - Build the file header
                    //

                    Header _header = new Header();
                    _header.MagicNumber = _MagicNumber;
                    _header.VersionNumber = 0x00020000;

                    // a. Index Pointer must be determined. Start with the size after the header itself
                    _header.IndexPointer = 4 + 4 + 4;

                    // b. Add in the size of all of the compressed chunks and their two size values
                    foreach (EQArchiveFile _entry in this.Files.Values)
                    {
                        _header.IndexPointer += (4 + 4) * (_entry.CompressedChunks == null ? 1 : (UInt32)_entry.CompressedChunks.Count);
                        _header.IndexPointer += _entry.Size.Compressed;
                    }

                    // c. Add in the size of the compressed filename directory and its size values
                    _header.IndexPointer += (4 + 4) * (UInt32)_directory.CompressedChunks.Count + _directory.Size.Compressed;

                    //
                    //    Step 4 - Write the file Header
                    //

                    _file.Write(_header.IndexPointer);
                    _file.Write(_header.MagicNumber);
                    _file.Write(_header.VersionNumber);

                    //
                    //    Step 5 - Compressed File Chunks
                    //
                    foreach (EQArchiveFile _entry in _filesByCRC.Values)
                    {
                        _entry.FilePointer = (UInt32)_file.BaseStream.Position;

                        foreach (EQArchiveFile.Chunk _chunk in _entry.CompressedChunks)
                        {
                            _file.Write(_chunk.Size.Compressed);
                            _file.Write(_chunk.Size.Uncompressed);
                            _file.Write(_chunk.CompressedData, 0, (int)_chunk.Size.Compressed);
                        }
                    }

                    //
                    //    Step 6 - Filename Directory compressed chunks at the end
                    //
                    _directory.FilePointer = (UInt32)_file.BaseStream.Position;

                    foreach (EQArchiveFile.Chunk _chunk in _directory.CompressedChunks)
                    {
                        _file.Write(_chunk.Size.Compressed);
                        _file.Write(_chunk.Size.Uncompressed);
                        _file.Write(_chunk.CompressedData, 0, (int)_chunk.Size.Compressed);
                    }

                    //
                    //    Step 7 - Index of File Entries
                    //
                    _file.Write((UInt32)(this.Files.Count + 1));

                    foreach (KeyValuePair<UInt32, EQArchiveFile> _kvp in _filesByCRC)
                    {
                        _file.Write(_kvp.Key);
                        _file.Write(_kvp.Value.FilePointer);
                        _file.Write(_kvp.Value.Size.Uncompressed);
                    }

                    //
                    //    Step 8 - Add filename directory to end of index
                    //

                    _file.Write(0xFFFFFFFFU);
                    _file.Write(_directory.FilePointer);
                    _file.Write(_directory.Size.Uncompressed);

                    //
                    //    Step 9 - PFS Footer
                    //

                    foreach (char _letter in _FooterToken)
                    {
                        _file.Write(_letter);
                    }

                    _file.Write(_header.DateStamp);

                    _file.Close();
                }
            }
            catch
            {
                return Result.FileWriteError;
            }

            if (_result == Result.OK)
            {
                this.IsDirty = false;
            }

            return _result;
        }
Ejemplo n.º 9
0
        private bool ImportFileAs(string File, byte[] Contents, string NewFilename)
        {
            EQArchiveFile _newFile = new EQArchiveFile(File, Contents);
            _newFile.Filename = NewFilename;

            return ImportFile(_newFile);
        }
Ejemplo n.º 10
0
        private bool ImportFile(EQArchiveFile File, bool Override)
        {
            if (CurrentArchive == null)
            {
                CurrentArchive = new EQArchive();
            }

            EQArchiveFile _existing;

            if (Settings.ImportFormat != "")
            {
                _existing = CurrentArchive.FindFileOrSimilarImage(File.Filename);
            }
            else
            {
                _existing = CurrentArchive.FindFile(File.Filename);
            }

            string _newName = null;

            if (_existing != null)
            {
                _newName = _existing.Filename;

                if (!Override || Settings.ConfirmImportOverwrite)
                {
                    switch (MessageBox.Show(this, "The file " + _existing.Filename + " exists in the archive.\n\nDo you wish to overwrite this file with your new one?", "Importing File Exists", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
                    {
                        case DialogResult.No:
                            _newName = File.Filename;

                            while (CurrentArchive.FindFileOrSimilarImage(_newName) != null)
                            {
                                _newName = System.IO.Path.GetFileNameWithoutExtension(_newName) + " (New)" + System.IO.Path.GetExtension(_newName);
                            }
                            break;
                    }
                }

                File.Filename = _newName;

                if (_newName == _existing.Filename) // We're replacing it.
                {
                    DeleteItem(listView1.Items[_existing.Filename.ToLower()]);
                }
            }

            if ((Settings.ImportFormat != "") && (File.GetImage() != null) && (File.ImageFormat != Settings.ImportFormat))
            {
                File = File.AsFormat(Settings.ImportFormat, (_existing == null));
            }

            bool _ok = (CurrentArchive.Add(File) == Result.OK);

            NewFile = File;
            Status_Changed(true);

            return _ok;
        }
Ejemplo n.º 11
0
 private bool ImportFile(EQArchiveFile File)
 {
     return ImportFile(File, false);
 }
Ejemplo n.º 12
0
        public EQArchiveFile AsFormat(string NewFormat, bool ChangeExtension)
        {
            if ((NewFormat == null) || (NewFormat == "") || (this.GetImage() == null))
            {
                return(this);
            }

            NewFormat = NewFormat.ToLower();

            if (NewFormat == "auto")
            {
                switch (GetAlphaBits())
                {
                case 0:
                case 1:
                    NewFormat = "16-bit";
                    break;

                case 8:
                    NewFormat = "32-bit";
                    break;

                default:     // ?
                    NewFormat = "32-bit";
                    break;
                }
            }

            EQArchiveFile _newFile = null;

            if (NewFormat != this.ImageFormat)
            {
                _newFile          = new EQArchiveFile();
                _newFile.Filename = this.Filename;
                _newFile.SetImage(this.GetImage(), NewFormat);
            }

            if (ChangeExtension && !System.IO.Path.GetExtension(this.Filename).Equals((NewFormat[0] == '.' ? NewFormat : ".dds"), StringComparison.CurrentCultureIgnoreCase))
            {
                // Gotta change the extension

                if (_newFile == null)
                {
                    _newFile = new EQArchiveFile();
                    _newFile.SetContents(this.GetContents());
                }

                _newFile.Filename = System.IO.Path.GetFileNameWithoutExtension(this.Filename) + (NewFormat[0] == '.' ? NewFormat : ".dds");
            }
            else
            {
                if (_newFile == null)
                {
                    _newFile = this; // Unchanged from our current contents
                }
                else
                {
                    _newFile.Filename = this.Filename;
                }
            }

            return(_newFile);
        }
Ejemplo n.º 13
0
        public static EQArchive Load(string Filename, byte[] Contents)
        {
            if (Util.IsBlank(Filename) || (Contents == null))
            {
                // We got a bad filename, or the file is zero length, and thus not a PFS archive.

                return(null);
            }

            Header _header = new Header();

            using (BinaryReader _input = new BinaryReader(new MemoryStream(Contents)))
            {
                try
                {
                    //
                    //   1. Read the file header
                    //

                    _header.IndexPointer  = _input.ReadUInt32();
                    _header.MagicNumber   = _input.ReadUInt32();
                    _header.VersionNumber = _input.ReadUInt32();
                }
                catch
                {
                    // Too small to be a PFS archive

                    return(null);
                }

                if (_header.MagicNumber != _MagicNumber)
                {
                    // Not a PFS archive

                    return(null);
                }

                EQArchive _archive = new EQArchive();
                _archive.Filename   = Filename;
                _archive.SizeOnDisk = (UInt32)Contents.Length;

                try
                {
                    //
                    //   2. Read Index of File Pointers and Sizes in Archive
                    //

                    _input.BaseStream.Seek(_header.IndexPointer, SeekOrigin.Begin);

                    _header.EntryCount = _input.ReadUInt32();

                    if (_header.EntryCount == 0)
                    {
                        // Empty archive...?
                        _archive.Files = new SortedList <string, EQArchiveFile>();
                    }
                    else
                    {
                        _archive.Files = new SortedList <string, EQArchiveFile>((int)_header.EntryCount);
                    }

                    // Filename directory is the "file" at the end of the archive (with the highest FilePointer)
                    EQArchiveFile _directory = null;

                    // For verification later, which is optional, but will catch a malformed/corrupted archive.
                    Dictionary <UInt32, UInt32> _filenameCRCs = new Dictionary <UInt32, UInt32>();

                    // Files in a PFS archive tend to be stored by ascending order of FilenameCRC.
                    // However, the filename directory is sorted by FilePointer
                    SortedList <UInt32, EQArchiveFile> _files = new SortedList <UInt32, EQArchiveFile>();

                    for (UInt32 _index = 0; _index < _header.EntryCount; _index++)
                    {
                        EQArchiveFile _file        = new EQArchiveFile();
                        UInt32        _filenameCRC = _input.ReadUInt32();
                        _file.FilePointer       = _input.ReadUInt32();
                        _file.Size.Uncompressed = _input.ReadUInt32();
                        _filenameCRCs.Add(_file.FilePointer, _filenameCRC);

                        if ((_directory == null) || (_file.FilePointer > _directory.FilePointer))
                        {
                            _directory = _file;
                        }

                        _files.Add(_file.FilePointer, _file);
                    }

                    if ((_input.BaseStream.Length - _input.BaseStream.Position) >= 9)
                    {
                        // PFS Footer

                        char[] _token = _input.ReadChars(5);

                        if (new String(_token).Equals("STEVE"))
                        {
                            // Valid Footer Token

                            _header.DateStamp = _input.ReadUInt32();
                        }
                    }

                    //
                    //   3. Read the compressed file entries (each split into compressed chunks)
                    //

                    foreach (EQArchiveFile _file in _files.Values)
                    {
                        // Seek to entry position in stream
                        _input.BaseStream.Seek(_file.FilePointer, SeekOrigin.Begin);

                        UInt32 _totalUncompressedBytes = _file.Size.Uncompressed;
                        _file.Size.Uncompressed = 0;

                        while ((_file.Size.Uncompressed < _totalUncompressedBytes) && (_input.BaseStream.Position < _input.BaseStream.Length))
                        {
                            UInt32 _blockSizeCmp = _input.ReadUInt32();
                            UInt32 _blockSizeUnc = _input.ReadUInt32();

                            // Sanity Check 1: Uncompressed data larger than what we were told?
                            if ((_blockSizeUnc + _file.Size.Uncompressed) > _totalUncompressedBytes)
                            {
                                throw new Exception();
                            }

                            // Sanity Check 2: Compressed data goes past the end of the file?
                            if ((_input.BaseStream.Position + _blockSizeCmp) > _input.BaseStream.Length)
                            {
                                throw new Exception();
                            }

                            _file.AddChunk(new EQArchiveFile.Chunk(Contents, (UInt32)_input.BaseStream.Position, _blockSizeCmp, _blockSizeUnc, true));

                            _input.BaseStream.Position += _blockSizeCmp;
                        }
                    }

                    //
                    //    4. Unpack and parse the directory of filenames from the "file" at the end of the archive (highest FilePointer)
                    //

                    // Remove directory from file entries in archive. We'll have to rebuild it when saving the archive anyway.
                    _files.Remove(_directory.FilePointer);
                    _header.EntryCount--;

                    // Load filenames from directory
                    BinaryReader _dirStream = new BinaryReader(new MemoryStream(_directory.GetContents()));

                    UInt32 _filenameCount = _dirStream.ReadUInt32();

                    if (_filenameCount > _header.EntryCount)
                    {
                        // If we somehow have more filenames than entries in the archive, ignore the glitched extras

                        _filenameCount = _header.EntryCount;
                    }

                    _archive.Files = new SortedList <string, EQArchiveFile>();

                    foreach (EQArchiveFile _file in _files.Values)
                    {
                        Int32  _len       = _dirStream.ReadInt32();
                        char[] _inputname = _dirStream.ReadChars(_len);
                        UInt32 _crc       = GetFilenameCRC(_inputname);

                        if (_crc != _filenameCRCs[_file.FilePointer])
                        {
                            // Filename doesn't match with what we were given in Step 2

                            // This happens in gequip.s3d. We are ignoring it.

                            //throw new Exception();
                        }

                        _file.Filename = new string(_inputname, 0, _len - 1);

                        _archive.Files.Add(_file.Filename.ToLower(), _file);
                    }

                    // All entries loaded and filenames read from directory.

                    _archive.Status = Result.OK;
                }
                catch
                {
                    _archive.Status = Result.MalformedFile;
                }

                return(_archive);
            }
        }
Ejemplo n.º 14
0
        public Result Save()
        {
            if ((this.FilePath == "") || (this.Filename == "(Untitled)") || (this.Filename == ""))
            {
                return(Result.InvalidArgument);
            }

            Result _result = Result.OK;

            try
            {
                using (BinaryWriter _file = new BinaryWriter(File.Create(this.FilePath + @"\" + this.Filename)))
                {
                    //
                    //    Step 1 - Get an order of files by filename CRC, per standard PFS archive practice.
                    //

                    SortedList <UInt32, EQArchiveFile> _filesByCRC = new SortedList <UInt32, EQArchiveFile>();

                    foreach (EQArchiveFile _entry in this.Files.Values)
                    {
                        _filesByCRC.Add(GetFilenameCRC(_entry.Filename), _entry);
                    }

                    //
                    //    Step 2 - Build the directory of filenames and compress it for adding at the end of the archive
                    //

                    EQArchiveFile _directory = new EQArchiveFile();

                    byte[] _directoryBytes = new byte[64 * 1024]; // global_chr.s3d = ~29,000 bytes of filenames!

                    using (BinaryWriter _stream = new BinaryWriter(new MemoryStream(_directoryBytes)))
                    {
                        UInt32 _directorySize = 0;

                        _stream.Write((UInt32)this.Files.Count);

                        foreach (EQArchiveFile _entry in _filesByCRC.Values)
                        {
                            _stream.Write((UInt32)_entry.Filename.Length + 1);
                            foreach (char _c in _entry.Filename)
                            {
                                _stream.Write(_c);
                            }
                            _stream.Write('\0');
                        }

                        _directorySize = (UInt32)_stream.BaseStream.Position;

                        Array.Resize <byte>(ref _directoryBytes, (int)_directorySize);

                        _directory.SetContents(_directoryBytes);
                    }

                    //
                    //    Step 3 - Build the file header
                    //

                    Header _header = new Header();
                    _header.MagicNumber   = _MagicNumber;
                    _header.VersionNumber = 0x00020000;

                    // a. Index Pointer must be determined. Start with the size after the header itself
                    _header.IndexPointer = 4 + 4 + 4;

                    // b. Add in the size of all of the compressed chunks and their two size values
                    foreach (EQArchiveFile _entry in this.Files.Values)
                    {
                        _header.IndexPointer += (4 + 4) * (_entry.CompressedChunks == null ? 1 : (UInt32)_entry.CompressedChunks.Count);
                        _header.IndexPointer += _entry.Size.Compressed;
                    }

                    // c. Add in the size of the compressed filename directory and its size values
                    _header.IndexPointer += (4 + 4) * (UInt32)_directory.CompressedChunks.Count + _directory.Size.Compressed;

                    //
                    //    Step 4 - Write the file Header
                    //

                    _file.Write(_header.IndexPointer);
                    _file.Write(_header.MagicNumber);
                    _file.Write(_header.VersionNumber);

                    //
                    //    Step 5 - Compressed File Chunks
                    //
                    foreach (EQArchiveFile _entry in _filesByCRC.Values)
                    {
                        _entry.FilePointer = (UInt32)_file.BaseStream.Position;

                        foreach (EQArchiveFile.Chunk _chunk in _entry.CompressedChunks)
                        {
                            _file.Write(_chunk.Size.Compressed);
                            _file.Write(_chunk.Size.Uncompressed);
                            _file.Write(_chunk.CompressedData, 0, (int)_chunk.Size.Compressed);
                        }
                    }

                    //
                    //    Step 6 - Filename Directory compressed chunks at the end
                    //
                    _directory.FilePointer = (UInt32)_file.BaseStream.Position;

                    foreach (EQArchiveFile.Chunk _chunk in _directory.CompressedChunks)
                    {
                        _file.Write(_chunk.Size.Compressed);
                        _file.Write(_chunk.Size.Uncompressed);
                        _file.Write(_chunk.CompressedData, 0, (int)_chunk.Size.Compressed);
                    }

                    //
                    //    Step 7 - Index of File Entries
                    //
                    _file.Write((UInt32)(this.Files.Count + 1));

                    foreach (KeyValuePair <UInt32, EQArchiveFile> _kvp in _filesByCRC)
                    {
                        _file.Write(_kvp.Key);
                        _file.Write(_kvp.Value.FilePointer);
                        _file.Write(_kvp.Value.Size.Uncompressed);
                    }

                    //
                    //    Step 8 - Add filename directory to end of index
                    //

                    _file.Write(0xFFFFFFFFU);
                    _file.Write(_directory.FilePointer);
                    _file.Write(_directory.Size.Uncompressed);

                    //
                    //    Step 9 - PFS Footer
                    //

                    foreach (char _letter in _FooterToken)
                    {
                        _file.Write(_letter);
                    }

                    _file.Write(_header.DateStamp);

                    _file.Close();
                }
            }
            catch
            {
                return(Result.FileWriteError);
            }

            if (_result == Result.OK)
            {
                this.IsDirty = false;
            }

            return(_result);
        }
Ejemplo n.º 15
0
        public Result Add(EQArchiveFile File, bool ReplaceSimilarImage)
        {
            if (File == null)
            {
                return Result.InvalidArgument;
            }

            EQArchiveFile _archiveFile;

            if (ReplaceSimilarImage)
            {
                _archiveFile = this.FindFileOrSimilarImage(Filename);
            }
            else
            {
                _archiveFile = this.FindFile(Filename);
            }

            if (_archiveFile != null)
            {
                // We already have a file that has a similar name. Import the new file AS that file, replacing it.

                this.Files.RemoveAt(this.Files.IndexOfValue(_archiveFile));

                File.Filename = _archiveFile.Filename;
            }

            this.Files[File.Filename.ToLower()] = File;

            this.IsDirty = true;

            return File.Status;
        }
Ejemplo n.º 16
0
        private void threadListView_DoWork(object sender, DoWorkEventArgs e)
        {
            ThumbnailPerf[0] = new System.Diagnostics.Stopwatch();
            ThumbnailPerf[0].Start();

            if ((CurrentArchive == null) || (CurrentArchive.Files.Count < 1))
            {
                ThumbnailPerf[0].Stop();
                return;
            }

            int _last = CurrentArchive.Files.Count - 1;
            EQArchiveFile[] _files = new EQArchiveFile[_last + 1];
            CurrentArchive.Files.Values.CopyTo(_files, 0);

            ListViewQueue.Clear();
            ThumbnailQueue.Clear();
            DecompressQueue.Clear();

            ThumbnailsLoaded = false;

            threadThumbnails.RunWorkerAsync();

            int _thumbIndex = 0;

            do
            {
                Thread.Sleep(1);

                ThumbnailMutex.WaitOne();
                _thumbIndex = (ThumbnailQueue.Count > 0) ? ThumbnailQueue[0] : -1;
                ThumbnailMutex.ReleaseMutex();

                if ((_thumbIndex >= 0) && (CurrentArchive != null))
                {
                    EQArchiveFile _file = _files[_thumbIndex];

                    Image _image = _file.GetImage();

                    ListViewQueue.Enqueue(_thumbIndex);

                    try
                    {
                        ThumbnailMutex.WaitOne();
                        ThumbnailQueue.RemoveAt(0);
                        ThumbnailMutex.ReleaseMutex();
                    }
                    catch { }
                }
            } while (!threadListView.CancellationPending && ((ThumbnailQueue.Count > 0) || threadThumbnails.IsBusy));

            if (threadListView.CancellationPending)
            {
                threadThumbnails.CancelAsync();

                while (threadThumbnails.IsBusy)
                {
                    Thread.Sleep(1);
                }
            }

            _files = null;

            ThumbnailsLoaded = true;

            ThumbnailPerf[0].Stop();
        }
Ejemplo n.º 17
0
        public Result Remove(EQArchiveFile File)
        {
            if (File == null)
            {
                return Result.FileNotFound;
            }

            this.Files.RemoveAt(this.Files.IndexOfValue(File));

            this.IsDirty = true;

            return Result.OK;
        }
Ejemplo n.º 18
0
        private void threadThumbnails_DoWork(object sender, DoWorkEventArgs e)
        {
            ThumbnailPerf[1] = new System.Diagnostics.Stopwatch();
            ThumbnailPerf[1].Start();

            int _fileCount;
            EQArchiveFile[] _files = null;

            ThumbnailMutex.WaitOne();

            if (CurrentArchive != null)
            {
                _fileCount = CurrentArchive.Files.Count;

                if (_fileCount > 0)
                {
                    _files = new EQArchiveFile[_fileCount];
                    CurrentArchive.Files.Values.CopyTo(_files, 0);
                }
            }
            else
            {
                _fileCount = 0;
            }

            ThumbnailMutex.ReleaseMutex();

            if (_fileCount < 1)
            {
                ThumbnailPerf[1].Stop();
                return;
            }

            threadDecompress.RunWorkerAsync(_files);

            int _decompressed = 0;
            int _last = (_fileCount - 1);

            do
            {
                DecompressMutex.WaitOne();
                if ((_decompressed = (DecompressQueue.Count == 0) ? -1 : DecompressQueue[0]) >= 0)
                {
                    DecompressQueue.RemoveAt(0);
                }
                DecompressMutex.ReleaseMutex();

                if (_decompressed >= 0)
                {
                    EQArchiveFile _file = _files[_decompressed];

                    Image _image = _file.GetImage();

                    _file.SetThumbnail(GetSquareImage(_image));
                    _file = null;

                    ThumbnailMutex.WaitOne();
                    ThumbnailQueue.Add(_decompressed);
                    ThumbnailMutex.ReleaseMutex();
                }
                else
                {
                    Thread.Sleep(1);
                }
            } while (!threadThumbnails.CancellationPending && ((DecompressQueue.Count > 0) || threadDecompress.IsBusy));

            if (threadThumbnails.CancellationPending)
            {
                threadDecompress.CancelAsync();

                while (threadDecompress.IsBusy)
                {
                    Thread.Sleep(1);
                }
            }

            ThumbnailPerf[1].Stop();

            e.Result = threadThumbnails.CancellationPending ? DialogResult.Cancel : DialogResult.OK;
        }
Ejemplo n.º 19
0
        public EQArchiveFile AsFormat(string NewFormat, bool ChangeExtension)
        {
            if ((NewFormat == null) || (NewFormat == "") || (this.GetImage() == null))
            {
                return this;
            }

            NewFormat = NewFormat.ToLower();

            if (NewFormat == "auto")
            {
                switch (GetAlphaBits())
                {
                    case 0:
                    case 1:
                        NewFormat = "16-bit";
                        break;

                    case 8:
                        NewFormat = "32-bit";
                        break;

                    default: // ?
                        NewFormat = "32-bit";
                        break;
                }
            }

            EQArchiveFile _newFile = null;

            if (NewFormat != this.ImageFormat)
            {
                _newFile = new EQArchiveFile();
                _newFile.Filename = this.Filename;
                _newFile.SetImage(this.GetImage(), NewFormat);
            }

            if (ChangeExtension && !System.IO.Path.GetExtension(this.Filename).Equals((NewFormat[0] == '.' ? NewFormat : ".dds"), StringComparison.CurrentCultureIgnoreCase))
            {
                // Gotta change the extension

                if (_newFile == null)
                {
                    _newFile = new EQArchiveFile();
                    _newFile.SetContents(this.GetContents());
                }

                _newFile.Filename = System.IO.Path.GetFileNameWithoutExtension(this.Filename) + (NewFormat[0] == '.' ? NewFormat : ".dds");
            }
            else
            {
                if (_newFile == null)
                {
                    _newFile = this; // Unchanged from our current contents
                }
                else
                {
                    _newFile.Filename = this.Filename;
                }
            }

            return _newFile;
        }
Ejemplo n.º 20
0
 public Result Add(EQArchiveFile File)
 {
     return(this.Add(File, false));
 }