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); }
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"); long expand = _expander.Expand(oldAddress); var entryLayout = _buildInfo.Layouts.GetLayout("simulation definition table entry"); var newTable = _table.Select(SerializeTag); var newAddr = ReflexiveWriter.WriteReflexive(newTable, oldCount, expand, _table.Count, entryLayout, _metaArea, _allocator, stream); uint cont = _expander.Contract(newAddr); scenarioData.SetInteger("simulation definition table count", (uint)_table.Count); scenarioData.SetInteger("simulation definition table address", cont); stream.SeekTo(_scenario.MetaLocation.AsOffset()); StructureWriter.WriteStructure(scenarioData, scenarioLayout, stream); _changed = false; }
private void SaveBitArray(BitArray bits, string countName, string addressName, MetaAllocator allocator, IStream stream, ReflexiveCache <int> cache, StructureValueCollection values, IPointerExpander expander) { if (bits.Length == 0) { values.SetInteger(countName, 0); values.SetInteger(addressName, 0); return; } var ints = bits.ToIntArray(); // If the address isn't cached, then allocate space and write a new array long 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); } uint cont = expander.Contract(newAddress); values.SetInteger(countName, (uint)ints.Length); values.SetInteger(addressName, cont); }
public StructureValueCollection Serialize(IList<ITagGroup> groupList, IPointerExpander expander) { var result = new StructureValueCollection(); uint cont = 0; if (MetaLocation != null) cont = expander.Contract(MetaLocation.AsPointer()); result.SetInteger("memory address", cont); result.SetInteger("tag group index", (Group != null) ? (uint) groupList.IndexOf(Group) : 0xFFFFFFFF); result.SetInteger("datum index salt", Index.Salt); return result; }
public StructureValueCollection Serialize(IList <ITagClass> classList, IPointerExpander expander) { var result = new StructureValueCollection(); uint cont = 0; if (MetaLocation != null) { cont = expander.Contract(MetaLocation.AsPointer()); } result.SetInteger("memory address", cont); result.SetInteger("class index", (Class != null) ? (uint)classList.IndexOf(Class) : 0xFFFFFFFF); result.SetInteger("datum index salt", Index.Salt); return(result); }
private void SaveData(IStream stream, EffectInteropType type) { long pointer; byte[] data; switch (type) { case EffectInteropType.Effect: pointer = _effePointer; data = _effe.SelectMany(a => a).ToArray(); break; case EffectInteropType.Beam: pointer = _beamPointer; data = _beam.SelectMany(a => a).ToArray(); break; case EffectInteropType.Contrail: pointer = _cntlPointer; data = _cntl.SelectMany(a => a).ToArray(); break; case EffectInteropType.LightVolume: pointer = _ltvlPointer; data = _ltvl.SelectMany(a => a).ToArray(); break; default: return; } var pointerLayout = _buildInfo.Layouts.GetLayout("data reference"); stream.SeekTo(_metaArea.PointerToOffset(pointer)); var pointerData = StructureReader.ReadStructure(stream, pointerLayout); var oldSize = (int)pointerData.GetInteger("size"); var oldAddress = (uint)pointerData.GetInteger("pointer"); var oldExpand = _expander.Expand(oldAddress); if (oldExpand >= 0 && oldSize > 0) { _allocator.Free(oldExpand, oldSize); } long newAddress = 0; if (data.Length > 0) { newAddress = _allocator.Allocate(data.Length, 0x10, stream); stream.SeekTo(_metaArea.PointerToOffset(newAddress)); stream.WriteBlock(data); } uint cont = _expander.Contract(newAddress); pointerData.SetInteger("size", (ulong)data.Length); pointerData.SetInteger("pointer", cont); stream.SeekTo(_metaArea.PointerToOffset(pointer)); StructureWriter.WriteStructure(pointerData, pointerLayout, stream); }
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); }
/// <summary> /// Frees the old Script Parameters and writes new ones to the stream. /// </summary> /// <param name="data">The new script data</param> /// <param name="stream">The stream to write to</param> /// <param name="scnr">scnr Meta Data</param> /// <returns>A dictionary containing the hashes of parameter groups an their new addresses.</returns> private Dictionary <int, uint> WriteParams(ScriptData data, IStream stream, StructureValueCollection scnr) { StructureLayout scrlayout = _buildInfo.Layouts.GetLayout("script element"); StructureLayout paramlayout = _buildInfo.Layouts.GetLayout("script parameter element"); int oldScriptCount = (int)scnr.GetInteger("number of scripts"); uint oldScriptAddress = (uint)scnr.GetInteger("script table address"); long expOldScriptAddress = _expander.Expand(oldScriptAddress); int oldParamSize = 0; StructureValueCollection[] oldScripts = TagBlockReader.ReadTagBlock(stream, oldScriptCount, expOldScriptAddress, scrlayout, _metaArea); HashSet <uint> freedParamAddresses = new HashSet <uint>(); int oldTotalParamCount = 0; // loop through old scripts for (int i = 0; i < oldScripts.Length; i++) { int paramCount = (int)oldScripts[i].GetInteger("number of parameters"); uint addr = (uint)oldScripts[i].GetInteger("address of parameter list"); oldTotalParamCount += paramCount; // free params if (addr != 0 && !freedParamAddresses.Contains(addr)) { long exp = _expander.Expand(addr); int blockSize = paramCount * paramlayout.Size; _allocator.Free(exp, blockSize); oldParamSize += blockSize; freedParamAddresses.Add(addr); } } int newTotalParamCount = 0; int newParamSize = 0; Dictionary <int, uint> newParamAddresses = new Dictionary <int, uint>(); // loop through new scripts foreach (var scr in data.Scripts) { int count = scr.Parameters.Count; if (count > 0) { int paramHash = SequenceHash.GetSequenceHashCode(scr.Parameters); if (!newParamAddresses.ContainsKey(paramHash)) { long newAddr = _allocator.Allocate(paramlayout.Size * count, stream); uint conNewAddr = _expander.Contract(newAddr); stream.SeekTo(_metaArea.PointerToOffset(newAddr)); // write params to stream foreach (var par in scr.Parameters) { par.Write(stream); } newParamAddresses.Add(paramHash, conNewAddr); newParamSize += scr.Parameters.Count * 36; } } newTotalParamCount += scr.Parameters.Count; } return(newParamAddresses); }