Esempio n. 1
0
        public void Deserialize(Stream input)
        {
            Endian endian;

            Package.HeaderV4 header;

            using (var data = input.ReadToMemoryStream(2048))
            {
                var magic = data.ReadValueU32(Endian.Little);
                if (magic != 0x51890ACE &&
                    magic.Swap() != 0x51890ACE)
                {
                    throw new FormatException("not a package file");
                }
                endian = magic == 0x51890ACE ? Endian.Little : Endian.Big;

                var version = data.ReadValueU32(endian);
                if (version != 4)
                {
                    throw new FormatException("unexpected package version (expected 4)");
                }

                header = new Package.HeaderV4();
                header.Deserialize(data, endian);
            }

            this.Entries.Clear();
            using (var directory = input.ReadToMemoryStream(header.DirectorySize.Align(2048)))
            {
                using (var names = input.ReadToMemoryStream(header.NamesSize.Align(2048)))
                {
                    using (var extensions = input.ReadToMemoryStream(header.ExtensionsSize.Align(2048)))
                    {
                        for (int i = 0; i < header.DirectoryCount; i++)
                        {
                            var nameOffset      = directory.ReadValueU32(endian);
                            var extensionOffset = directory.ReadValueU32(endian);
                            directory.Seek(4, SeekOrigin.Current); // runtime offset
                            var offset           = directory.ReadValueU32(endian);
                            var uncompressedSize = directory.ReadValueU32(endian);
                            var compressedSize   = directory.ReadValueU32(endian);
                            directory.Seek(4, SeekOrigin.Current); // package pointer

                            names.Seek(nameOffset, SeekOrigin.Begin);
                            extensions.Seek(extensionOffset, SeekOrigin.Begin);

                            var name = names.ReadStringZ(Encoding.ASCII);
                            name += "." + extensions.ReadStringZ(Encoding.ASCII);

                            this.Entries.Add(new Package.Entry()
                            {
                                Name             = name,
                                Offset           = offset,
                                UncompressedSize = uncompressedSize,
                                CompressedSize   = compressedSize,
                            });
                        }
                    }
                }
            }

            this.Endian           = endian;
            this.Flags            = ConvertFlags(header.Flags);
            this.UncompressedSize = header.UncompressedSize;
            this.CompressedSize   = header.CompressedSize;
            this.DataOffset       = input.Position;
        }
Esempio n. 2
0
        public void Serialize(Stream output)
        {
            var endian = this.Endian;

            var names      = new MemoryStream();
            var extensions = new MemoryStream();
            var directory  = new MemoryStream();

            var nameOffsets      = new Dictionary <string, uint>();
            var extensionOffsets = new Dictionary <string, uint>();

            foreach (var entry in this.Entries)
            {
                var name = Path.GetFileNameWithoutExtension(entry.Name);

                var extension = Path.GetExtension(entry.Name);
                if (extension != null && extension.StartsWith(".") == true)
                {
                    extension = extension.Substring(1);
                }

                uint nameOffset;
                if (nameOffsets.ContainsKey(name) == false)
                {
                    nameOffset = (uint)names.Position;
                    nameOffsets.Add(name, nameOffset);
                    names.WriteStringZ(name, Encoding.ASCII);
                }
                else
                {
                    nameOffset = nameOffsets[name];
                }

                uint extensionOffset;
                if (extensionOffsets.ContainsKey(extension) == false)
                {
                    extensionOffset = (uint)extensions.Position;
                    extensionOffsets.Add(extension, extensionOffset);
                    extensions.WriteStringZ(extension, Encoding.ASCII);
                }
                else
                {
                    extensionOffset = extensionOffsets[extension];
                }

                directory.WriteValueU32(nameOffset, endian);
                directory.WriteValueU32(extensionOffset, endian);
                directory.WriteValueU32(0, endian);
                directory.WriteValueU32(entry.Offset, endian);
                directory.WriteValueU32(entry.UncompressedSize, endian);
                directory.WriteValueU32(entry.CompressedSize, endian);
                directory.WriteValueU32(0, endian);
            }

            var header = new Package.HeaderV4();

            header.Name = "         Created using      Gibbed's     Volition Tools ";
            header.Path = "           Read the       Foundation     Novels from       Asimov.       I liked them. ";

            header.Flags = ConvertFlags(this.Flags);

            if (this.ExtraFlags != 0)
            {
                header.Flags |= (Package.HeaderFlagsV4) this.ExtraFlags;
            }

            header.DirectoryCount   = (uint)this.Entries.Count;
            header.PackageSize      = this.TotalSize;
            header.DirectorySize    = (uint)directory.Length;
            header.NamesSize        = (uint)names.Length;
            header.ExtensionsSize   = (uint)extensions.Length;
            header.UncompressedSize = this.UncompressedSize;
            header.CompressedSize   = (this.Flags & Package.HeaderFlags.Compressed) != 0 ?
                                      this.CompressedSize : 0xFFFFFFFF;

            directory.Seek(0, SeekOrigin.Begin);
            directory.SetLength(directory.Length.Align(2048));

            names.Seek(0, SeekOrigin.Begin);
            names.SetLength(names.Length.Align(2048));

            extensions.Seek(0, SeekOrigin.Begin);
            extensions.SetLength(extensions.Length.Align(2048));

            output.WriteValueU32(0x51890ACE, endian);
            output.WriteValueU32(4, endian);

            header.Serialize(output, endian);
            output.Seek(2048, SeekOrigin.Begin);
            output.WriteFromStream(directory, directory.Length);
            output.WriteFromStream(names, names.Length);
            output.WriteFromStream(extensions, extensions.Length);
        }