public void SaveChanges(IStream stream) { if (!_changed) { return; } var scenarioLayout = _buildInfo.Layouts.GetLayout("scnr"); stream.SeekTo(_scenario.MetaLocation.AsOffset()); var scenarioData = StructureReader.ReadStructure(stream, scenarioLayout); var oldCount = (int)scenarioData.GetInteger("simulation definition table count"); var oldAddress = (uint)scenarioData.GetInteger("simulation definition table address"); var entryLayout = _buildInfo.Layouts.GetLayout("simulation definition table element"); var newTable = _table.Select(SerializeTag); var newAddr = TagBlockWriter.WriteTagBlock(newTable, oldCount, oldAddress, _table.Count, entryLayout, _metaArea, _allocator, stream); scenarioData.SetInteger("simulation definition table count", (uint)_table.Count); scenarioData.SetInteger("simulation definition table address", (uint)newAddr); stream.SeekTo(_scenario.MetaLocation.AsOffset()); StructureWriter.WriteStructure(scenarioData, scenarioLayout, stream); _changed = false; }
/// <summary> /// Saves changes to the tag table. /// </summary> /// <param name="stream">The stream to write changes to.</param> public void SaveChanges(IStream stream) { StructureValueCollection headerValues = LoadHeader(stream); if (headerValues == null) { return; } SaveTags(headerValues, stream); if (Interops != null && Interops.Count > 0) { var oldCount = (int)headerValues.GetInteger("number of tag interops"); long oldAddress = (long)headerValues.GetInteger("tag interop table address"); StructureLayout layout = _buildInfo.Layouts.GetLayout("tag interop element"); IEnumerable <StructureValueCollection> entries = _interops.OrderBy(i => i.Pointer).Select(t => ((ThirdGenTagInterop)t).Serialize()); // hax long newAddress = TagBlockWriter.WriteTagBlock(entries, oldCount, oldAddress, _interops.Count, layout, _metaArea, _allocator, stream); headerValues.SetInteger("number of tag interops", (uint)_interops.Count); headerValues.SetInteger("tag interop table address", (ulong)newAddress); } SaveHeader(headerValues, stream); }
private void SaveDefinitionFixups(IList <ResourceDefinitionFixup> fixups, StructureValueCollection values, IStream stream, TagBlockCache <ResourceDefinitionFixup> cache) { var oldCount = (int)values.GetIntegerOrDefault("number of definition fixups", 0); uint oldAddress = (uint)values.GetIntegerOrDefault("definition fixup table address", 0); long oldExpand = _expander.Expand(oldAddress); StructureLayout layout = _buildInfo.Layouts.GetLayout("definition fixup element"); long newAddress; if (!cache.TryGetAddress(fixups, out newAddress)) { // Write a new block IEnumerable <StructureValueCollection> entries = fixups.Select(f => SerializeDefinitionFixup(f)); newAddress = TagBlockWriter.WriteTagBlock(entries, oldCount, oldExpand, fixups.Count, layout, _metaArea, _allocator, stream); cache.Add(newAddress, fixups); } else if (oldAddress != 0 && oldCount > 0) { // Block was cached - just free it _allocator.Free(oldExpand, oldCount * layout.Size); } uint cont = _expander.Contract(newAddress); values.SetInteger("number of definition fixups", (uint)fixups.Count); values.SetInteger("definition fixup table address", cont); }
public void SavePages(ICollection <ResourcePage> pages, ICollection <ResourcePointer> pointers, IStream stream) { StructureValueCollection values = LoadTag(stream); ThirdGenCacheFileReference[] files = LoadExternalFiles(values, stream); StructureLayout layout = _buildInfo.Layouts.GetLayout("raw page table element"); var oldCount = (int)values.GetInteger("number of raw pages"); uint oldAddress = (uint)values.GetInteger("raw page table address"); long expand = _expander.Expand(oldAddress); // recount asset count values for every page for predictions foreach (ResourcePage p in pages) { p.AssetCount = pointers.Count(x => x.PrimaryPage == p || x.SecondaryPage == p || x.TertiaryPage == p); } IEnumerable <StructureValueCollection> entries = pages.Select(p => SerializePage(p, files)); long newAddress = TagBlockWriter.WriteTagBlock(entries, oldCount, expand, pages.Count, layout, _metaArea, _allocator, stream); // Update values uint cont = _expander.Contract(newAddress); values.SetInteger("number of raw pages", (uint)pages.Count); values.SetInteger("raw page table address", cont); SaveTag(values, stream); }
private void SaveSizeParts(IList <ResourceSizePart> parts, StructureValueCollection values, IStream stream, TagBlockCache <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 element"); long newAddress; if (!cache.TryGetAddress(parts, out newAddress)) { // Write a new block IEnumerable <StructureValueCollection> entries = parts.Select(p => SerializeSizePart(p)); newAddress = TagBlockWriter.WriteTagBlock(entries, oldCount, expand, parts.Count, layout, _metaArea, _allocator, stream); cache.Add(newAddress, parts); } else if (oldAddress != 0 && oldCount > 0) { // Block 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 TagBlockCache <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 element"); 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 = TagBlockWriter.WriteTagBlock(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); }
private void SaveTags(StructureValueCollection headerValues, int offset, IStream stream) { StructureLayout layout = _buildInfo.Layouts.GetLayout("tag element"); IEnumerable <StructureValueCollection> entries = _tags.Select(t => ((SecondGenTag)t).Serialize()); var addr = _metaArea.OffsetToPointer(_metaArea.Offset + offset); TagBlockWriter.WriteTagBlock(entries, addr, layout, _metaArea, stream); headerValues.SetInteger("number of tags", (uint)_tags.Count); headerValues.SetInteger("tag table offset", (uint)offset); }
private int SaveGroups(StructureValueCollection headerValues, int offset, IStream stream) { StructureLayout layout = _buildInfo.Layouts.GetLayout("tag group element"); IEnumerable <StructureValueCollection> entries = _groups.Select(g => ((SecondGenTagGroup)g).Serialize()); var addr = _metaArea.OffsetToPointer(_metaArea.Offset + offset); TagBlockWriter.WriteTagBlock(entries, addr, layout, _metaArea, stream); headerValues.SetInteger("number of tag groups", (uint)_groups.Count); headerValues.SetInteger("tag group table offset", (uint)offset); return(Groups.Count * layout.Size); }
private void SaveTags(StructureValueCollection headerValues, IStream stream) { var oldCount = (int)headerValues.GetInteger("number of tags"); long oldAddress = (long)headerValues.GetInteger("tag table address"); StructureLayout layout = _buildInfo.Layouts.GetLayout("tag element"); IEnumerable <StructureValueCollection> entries = _tags.Select(t => ((ThirdGenTag)t).Serialize(Groups, _expander)); // hax, _tags is a list of ITag objects so we have to upcast long newAddress = TagBlockWriter.WriteTagBlock(entries, oldCount, oldAddress, _tags.Count, layout, _metaArea, _allocator, stream); headerValues.SetInteger("number of tags", (uint)_tags.Count); headerValues.SetInteger("tag table address", (ulong)newAddress); }
public void SavePointers(ICollection <ResourcePointer> pointers, IStream stream) { StructureValueCollection values = LoadTag(stream); StructureLayout layout = _buildInfo.Layouts.GetLayout("raw segment table element"); var oldCount = (int)values.GetInteger("number of raw segments"); uint oldAddress = (uint)values.GetInteger("raw segment table address"); long expand = _expander.Expand(oldAddress); IEnumerable <StructureValueCollection> entries = pointers.Select(p => SerializePointer(p)); long newAddress = TagBlockWriter.WriteTagBlock(entries, oldCount, expand, pointers.Count, layout, _metaArea, _allocator, stream); // Update values uint cont = _expander.Contract(newAddress); values.SetInteger("number of raw segments", (uint)pointers.Count); values.SetInteger("raw segment table address", cont); SaveTag(values, stream); }
private void SaveZoneSetTable(IZoneSet[] sets, StructureValueCollection tagValues, string countName, string addressName, TagBlockCache <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(); TagBlockWriter.WriteTagBlock(entries, expand, layout, _metaArea, stream); }
public IList <ResourcePointer> SaveResources(ICollection <Resource> resources, IStream stream) { StructureValueCollection values = LoadTag(stream); StructureLayout layout = _buildInfo.Layouts.GetLayout("resource table element"); FreeResources(values, stream); FreeInfoBuffer(values); // Serialize each resource element // This can't be lazily evaluated because allocations might cause the stream to expand int infoOffset = 0; int altInfoOffset = 0; var infocache = new TagBlockCache <int>(); var pointers = new List <ResourcePointer>(); var entries = new List <StructureValueCollection>(); var fixupCache = new TagBlockCache <ResourceFixup>(); var defFixupCache = new TagBlockCache <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 element"); if (size > 0) { long newBlockAddress; // Write a new block IEnumerable <StructureValueCollection> infoentries = offsets.Select(f => SerializeInfos(f)); newBlockAddress = TagBlockWriter.WriteTagBlock(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 block and update the tag values long newAddress = TagBlockWriter.WriteTagBlock(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 void SavePredictions(ICollection <ResourcePredictionD> predictions, IStream stream) { StructureValueCollection values = LoadTag(stream); FreePredictions(values); var dentries = new List <StructureValueCollection>(); var centries = new List <StructureValueCollection>(); var bentries = new List <StructureValueCollection>(); var aentries = new List <StructureValueCollection>(); var writtenc = new Dictionary <long, int>(); //hash, index var writtenb = new Dictionary <long, int>(); int firstnullc = -1; DatumIndex currenttag = DatumIndex.Null; foreach (ResourcePredictionD pred in predictions) { long dchash = pred.GetCHash(); int dcstart = centries.Count(); int dastart = aentries.Count; if (pred.CEntries.Count > 0) { int exist; bool found = writtenc.TryGetValue(dchash, out exist); if (!found) { foreach (ResourcePredictionC pc in pred.CEntries) { long cbhash = pc.GetBHash(); int cbstart = bentries.Count; int bexist; bool bfound = writtenb.TryGetValue(cbhash, out bexist); if (!bfound) { int bkstart = aentries.Count(); foreach (ResourcePredictionA pa in pc.BEntry.AEntries) { aentries.Add(SerializePredictionA(pa, stream)); } writtenb[cbhash] = cbstart; bentries.Add(SerializePredictionB(pc.BEntry, bkstart, cbstart, stream)); } else { cbstart = bexist; } writtenc[dchash] = dcstart; centries.Add(SerializePredictionC(pc, cbstart, cbstart, stream)); } } else { dcstart = exist; } } else { if (firstnullc == -1) { firstnullc = dcstart; } else { dcstart = firstnullc; } } if (pred.AEntries.Count > 0) { foreach (ResourcePredictionA pa in pred.AEntries) { aentries.Add(SerializePredictionA(pa, stream)); } } else { dastart = -1; } dentries.Add(SerializePredictionD(pred, dcstart, dastart, stream)); } // a StructureLayout alayout = _buildInfo.Layouts.GetLayout("prediction a element"); long newa = TagBlockWriter.WriteTagBlock(aentries, alayout, _metaArea, _allocator, stream); uint conta = _expander.Contract(newa); values.SetInteger("number of prediction as", (uint)aentries.Count); values.SetInteger("prediction a table address", conta); // b StructureLayout blayout = _buildInfo.Layouts.GetLayout("prediction b element"); long newb = TagBlockWriter.WriteTagBlock(bentries, blayout, _metaArea, _allocator, stream); uint contb = _expander.Contract(newb); values.SetInteger("number of prediction bs", (uint)bentries.Count); values.SetInteger("prediction b table address", contb); // cc StructureLayout clayout = _buildInfo.Layouts.GetLayout("prediction c element"); long newc = TagBlockWriter.WriteTagBlock(centries, clayout, _metaArea, _allocator, stream); uint contc = _expander.Contract(newc); values.SetInteger("number of prediction cs", (uint)centries.Count); values.SetInteger("prediction c table address", contc); // d StructureLayout dlayout = _buildInfo.Layouts.GetLayout("prediction d element"); long newd = TagBlockWriter.WriteTagBlock(dentries, dlayout, _metaArea, _allocator, stream); uint contd = _expander.Contract(newd); values.SetInteger("number of prediction ds", (uint)dentries.Count); values.SetInteger("prediction d table address", contd); // d2 StructureLayout d2layout = _buildInfo.Layouts.GetLayout("prediction d2 element"); long newd2 = TagBlockWriter.WriteTagBlock(dentries, d2layout, _metaArea, _allocator, stream); uint contd2 = _expander.Contract(newd2); values.SetInteger("number of prediction d2s", (uint)dentries.Count); values.SetInteger("prediction d2 table address", contd2); SaveTag(values, stream); }