Ejemplo n.º 1
0
        public override void Export(String path, IProgressReport progress = null)
        {
            string filename;

            if (Directory.Exists(path))
            {
                filename = Path.Combine(path, this.Name);
            }
            else
            {
                filename = path;
            }

            if (progress != null)
            {
                progress.SetMessage("Extracting " + this.Name + ".");
            }

            using (FileStream file = File.Create(filename))
            {
                using (Stream stream = this.Data.GetStream())
                {
                    stream.CopyToCount(file, this.Data.GetSize(), progress);
                }
            }
        }
Ejemplo n.º 2
0
        public override void Export(String foldername, IProgressReport progress = null)
        {
            string filename;

            if (Directory.Exists(foldername))
            {
                filename = Path.Combine(foldername, this.Name);
            }
            else
            {
                filename = foldername;
            }

            if (progress != null)
            {
                progress.SetMessage("Extracting " + this.Name + ".");
            }

            switch (Properties.Settings.Default.ExportResourcesChoice)
            {
            case Settings.ExportResourcesChoice.RSC7:
            {
                using (FileStream file = File.Create(filename))
                {
                    using (BinaryWriter writer = new BinaryWriter(new StreamKeeper(file)))
                    {
                        // big endian resource 7 for now
                        writer.Write("RSC7".ToArray());
                        writer.Write(Structs.SwapEndian((uint)this.Version));
                        writer.Write(Structs.SwapEndian(this.SystemFlag));
                        writer.Write(Structs.SwapEndian(this.GraphicsFlag));
                    }

                    using (Stream stream = this.Data.GetStream())
                    {
                        stream.CopyToCount(file, this.Data.GetSize(), progress);
                    }
                }
                break;
            }

            case Settings.ExportResourcesChoice.SYSGFX:
            {
                if (progress != null)
                {
                    progress = new SubProgressReport(progress, (int)(this.SystemSize + this.GraphicsFlag));
                }
                using (Stream stream = this.Data.GetStream())
                {
                    // If there is no graphics information, no need to extract into two files
                    string sysExtension = this.GraphicSize == 0 ? "" : ".sys";
                    if (this.SystemSize != 0)
                    {
                        using (FileStream file = File.Create(filename + sysExtension))
                        {
                            stream.CopyToCount(file, this.SystemSize, progress == null ? null : new SubProgressReport(progress, 0, this.SystemSize));
                        }
                    }

                    if (this.GraphicSize != 0)
                    {
                        using (FileStream file = File.Create(filename + ".gfx"))
                        {
                            stream.CopyToCount(file, this.GraphicSize, progress == null ? null : new SubProgressReport(progress, this.SystemSize, (int)(this.SystemSize + this.GraphicsFlag)));
                        }
                    }
                }
                break;
            }

            case Settings.ExportResourcesChoice.RAW:
            {
                using (FileStream file = File.Create(filename))
                {
                    // Well, it isn't REALLY raw. We are rewriting it, so of the regular random-header, there are zeros,
                    //but it is close enough, that information is random anyway
                    this.Write(file);
                    if (progress != null)
                    {
                        progress.SetProgress(progress.GetFullValue());
                    }
                }
                break;
            }
            }
        }
Ejemplo n.º 3
0
 public void SetMessage(string message)
 {
     Parent.SetMessage(message);
 }
Ejemplo n.º 4
0
        /* TODO:
         * private void WriteDataInline(Stream stream, List<Entry> entries, Dictionary<Entry, Structs.RPF7EntryInfoTemplate> entriesInfo, int headersEnd)
         * {
         *  Range<FileEntry> oldFileLayout = new Range<FileEntry>(Math.Max(stream.Length, (long)headersEnd));
         *  List<FileEntry> emptyEntries = new List<FileEntry>();
         *  List<FileEntry> moveEntries = new List<FileEntry>();
         *  List<FileEntry> newEntries = new List<FileEntry>();
         *  // Entries that should be written to temporary files
         *  List<FileEntry> newSavedEntries = new List<FileEntry>();
         *
         *  // A dictionary of the raw data stream that we need to write to the file
         *  Dictionary<FileEntry, Stream> entriesStream = new Dictionary<FileEntry, System.IO.Stream>();
         *
         *  // Add the header
         *  oldFileLayout.AddItem(0, headersEnd, null);
         *
         *  foreach (Entry entry in entries)
         *  {
         *      FileEntry fentry = entry as FileEntry;
         *      if (fentry != null)
         *      {
         *
         *          // We need to find all the files that depends on the origianl stream first
         *          FileStreamCreator originalStream = fentry.TryGetOriginalFileStreamCreator();
         *          if (fentry.Data.GetSize() == 0 && fentry.IsRegularFile() && !((RegularFileEntry)fentry).Compressed)
         *          {
         *              emptyEntries.Add(fentry);
         *          }
         *          else if (originalStream != null && originalStream.FileStream == this.Stream)
         *          {
         *              if (originalStream.Offset < headersEnd) {
         *                  moveEntries.Add(fentry);
         *              }
         *              if (!oldFileLayout.AddItem(originalStream.Offset, originalStream.Size, fentry, false))
         *              {
         *                  // If failed for some reason.. well it can happen if two entries have the same data. Anyway I don't want that two entries will use the same data.
         *                  newSavedEntries.Add(fentry);
         *              }
         *              else
         *              {
         *                  entriesStream[fentry] = new PartialStream(this.Stream, originalStream.Offset, originalStream.Size);
         *              }
         *          }
         *          else if (fentry.Data is FileStreamCreator && ((FileStreamCreator)fentry.Data).FileStream == this.Stream)
         *          {
         *              // This file points to the original file, but something about it changed (compression, encryption, ..)
         *              newSavedEntries.Add(fentry);
         *          }
         *          // From here are entries that are not depends on the original strema
         *          else if ((fentry.IsRegularFile() && ((RegularFileEntry)fentry).Compressed) || fentry.IsResource())
         *          {
         *              newSavedEntries.Add(fentry);
         *          }
         *          else
         *          {
         *              entriesStream[fentry] = fentry.Data.GetStream();
         *              newEntries.Add(fentry);
         *          }
         *      }
         *  }
         *
         *  foreach (FileEntry entry in newSavedEntries)
         *  {
         *      string filepath = Path.GetTempFileName();
         *      // Let's copy the file to temp folder, this file will be deleted on close
         *      FileStream writeStream = new FileStream(filepath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete, 0x1000, FileOptions.DeleteOnClose);
         *
         *      entry.Data.GetStream().CopyTo(writeStream);
         *
         *      // Take an handle to the file, so it will be delete only when this handle will be closed.
         *      FileStream readStream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
         *      writeStream.Close();
         *
         *      entriesStream[entry] = writeStream;
         *  }
         *
         *  Range<FileEntry> newFileLayout = new Range<FileEntry>();
         * }
         */

        public void Write(Stream stream, IProgressReport progressReport = null)
        {
            if (progressReport != null)
            {
                progressReport.SetMessage("Preparing...");
                progressReport.SetProgress(-1);
            }
            if (this.Filename == "")
            {
                throw new Exception("Can't save");
            }
            // Get all the entries
            List <Entry> entries = new List <Entry>();

            this.Root.AddToList(entries);


            Dictionary <Entry, Structs.RPF7EntryInfoTemplate> entriesInfo = new Dictionary <Entry, Structs.RPF7EntryInfoTemplate>();

            foreach (Entry entry in entries)
            {
                Structs.RPF7EntryInfoTemplate entryInfo = new Structs.RPF7EntryInfoTemplate();
                // update the is resource field
                entryInfo.Field1   = (entry is ResourceEntry) ? 1U : 0U;
                entriesInfo[entry] = entryInfo;
            }

            int    shiftNameAccessBy;
            Stream names = WriteNames(entries, entriesInfo, out shiftNameAccessBy);

            // Fill the header
            Info.EntriesCount       = entries.Count;
            Info.ShiftNameAccessBy  = shiftNameAccessBy;
            Info.EntriesNamesLength = (int)names.Length;

            // Go to current position
            stream.Seek(0x10 + 0x10 * Info.EntriesCount + Info.EntriesNamesLength, SeekOrigin.Begin);

            // align to 0x200
            if (stream.Position % (1 << 9) != 0)
            {
                stream.Write(new byte[(1 << 9) - ((int)stream.Position % (1 << 9))], 0, (1 << 9) - ((int)stream.Position % (1 << 9)));
            }
            WriteData(stream, entries, entriesInfo, progressReport);

            long end = stream.Position;

            using (Stream writer = AES.EncryptStream(new StreamKeeper(stream), sixteenRoundsDecrypt))
            {
                int currentFreeIndex = 1;
                // Last finish to build and write the file
                stream.Seek(0, SeekOrigin.Begin);
                Info.Write(stream);
                Queue <Entry> entriesToProcess = new Queue <Entry>();
                entriesToProcess.Enqueue(this.Root);
                while (entriesToProcess.Count > 0)
                {
                    Entry entry = entriesToProcess.Dequeue();
                    if (entry is DirectoryEntry)
                    {
                        Structs.RPF7EntryInfoTemplate entryInfo = entriesInfo[entry];
                        IList <Entry> subentries = (entry as DirectoryEntry).GetEntries();
                        // Update the info on the sub entries
                        entryInfo.Field5   = (uint)currentFreeIndex;
                        entryInfo.Field6   = (uint)subentries.Count;
                        entriesInfo[entry] = entryInfo;
                        // Process the sub entries
                        foreach (Entry subentry in subentries)
                        {
                            entriesToProcess.Enqueue(subentry);
                        }
                        currentFreeIndex += subentries.Count;
                    }
                    // Write the entry info
                    entriesInfo[entry].Write(writer);
                }

                // Write names
                names.Seek(0, SeekOrigin.Begin);
                names.CopyTo(writer);
            }

            // Seek to end
            stream.Seek(end, SeekOrigin.Begin);
            // Done!
        }