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); }
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); }