private void SaveDefinitionFixups(IList <ResourceDefinitionFixup> fixups, StructureValueCollection values, IStream stream, ReflexiveCache <ResourceDefinitionFixup> cache) { var oldCount = (int)values.GetIntegerOrDefault("number of definition fixups", 0); uint oldAddress = values.GetIntegerOrDefault("definition fixup table address", 0); StructureLayout layout = _buildInfo.Layouts.GetLayout("definition fixup entry"); uint newAddress; if (!cache.TryGetAddress(fixups, out newAddress)) { // Write a new reflexive IEnumerable <StructureValueCollection> entries = fixups.Select(f => SerializeDefinitionFixup(f)); newAddress = ReflexiveWriter.WriteReflexive(entries, oldCount, oldAddress, fixups.Count, layout, _metaArea, _allocator, stream); cache.Add(newAddress, fixups); } else if (oldAddress != 0 && oldCount > 0) { // Reflexive was cached - just free it _allocator.Free(oldAddress, oldCount * layout.Size); } values.SetInteger("number of definition fixups", (uint)fixups.Count); values.SetInteger("definition fixup table address", newAddress); }
private void SaveSizeParts(IList <ResourceSizePart> parts, StructureValueCollection values, IStream stream, ReflexiveCache <ResourceSizePart> cache) { var oldCount = (int)values.GetIntegerOrDefault("number of size parts", 0); uint oldAddress = (uint)values.GetIntegerOrDefault("size part table address", 0); long expand = _expander.Expand(oldAddress); StructureLayout layout = _buildInfo.Layouts.GetLayout("size part table entry"); long newAddress; if (!cache.TryGetAddress(parts, out newAddress)) { // Write a new reflexive IEnumerable <StructureValueCollection> entries = parts.Select(p => SerializeSizePart(p)); newAddress = ReflexiveWriter.WriteReflexive(entries, oldCount, expand, parts.Count, layout, _metaArea, _allocator, stream); cache.Add(newAddress, parts); } else if (oldAddress != 0 && oldCount > 0) { // Reflexive was cached - just free it _allocator.Free(expand, oldCount * layout.Size); } uint cont = _expander.Contract(newAddress); values.SetInteger("number of size parts", (uint)parts.Count); values.SetInteger("size part table address", cont); }
public void SaveSizes(ICollection <ResourceSize> sizes, IStream stream) { StructureValueCollection values = LoadTag(stream); var entries = new List <StructureValueCollection>(); var partCache = new ReflexiveCache <ResourceSizePart>(); foreach (ResourceSize size in sizes) { StructureValueCollection entry = SerializeSize(size); entries.Add(entry); SaveSizeParts(size.Parts, entry, stream, partCache); } StructureLayout layout = _buildInfo.Layouts.GetLayout("raw size table entry"); var oldCount = (int)values.GetInteger("number of raw sizes"); uint oldAddress = (uint)values.GetInteger("raw size table address"); long expand = _expander.Expand(oldAddress); long newAddress = ReflexiveWriter.WriteReflexive(entries, oldCount, expand, sizes.Count, layout, _metaArea, _allocator, stream); // Update values uint cont = _expander.Contract(newAddress); values.SetInteger("number of raw sizes", (uint)sizes.Count); values.SetInteger("raw size table address", cont); SaveTag(values, stream); }
public IList <ResourcePointer> SaveResources(ICollection <Resource> resources, IStream stream) { StructureValueCollection values = LoadTag(stream); // Free everything FreeResources(values, stream); // Serialize each resource entry // This can't be lazily evaluated because allocations might cause the stream to expand int infoOffset = 0; var pointers = new List <ResourcePointer>(); var entries = new List <StructureValueCollection>(); var fixupCache = new ReflexiveCache <ResourceFixup>(); var defFixupCache = new ReflexiveCache <ResourceDefinitionFixup>(); foreach (Resource resource in resources) { infoOffset = AlignInfoBlockOffset(resource, infoOffset); StructureValueCollection entry = SerializeResource(resource, (resource.Location != null) ? pointers.Count : -1, (resource.Info != null) ? infoOffset : 0, stream); entries.Add(entry); // Save fixups SaveResourceFixups(resource.ResourceFixups, entry, stream, fixupCache); SaveDefinitionFixups(resource.DefinitionFixups, entry, stream, defFixupCache); // Update info offset and pointer info if (resource.Info != null) { infoOffset += resource.Info.Length; } if (resource.Location != null) { pointers.Add(resource.Location); } } // Write the reflexive and update the tag values StructureLayout layout = _buildInfo.Layouts.GetLayout("resource table entry"); uint newAddress = ReflexiveWriter.WriteReflexive(entries, layout, _metaArea, _allocator, stream); values.SetInteger("number of resources", (uint)entries.Count); values.SetInteger("resource table address", newAddress); // Build and save the info buffer byte[] infoBuffer = BuildResourceInfoBuffer(resources); SaveResourceInfoBuffer(infoBuffer, values, stream); SaveTag(values, stream); return(pointers); }
public IList<ResourcePointer> SaveResources(ICollection<Resource> resources, IStream stream) { StructureValueCollection values = LoadTag(stream); // Free everything FreeResources(values, stream); // Serialize each resource entry // This can't be lazily evaluated because allocations might cause the stream to expand int infoOffset = 0; var pointers = new List<ResourcePointer>(); var entries = new List<StructureValueCollection>(); var fixupCache = new ReflexiveCache<ResourceFixup>(); var defFixupCache = new ReflexiveCache<ResourceDefinitionFixup>(); foreach (Resource resource in resources) { infoOffset = AlignInfoBlockOffset(resource, infoOffset); StructureValueCollection entry = SerializeResource(resource, (resource.Location != null) ? pointers.Count : -1, (resource.Info != null) ? infoOffset : 0, stream); entries.Add(entry); // Save fixups SaveResourceFixups(resource.ResourceFixups, entry, stream, fixupCache); SaveDefinitionFixups(resource.DefinitionFixups, entry, stream, defFixupCache); // Update info offset and pointer info if (resource.Info != null) infoOffset += resource.Info.Length; if (resource.Location != null) pointers.Add(resource.Location); } // Write the reflexive and update the tag values StructureLayout layout = _buildInfo.Layouts.GetLayout("resource table entry"); uint newAddress = ReflexiveWriter.WriteReflexive(entries, layout, _metaArea, _allocator, stream); values.SetInteger("number of resources", (uint) entries.Count); values.SetInteger("resource table address", newAddress); // Build and save the info buffer byte[] infoBuffer = BuildResourceInfoBuffer(resources); SaveResourceInfoBuffer(infoBuffer, values, stream); SaveTag(values, stream); return pointers; }
/// <summary> /// Saves changes made to zone sets in the table. /// </summary> /// <param name="stream">The stream to write to.</param> /// <exception cref="System.NotImplementedException"></exception> public void SaveChanges(IStream stream) { StructureValueCollection tagValues = _gestalt.LoadTag(stream); FreeZoneSets(tagValues, stream); var cache = new ReflexiveCache<int>(); SaveZoneSetTable(GlobalZoneSet, tagValues, "number of global zone sets", "global zone set table address", cache, stream); SaveZoneSetTable(UnattachedZoneSet, tagValues, "number of unattached zone sets", "unattached zone set table address", cache, stream); SaveZoneSetTable(DiscForbiddenZoneSet, tagValues, "number of disc forbidden zone sets", "disc forbidden zone set table address", cache, stream); SaveZoneSetTable(DiscAlwaysStreamingZoneSet, tagValues, "number of disc always streaming zone sets", "disc always streaming zone set table address", cache, stream); SaveZoneSetTable(GeneralZoneSets, tagValues, "number of general zone sets", "general zone set table address", cache, stream); SaveZoneSetTable(BSPZoneSets, tagValues, "number of bsp zone sets", "bsp zone set table address", cache, stream); SaveZoneSetTable(BSPZoneSets2, tagValues, "number of bsp 2 zone sets", "bsp 2 zone set table address", cache, stream); SaveZoneSetTable(BSPZoneSets3, tagValues, "number of bsp 3 zone sets", "bsp 3 zone set table address", cache, stream); SaveZoneSetTable(CinematicZoneSets, tagValues, "number of cinematic zone sets", "cinematic zone set table address", cache, stream); SaveZoneSetTable(CustomZoneSets, tagValues, "number of custom zone sets", "custom zone set table address", cache, stream); _gestalt.SaveTag(tagValues, stream); }
/// <summary> /// Saves changes made to zone sets in the table. /// </summary> /// <param name="stream">The stream to write to.</param> /// <exception cref="System.NotImplementedException"></exception> public void SaveChanges(IStream stream) { StructureValueCollection tagValues = _gestalt.LoadTag(stream); FreeZoneSets(tagValues, stream); var cache = new ReflexiveCache <int>(); SaveZoneSetTable(GlobalZoneSet, tagValues, "number of global zone sets", "global zone set table address", cache, stream); SaveZoneSetTable(UnattachedZoneSet, tagValues, "number of unattached zone sets", "unattached zone set table address", cache, stream); SaveZoneSetTable(DiscForbiddenZoneSet, tagValues, "number of disc forbidden zone sets", "disc forbidden zone set table address", cache, stream); SaveZoneSetTable(DiscAlwaysStreamingZoneSet, tagValues, "number of disc always streaming zone sets", "disc always streaming zone set table address", cache, stream); SaveZoneSetTable(GeneralZoneSets, tagValues, "number of general zone sets", "general zone set table address", cache, stream); SaveZoneSetTable(BSPZoneSets, tagValues, "number of bsp zone sets", "bsp zone set table address", cache, stream); SaveZoneSetTable(BSPZoneSets2, tagValues, "number of bsp 2 zone sets", "bsp 2 zone set table address", cache, stream); SaveZoneSetTable(BSPZoneSets3, tagValues, "number of bsp 3 zone sets", "bsp 3 zone set table address", cache, stream); SaveZoneSetTable(CinematicZoneSets, tagValues, "number of cinematic zone sets", "cinematic zone set table address", cache, stream); SaveZoneSetTable(CustomZoneSets, tagValues, "number of custom zone sets", "custom zone set table address", cache, stream); _gestalt.SaveTag(tagValues, stream); }
private void SaveZoneSetTable(IZoneSet[] sets, StructureValueCollection tagValues, string countName, string addressName, ReflexiveCache <int> cache, IStream stream) { if (!tagValues.HasInteger(countName) || !tagValues.HasInteger(addressName)) { return; } var count = (int)tagValues.GetInteger(countName); if (count != sets.Length) { throw new InvalidOperationException("Zone set count does not match"); } uint address = (uint)tagValues.GetInteger(addressName); long expand = _expander.Expand(address); StructureLayout layout = _buildInfo.Layouts.GetLayout("zone set definition"); List <StructureValueCollection> entries = sets.Select(set => ((ThirdGenZoneSet)set).Serialize(stream, _allocator, cache, _expander)).ToList(); ReflexiveWriter.WriteReflexive(entries, expand, layout, _metaArea, stream); }
private void SaveZoneSetTable(IZoneSet set, StructureValueCollection tagValues, string countName, string addressName, ReflexiveCache <int> cache, IStream stream) { SaveZoneSetTable(new[] { set }, tagValues, countName, addressName, cache, stream); }
private void SaveResourceFixups(IList<ResourceFixup> fixups, StructureValueCollection values, IStream stream, ReflexiveCache<ResourceFixup> cache) { var oldCount = (int) values.GetIntegerOrDefault("number of resource fixups", 0); uint oldAddress = values.GetIntegerOrDefault("resource fixup table address", 0); StructureLayout layout = _buildInfo.Layouts.GetLayout("resource fixup entry"); uint newAddress; if (!cache.TryGetAddress(fixups, out newAddress)) { // Write a new reflexive IEnumerable<StructureValueCollection> entries = fixups.Select(f => SerializeResourceFixup(f)); newAddress = ReflexiveWriter.WriteReflexive(entries, oldCount, oldAddress, fixups.Count, layout, _metaArea, _allocator, stream); cache.Add(newAddress, fixups); } else if (oldAddress != 0 && oldCount > 0) { // Reflexive was cached - just free it _allocator.Free(oldAddress, oldCount*layout.Size); } values.SetInteger("number of resource fixups", (uint) fixups.Count); values.SetInteger("resource fixup table address", newAddress); }
private void SaveZoneSetTable(IZoneSet[] sets, StructureValueCollection tagValues, string countName, string addressName, ReflexiveCache<int> cache, IStream stream) { if (!tagValues.HasInteger(countName) || !tagValues.HasInteger(addressName)) return; var count = (int) tagValues.GetInteger(countName); if (count != sets.Length) throw new InvalidOperationException("Zone set count does not match"); uint address = tagValues.GetInteger(addressName); StructureLayout layout = _buildInfo.Layouts.GetLayout("zone set definition"); List<StructureValueCollection> entries = sets.Select(set => ((FourthGenZoneSet) set).Serialize(stream, _allocator, cache)).ToList(); ReflexiveWriter.WriteReflexive(entries, address, layout, _metaArea, stream); }
private void SaveBitArray(BitArray bits, string countName, string addressName, MetaAllocator allocator, IStream stream, ReflexiveCache <int> cache, StructureValueCollection values) { if (bits.Length == 0) { values.SetInteger(countName, 0); values.SetInteger(addressName, 0); return; } var ints = new int[((bits.Length + 31) & ~31) / 32]; bits.CopyTo(ints, 0); // If the address isn't cached, then allocate space and write a new array uint newAddress; if (!cache.TryGetAddress(ints, out newAddress)) { newAddress = allocator.Allocate(ints.Length * 4, stream); stream.SeekTo(_metaArea.PointerToOffset(newAddress)); foreach (int i in ints) { stream.WriteInt32(i); } cache.Add(newAddress, ints); } values.SetInteger(countName, (uint)ints.Length); values.SetInteger(addressName, newAddress); }
public StructureValueCollection Serialize(IStream stream, MetaAllocator allocator, ReflexiveCache <int> cache) { var result = new StructureValueCollection(); SaveBitArray(_activeResources, "number of raw pool bitfields", "raw pool bitfield table address", allocator, stream, cache, result); SaveBitArray(_unknownResources, "number of raw pool 2 bitfields", "raw pool 2 bitfield table address", allocator, stream, cache, result); SaveBitArray(_unknownResources2, "number of raw pool 3 bitfields", "raw pool 3 bitfield table address", allocator, stream, cache, result); SaveBitArray(_activeTags, "number of tag bitfields", "tag bitfield table address", allocator, stream, cache, result); SaveBitArray(_unknownTags, "number of tag 2 bitfields", "tag 2 bitfield table address", allocator, stream, cache, result); return(result); }
public IList <ResourcePointer> SaveResources(ICollection <Resource> resources, IStream stream) { StructureValueCollection values = LoadTag(stream); StructureLayout layout = _buildInfo.Layouts.GetLayout("resource table entry"); FreeResources(values, stream); FreeInfoBuffer(values); // Serialize each resource entry // This can't be lazily evaluated because allocations might cause the stream to expand int infoOffset = 0; int altInfoOffset = 0; var infocache = new ReflexiveCache <int>(); var pointers = new List <ResourcePointer>(); var entries = new List <StructureValueCollection>(); var fixupCache = new ReflexiveCache <ResourceFixup>(); var defFixupCache = new ReflexiveCache <ResourceDefinitionFixup>(); List <byte[]> paddedInfos = new List <byte[]>(); foreach (Resource resource in resources) { StructureValueCollection entry = SerializeResource(resource, (resource.Location != null) ? pointers.Count : -1, stream); entries.Add(entry); // Save fixups SaveResourceFixups(resource.ResourceFixups, entry, stream, fixupCache); SaveDefinitionFixups(resource.DefinitionFixups, entry, stream, defFixupCache); uint bits = (uint)entry.GetInteger("resource bits"); int size = (int)entry.GetInteger("resource info size"); List <int> offsets = new List <int>(); if (size > 0) { int dirtyoffset = infoOffset; infoOffset = AlignInfoBlockOffset(resource, infoOffset); offsets.Add(infoOffset); int padding = infoOffset - dirtyoffset; byte[] temp = new byte[padding + size]; Buffer.BlockCopy(resource.Info, 0, temp, padding, size); paddedInfos.Add(temp); infoOffset += size; } else { offsets.Add(0); } if ((bits & 2) > 0) { int tempalt = AlignInfoBlockOffset(resource, altInfoOffset); offsets.Add(tempalt); altInfoOffset += size; } else { offsets.Add(size > 0 ? -1 : 0); } if ((bits & 4) > 0) { int tempalt = AlignInfoBlockOffset(resource, altInfoOffset); offsets.Add(tempalt); altInfoOffset += size; } else { offsets.Add(size > 0 ? -1 : 0); } if (layout.HasField("number of resource info offsets")) { var oldCount = (int)entry.GetIntegerOrDefault("number of resource info offsets", 0); uint oldAddress = (uint)entry.GetIntegerOrDefault("resource info offsets table address", 0); long expand = _expander.Expand(oldAddress); StructureLayout infolayout = _buildInfo.Layouts.GetLayout("resource info offset entry"); if (size > 0) { long newBlockAddress; // Write a new reflexive IEnumerable <StructureValueCollection> infoentries = offsets.Select(f => SerializeInfos(f)); newBlockAddress = ReflexiveWriter.WriteReflexive(infoentries, oldCount, expand, offsets.Count, infolayout, _metaArea, _allocator, stream); infocache.Add(newBlockAddress, offsets); uint cont = _expander.Contract(newBlockAddress); entry.SetInteger("number of resource info offsets", (uint)offsets.Count); entry.SetInteger("resource info offsets table address", cont); } else { entry.SetInteger("number of resource info offsets", 0); entry.SetInteger("resource info offsets table address", 0); } } else { if (size > 0) { entry.SetInteger("resource info offset", (uint)offsets[0]); entry.SetInteger("alt resource info offset", (uint)offsets[1]); } else { entry.SetInteger("resource info offset", 0); entry.SetInteger("alt resource info offset", 0); } } // Update pointer info if (resource.Location != null) { pointers.Add(resource.Location); } } // Write the reflexive and update the tag values long newAddress = ReflexiveWriter.WriteReflexive(entries, layout, _metaArea, _allocator, stream); uint contr = _expander.Contract(newAddress); values.SetInteger("number of resources", (uint)entries.Count); values.SetInteger("resource table address", contr); // Save the info buffer SaveResourceInfoBuffer(paddedInfos.SelectMany(a => a).ToArray(), values, stream); SaveTag(values, stream); return(pointers); }
public StructureValueCollection Serialize(IStream stream, MetaAllocator allocator, ReflexiveCache<int> cache) { var result = new StructureValueCollection(); SaveBitArray(_activeResources, "number of raw pool bitfields", "raw pool bitfield table address", allocator, stream, cache, result); SaveBitArray(_unknownResources, "number of raw pool 2 bitfields", "raw pool 2 bitfield table address", allocator, stream, cache, result); SaveBitArray(_unknownResources2, "number of raw pool 3 bitfields", "raw pool 3 bitfield table address", allocator, stream, cache, result); SaveBitArray(_activeTags, "number of tag bitfields", "tag bitfield table address", allocator, stream, cache, result); SaveBitArray(_unknownTags, "number of tag 2 bitfields", "tag 2 bitfield table address", allocator, stream, cache, result); return result; }
private void SaveBitArray(BitArray bits, string countName, string addressName, MetaAllocator allocator, IStream stream, ReflexiveCache<int> cache, StructureValueCollection values) { if (bits.Length == 0) { values.SetInteger(countName, 0); values.SetInteger(addressName, 0); return; } var ints = new int[((bits.Length + 31) & ~31)/32]; bits.CopyTo(ints, 0); // If the address isn't cached, then allocate space and write a new array uint newAddress; if (!cache.TryGetAddress(ints, out newAddress)) { newAddress = allocator.Allocate(ints.Length*4, stream); stream.SeekTo(_metaArea.PointerToOffset(newAddress)); foreach (int i in ints) stream.WriteInt32(i); cache.Add(newAddress, ints); } values.SetInteger(countName, (uint)ints.Length); values.SetInteger(addressName, newAddress); }
private void SaveZoneSetTable(IZoneSet set, StructureValueCollection tagValues, string countName, string addressName, ReflexiveCache<int> cache, IStream stream) { SaveZoneSetTable(new[] {set}, tagValues, countName, addressName, cache, stream); }