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