Example #1
0
        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;
        }
Example #2
0
        /// <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);
        }
Example #7
0
        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);
        }
Example #8
0
        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);
        }
Example #9
0
        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);
        }
Example #11
0
        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);
        }