Example #1
0
        public void Deserialize(Stream input)
        {
            if (input.ReadValueU32() != 0x57325243) // 'W2RC' -> Witcher 2 Resource?
            {
                throw new FormatException();
            }

            this.Version = input.ReadValueU32();
            if (this.Version < 83 || this.Version > 115)
            {
                throw new FormatException();
            }

            // ReSharper disable UnusedVariable
            var flags = input.ReadValueU32();
            // ReSharper restore UnusedVariable

            var  nameDataOffset       = input.ReadValueU32();
            var  nameCount            = input.ReadValueU32();
            var  objectDataOffset     = input.ReadValueU32();
            var  objectCount          = input.ReadValueU32();
            var  linkDataOffset       = input.ReadValueU32();
            var  linkCount            = input.ReadValueU32();
            uint dependencyDataOffset = 0;
            uint dependencyCount      = 0;

            if (this.Version >= 46)
            {
                dependencyDataOffset = input.ReadValueU32();
                dependencyCount      = input.ReadValueU32();
            }

            var info = new Resource.Info
            {
                Names = new string[nameCount],
            };

            if (nameCount > 0)
            {
                input.Seek(nameDataOffset, SeekOrigin.Begin);
                for (uint i = 0; i < nameCount; i++)
                {
                    info.Names[i] = input.ReadEncodedString();
                }
            }

            info.Links = new Resource.LinkInfo[linkCount];
            if (linkCount > 0)
            {
                input.Seek(linkDataOffset, SeekOrigin.Begin);

                for (uint i = 0; i < linkCount; i++)
                {
                    // ReSharper disable UseObjectOrCollectionInitializer
                    var link = new Resource.LinkInfo();
                    // ReSharper restore UseObjectOrCollectionInitializer
                    link.FileName = input.ReadEncodedStringW();
                    link.Unknown1 = input.ReadValueU16();
                    link.Unknown2 = input.ReadValueU16();
                    info.Links[i] = link;
                }
            }

            this.Dependencies.Clear();
            if (dependencyCount > 1)
            {
                input.Seek(dependencyDataOffset, SeekOrigin.Begin);

                for (uint i = 1; i < dependencyCount; i++)
                {
                    this.Dependencies.Add(input.ReadEncodedString());
                }
            }

            this.Objects = new List <Resource.ObjectInfo>();
            info.Objects = new Resource.ObjectInfo[objectCount];
            if (objectCount > 0)
            {
                input.Seek(objectDataOffset, SeekOrigin.Begin);

                var offsets = new Dictionary <Resource.ObjectInfo, ObjectLocation>();

                for (uint i = 0; i < objectCount; i++)
                {
                    var typeNameIndex = input.ReadValueS16();
                    if (typeNameIndex < 1 ||
                        typeNameIndex > info.Names.Length)
                    {
                        throw new FormatException();
                    }

                    var obj = new Resource.ObjectInfo
                    {
                        TypeName = info.Names[typeNameIndex - 1],
                    };

                    var parentIndex = input.ReadValueS32();

                    // ReSharper disable UseObjectOrCollectionInitializer
                    var location = new ObjectLocation();
                    // ReSharper restore UseObjectOrCollectionInitializer
                    location.Size   = input.ReadValueU32();
                    location.Offset = input.ReadValueU32();

                    obj.Flags         = input.ReadValueU32();
                    obj.TemplateIndex = input.ReadValueS32();
                    obj.Link          = this.Version < 102 ? null : input.ReadEncodedString();

                    obj.Data = TypeCache.Supports(obj.TypeName) == false
                                   ? new Resource.Dummy()
                                   : TypeCache.Instantiate(obj.TypeName);

                    info.Objects[i] = obj;
                    offsets.Add(obj, location);

                    if (parentIndex > 0)
                    {
                        var parent = info.Objects[parentIndex - 1];
                        if (parent.Children == null)
                        {
                            parent.Children = new List <Resource.ObjectInfo>();
                        }
                        parent.Children.Add(obj);
                        obj.Parent = parent;
                    }
                    else
                    {
                        obj.Parent = null;
                        this.Objects.Add(obj);
                    }
                }

                foreach (var obj in info.Objects)
                {
                    var location = offsets[obj];

                    input.Seek(location.Offset, SeekOrigin.Begin);

                    var data = new byte[location.Size];
                    input.Read(data, 0, data.Length);

                    using (var reader = new Resource.ResourceReader(info, data))
                    {
                        obj.Data.Serialize(reader);

                        if (reader.Position != reader.Length)
                        {
                            throw new FormatException();
                        }
                    }
                }
            }
        }
Example #2
0
        public void Deserialize(Stream input)
        {
            if (input.ReadValueU32() != 0x57325243) // 'W2RC' -> Witcher 2 Resource?
            {
                throw new FormatException();
            }

            this.Version = input.ReadValueU32();
            if (this.Version < 83 || this.Version > 115)
            {
                throw new FormatException();
            }

            var flags = input.ReadValueU32();

            var  nameDataOffset       = input.ReadValueU32();
            var  nameCount            = input.ReadValueU32();
            var  objectDataOffset     = input.ReadValueU32();
            var  objectCount          = input.ReadValueU32();
            var  linkDataOffset       = input.ReadValueU32();
            var  linkCount            = input.ReadValueU32();
            uint dependencyDataOffset = 0;
            uint dependencyCount      = 0;

            if (this.Version >= 46)
            {
                dependencyDataOffset = input.ReadValueU32();
                dependencyCount      = input.ReadValueU32();
            }

            var info = new Resource.Info();

            info.Names = new string[nameCount];
            if (nameCount > 0)
            {
                input.Seek(nameDataOffset, SeekOrigin.Begin);
                for (uint i = 0; i < nameCount; i++)
                {
                    info.Names[i] = input.ReadEncodedString();
                }
            }

            info.Links = new Resource.LinkInfo[linkCount];
            if (linkCount > 0)
            {
                input.Seek(linkDataOffset, SeekOrigin.Begin);

                for (uint i = 0; i < linkCount; i++)
                {
                    var link = new Resource.LinkInfo();
                    link.FileName = input.ReadEncodedStringW();
                    link.Unknown1 = input.ReadValueU16();
                    link.Unknown2 = input.ReadValueU16();
                    info.Links[i] = link;
                }
            }

            this.Dependencies.Clear();
            if (dependencyCount > 1)
            {
                input.Seek(dependencyDataOffset, SeekOrigin.Begin);

                info.Dependencies = new string[dependencyCount];
                for (uint i = 1; i < dependencyCount; i++)
                {
                    var path = input.ReadEncodedString();
                    info.Dependencies[i] = path;
                    this.Dependencies.Add(path);
                }
            }

            this.Objects = new List <Resource.ObjectInfo>();
            info.Objects = new Resource.ObjectInfo[objectCount];
            if (objectCount > 0)
            {
                input.Seek(objectDataOffset, SeekOrigin.Begin);

                var offsets = new Dictionary <Resource.ObjectInfo, ObjectLocation>();

                for (uint i = 0; i < objectCount; i++)
                {
                    var typeNameIndex = input.ReadValueS16();
                    if (typeNameIndex < 1 ||
                        typeNameIndex > info.Names.Length)
                    {
                        throw new FormatException();
                    }

                    var obj = new Resource.ObjectInfo();
                    obj.TypeName = info.Names[typeNameIndex - 1];

                    var parentIndex = input.ReadValueS32();

                    var location = new ObjectLocation();
                    location.Size   = input.ReadValueU32();
                    location.Offset = input.ReadValueU32();

                    obj.Flags    = input.ReadValueU32();
                    obj.Unknown5 = input.ReadValueU32();
                    obj.Link     = this.Version < 102 ? null : input.ReadEncodedString();

                    if (TypeCache.Supports(obj.TypeName) == false)
                    {
                        obj.Data = new GenericObject(obj.TypeName);
                    }
                    else
                    {
                        obj.Data = TypeCache.Instantiate(obj.TypeName);
                    }

                    info.Objects[i] = obj;
                    offsets.Add(obj, location);

                    if (obj.Unknown5 != 0)
                    {
                        throw new FormatException();
                    }

                    if (parentIndex > 0)
                    {
                        var parent = info.Objects[parentIndex - 1];
                        if (parent.Children == null)
                        {
                            parent.Children = new List <Resource.ObjectInfo>();
                        }
                        parent.Children.Add(obj);
                        obj.Parent = parent;
                    }
                    else
                    {
                        obj.Parent = null;
                        this.Objects.Add(obj);
                    }
                }

                foreach (var obj in info.Objects)
                {
                    var location = offsets[obj];

                    input.Seek(location.Offset, SeekOrigin.Begin);

                    var data = new byte[location.Size];
                    input.Read(data, 0, data.Length);

                    using (var reader = new Resource.ResourceReader(info, data))
                    {
                        obj.Data.Serialize(reader);

                        var bytesRemaining = reader.Length - reader.Position;
                        if (bytesRemaining > 0)
                        {
                            if (obj.Data is GenericObject)
                            {
                                byte[] undecodedData = new byte[bytesRemaining];
                                Array.Copy(data, reader.Position, undecodedData, 0, bytesRemaining);
                                ((GenericObject)obj.Data).UndecodedData = undecodedData;
                            }
                            else
                            {
                                throw new FormatException();
                            }
                        }
                    }
                }
            }
        }