Beispiel #1
0
 /// <summary>
 /// Gets the number of files contained in the specifed ERF file.
 /// </summary>
 /// <param name="fileName">The name of the file</param>
 /// <returns>The number of files in the ERF</returns>
 public static int GetFileCount(string fileName)
 {
     using (FileStream reader = new FileStream(fileName, FileMode.Open))
     {
         // Read the header from the ERF and return the number of files.
         ErfHeader header = new ErfHeader(reader);
         return header.EntryCount;
     }
 }
Beispiel #2
0
        /// <summary>
        /// Saves the ERF file under the specified name.
        /// </summary>
        /// <param name="fileName">The name of the file.</param>
        public void SaveAs(string fileName)
        {
            NWNLogger.Log(0, "module.SaveAs entering [{0}]", fileName);
            // The ERF must be decompressed first unless it is a new ERF.
            if (keys.Length > 0 && string.Empty == decompressedPath)
                throw new NWNException("ERF must be decompressed to recreate");

            // Copy all of the modified files into the temp directory
            StringCollection replacedFiles = ReplacedFiles;
            NWNLogger.Log(0, "module.SaveAs copying {0} modified files into temp directory", replacedFiles.Count);
            foreach (string file in replacedFiles)
                File.Copy(file, Path.Combine(decompressedPath,
                    Path.GetFileName(file)), true);

            // Figure out the new number of files in the ERF and create new
            // key/resource arrays of the proper size.
            int fileCount = keys.Length + addedFileHash.Count - removedFiles.Count;
            NWNLogger.Log(0, "module.SaveAs {0} total files, allocating key/resource arrays", fileCount);
            ErfKey[] newKeys = new ErfKey[fileCount];
            ErfResource[] newResources = new ErfResource[fileCount];

            // Create a buffer to store the data.
            NWNLogger.Log(0, "module.SaveAs creating memory stream");
            MemoryStream buffer = new MemoryStream();

            // Copy all of the existing not-removed files into the new key/resource
            // arrays.
            int index = 0;
            for (int i = 0; i < keys.Length; i++)
            {
                string file = keys[i].FileName;
                if (string.Empty == file || removedFiles.Contains(file)) continue;

                // Copy the key/resource pair over.
            NWNLogger.Log(1, "module.SaveAs copying file[{0}] '{1}'", i, file);
                newKeys[index] = keys[i];
                newResources[index] = resources[i];

                // Read the file into the buffer.
                ReadFileIntoStream(Path.Combine(decompressedPath, file),
                    ref newResources[index], buffer);

                index++;
            }

            // Add all of the new files to the key/resource arrays.
            StringCollection addedFiles = AddedFiles;
            foreach (string file in addedFiles)
            {
            NWNLogger.Log(1, "module.SaveAs adding new file '{0}'", file);
                // SBH - depends on mode (NWN1 uses 1.0, 2 uses 1.1)
                if (NWNInfo.ModeNWN1)
                    newKeys[index] = new ErfKey(file, 1.0);
                else
                    newKeys[index] = new ErfKey(file, 1.1);

                newResources[index] = new ErfResource();

                // Read the file into the buffer.
                ReadFileIntoStream(file, ref newResources[index], buffer);
                index++;
            }

            // Figure out how big our descriptions are going to be.
            NWNLogger.Log(0, "module.SaveAs calcing description size");
            int descriptionsCount = 0;
            for (int i = 0; i < descriptions.Length; i++)
                descriptionsCount += descriptions[i].SizeInStream;

            // Create a new resource header and calculate the new offsets.
            NWNLogger.Log(0, "module.SaveAs creating header");
            ErfHeader newHeader = header;
            newHeader.OffsetToLocalizedString = Marshal.SizeOf(typeof(ErfHeader));
            newHeader.OffsetToKeyList = newHeader.OffsetToLocalizedString + descriptionsCount;
            newHeader.EntryCount = fileCount;
            //SBH - depends on mode
            if (NWNInfo.ModeNWN1)
                newHeader.OffsetToResourceList = newHeader.OffsetToKeyList +
                    (fileCount * ErfKey.SizeOf(1.0));
            else
                newHeader.OffsetToResourceList = newHeader.OffsetToKeyList +
                    (fileCount * ErfKey.SizeOf(1.1));

            // Calculate the offset to the beginning of the resource data and adjust
            // the offsets in the resource array to take this into account.
            NWNLogger.Log(0, "module.SaveAs calcing offsets");
            int offsetToData = newHeader.OffsetToResourceList +
                (fileCount * Marshal.SizeOf(typeof(ErfResource)));
            for (int i = 0; i < newResources.Length; i++)
                newResources[i].OffsetToResource += offsetToData;

            // Create the new file and write the data to it.
            NWNLogger.Log(0, "module.SaveAs creating output file");
            string newName = fileName + ".New";
            using (FileStream writer = new FileStream(newName, FileMode.Create,
                       FileAccess.Write, FileShare.Write))
            {
            NWNLogger.Log(0, "module.SaveAs writing header");
                newHeader.Serialize(writer);
            NWNLogger.Log(0, "module.SaveAs writing strings");
                ErfString.Serialize(writer, descriptions);
            NWNLogger.Log(0, "module.SaveAs writing keys");
                ErfKey.Serlialize(writer, newKeys);
            NWNLogger.Log(0, "module.SaveAs writing resources");
                ErfResource.Serlialize(writer, newResources);
            NWNLogger.Log(0, "module.SaveAs writing raw data");
                writer.Write(buffer.GetBuffer(), 0, (int) buffer.Length);

            NWNLogger.Log(0, "module.SaveAs flushing and closing");
                writer.Flush();
                writer.Close();
            }

            // Delete the old file and rename the new file to the proper name.
            NWNLogger.Log(0, "module.SaveAs copying over current file");
            File.Copy(newName, fileName, true);
            NWNLogger.Log(0, "module.SaveAs deleting");
            File.Delete(newName);

            // Update the ERF's field's with the new values.
            NWNLogger.Log(0, "module.SaveAs updating object definition");
            header = newHeader;
            keys = newKeys;
            resources = newResources;

            // Clear our string collections.
            replacedFileHash.Clear();
            addedFileHash.Clear();
            removedFiles.Clear();

            fileInfo = new FileInfo(fileName);
        }
Beispiel #3
0
        /// <summary>
        /// This method loads a single file from the specified erf, returning
        /// a MemoryStream containing the file's contents.
        /// </summary>
        /// <param name="erf">The erf containing the file</param>
        /// <param name="file">The file to load</param>
        /// <returns>A MemoryStream containing the file's data</returns>
        public static MemoryStream GetFile(string erf, string file)
        {
            // Open the erf file.
            NWNLogger.Log(0, "Erf.GetFile({0}, {1}) entering", erf, file);
            using (FileStream reader =
                       new FileStream(erf, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                // Read the header from the ERF
                ErfHeader header = new ErfHeader(reader);
                NWNLogger.Log(0, "Erf.GetFile({0}, {1}) has {2} files", erf, file, header.EntryCount);

                // Read the key (file) list from the ERF.
                reader.Seek(header.OffsetToKeyList, SeekOrigin.Begin);
                ErfKey[] keys = ErfKey.Deserialize(reader, header.EntryCount, header.Version);
                NWNLogger.Log(0, "Erf.GetFile({0}, {1}) read {2} keys", erf, file, keys.Length);

                // Read the resource (file) list from the ERF.
                reader.Seek(header.OffsetToResourceList, SeekOrigin.Begin);
                ErfResource[] resources = ErfResource.Deserialize(reader, header.EntryCount);
                NWNLogger.Log(0, "Erf.GetFile({0}, {1}) read {2} resources", erf, file, resources.Length);

                // Loop through all of the resources in the erf looking for the file.
                for (int i = 0; i < keys.Length; i++)
                {
                    // Check to see if this is the file we're looking for.
                    NWNLogger.Log(1, "Erf.GetFile('{0}', '{1}'), keys[{2}].FileName '{3}'", erf, file, i, keys[i].FileName);
                    //if (keys[i].FileName.ToLower() == file.ToLower())
                    if (0 == string.Compare(keys[i].FileName, file, true, CultureInfo.InvariantCulture))
                    {
                        NWNLogger.Log(1, "Erf.GetFile('{0}', '{1}'), match!", erf, file);
                        // We found our file, create a MemoryStream large enough to hold the file's
                        // data and load the data into the stream.
                        byte[] buffer = new Byte[resources[i].ResourceSize];
                        reader.Seek(resources[i].OffsetToResource, SeekOrigin.Begin);
                        reader.Read(buffer, 0, resources[i].ResourceSize);
                        NWNLogger.Log(1, "Erf.GetFile('{0}', '{1}'), creating MemoryStream from {2} bytes!", erf, file, buffer.Length);
                        return new MemoryStream(buffer, false);
                    }
                }

                return null;
            }
        }