Beispiel #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");

            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;
        }
Beispiel #2
0
        private List <ScriptGlobal> LoadGlobals(IReader reader, StructureValueCollection values)
        {
            int             count   = (int)values.GetInteger("number of script globals");
            uint            address = (uint)values.GetInteger("script global table address");
            long            expand  = _expander.Expand(address);
            StructureLayout layout  = _buildInfo.Layouts.GetLayout("script global element");

            StructureValueCollection[] entries = TagBlockReader.ReadTagBlock(reader, count, expand, layout, _metaArea);
            return(entries.Select(e => new ScriptGlobal(e, _stringIDs)).ToList());
        }
Beispiel #3
0
        private void Load(StructureValueCollection values, ushort index, FileSegmentGroup metaArea, IList <ITagClass> classList, IPointerExpander expander)
        {
            uint address = (uint)values.GetInteger("memory address");

            if (address != 0 && address != 0xFFFFFFFF)
            {
                long expanded = expander.Expand(address);

                MetaLocation = SegmentPointer.FromPointer(expanded, metaArea);
            }

            var classIndex = (int)values.GetInteger("class index");

            if (classIndex >= 0 && classIndex < classList.Count)
            {
                Class = classList[classIndex];
            }

            var salt = (ushort)values.GetInteger("datum index salt");

            if (salt != 0xFFFF)
            {
                Index = new DatumIndex(salt, index);
            }
            else
            {
                Index = DatumIndex.Null;
            }
        }
        private BitArray LoadBitArray(StructureValueCollection values, string countName, string addressName, IReader reader, IPointerExpander expander)
        {
            if (!values.HasInteger(countName) || !values.HasInteger(addressName))
            {
                return(new BitArray(0));
            }

            var  count   = (int)values.GetInteger(countName);
            uint address = (uint)values.GetInteger(addressName);

            if (count <= 0 || address == 0)
            {
                return(new BitArray(0));
            }

            long expand = expander.Expand(address);

            var ints = new int[count];

            reader.SeekTo(_metaArea.PointerToOffset(expand));
            for (int i = 0; i < count; i++)
            {
                ints[i] = reader.ReadInt32();
            }

            return(new BitArray(ints));
        }
        private IEnumerable <ThirdGenZoneSet> ReadZoneSetTable(StructureValueCollection tagValues, string countName, string addressName, IReader reader)
        {
            if (!tagValues.HasInteger(countName) || !tagValues.HasInteger(addressName))
            {
                return(Enumerable.Empty <ThirdGenZoneSet>());
            }

            var  count   = (int)tagValues.GetInteger(countName);
            uint address = (uint)tagValues.GetInteger(addressName);

            long expand = _expander.Expand(address);

            StructureLayout layout = _buildInfo.Layouts.GetLayout("zone set definition");

            StructureValueCollection[] entries = TagBlockReader.ReadTagBlock(reader, count, expand, layout, _metaArea);
            return(entries.Select(e => new ThirdGenZoneSet(e, reader, _metaArea, _expander)));
        }
        public IEnumerable <ResourcePage> LoadPages(IReader reader)
        {
            StructureValueCollection values = LoadTag(reader);

            ThirdGenCacheFileReference[] files = LoadExternalFiles(values, reader);

            var  count   = (int)values.GetInteger("number of raw pages");
            uint address = (uint)values.GetInteger("raw page table address");

            long expand = _expander.Expand(address);

            StructureLayout layout = _buildInfo.Layouts.GetLayout("raw page table element");

            StructureValueCollection[] entries = TagBlockReader.ReadTagBlock(reader, count, expand, layout, _metaArea);
            return(entries.Select((e, i) => LoadPage(e, i, files)));
        }
Beispiel #7
0
        /// <summary>
        ///     Reads all child objects of this block.
        /// </summary>
        /// <param name="values">The values read from the parent.</param>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="metaArea">The meta area of the cache file.</param>
        /// <param name="stringIDs">The string ID source for the cache file.</param>
        /// <param name="buildInfo">The build info for the cache file.</param>
        /// <returns>The objects that were read.</returns>
        public ScriptObject[] ReadObjects(StructureValueCollection values, IReader reader, FileSegmentGroup metaArea,
                                          StringIDSource stringIDs, EngineDescription buildInfo, IPointerExpander expander)
        {
            var  count   = (int)values.GetInteger(_countEntryName);
            uint address = (uint)values.GetInteger(_addressEntryName);

            long expand = expander.Expand(address);

            StructureLayout layout = buildInfo.Layouts.GetLayout(_layoutName);

            StructureValueCollection[] entries = TagBlockReader.ReadTagBlock(reader, count, expand, layout, metaArea);
            return(entries.Select(e => ReadScriptObject(e, reader, metaArea, stringIDs, buildInfo, expander)).ToArray());
        }
Beispiel #8
0
        private IList <ScriptParameter> LoadParameters(IReader reader, StructureValueCollection values,
                                                       FileSegmentGroup metaArea, EngineDescription buildInfo, IPointerExpander expander)
        {
            var  count   = (int)values.GetInteger("number of parameters");
            uint address = (uint)values.GetInteger("address of parameter list");

            long expand = expander.Expand(address);

            StructureLayout layout = buildInfo.Layouts.GetLayout("script parameter element");

            StructureValueCollection[] entries = TagBlockReader.ReadTagBlock(reader, count, expand, layout, metaArea);
            return(entries.Select(e => new ScriptParameter(e)).ToList());
        }
Beispiel #9
0
        public static void WriteContractedTagBlock(IEnumerable <StructureValueCollection> elements, uint address, StructureLayout layout,
                                                   FileSegmentGroup metaArea, IWriter writer, IPointerExpander expander)
        {
            long cont   = expander.Expand(address);
            int  offset = metaArea.PointerToOffset(address);
            int  index  = 0;

            foreach (StructureValueCollection entry in elements)
            {
                writer.SeekTo(offset + index * layout.Size);
                StructureWriter.WriteStructure(entry, layout, writer);
                index++;
            }
        }
        private static void FreeBitArray(StructureValueCollection values, string countName, string addressName, MetaAllocator allocator, IPointerExpander expander)
        {
            if (!values.HasInteger(countName) || !values.HasInteger(addressName))
            {
                return;
            }

            var  oldCount   = (int)values.GetInteger(countName);
            uint oldAddress = (uint)values.GetInteger(addressName);

            long expand = expander.Expand(oldAddress);

            if (oldCount > 0 && oldAddress > 0)
            {
                allocator.Free(expand, oldCount * 4);
            }
        }
Beispiel #11
0
		private void Load(StructureValueCollection values, ushort index, FileSegmentGroup metaArea, IList<ITagGroup> groupList, IPointerExpander expander)
		{
			uint address = (uint)values.GetInteger("memory address");
			if (address != 0 && address != 0xFFFFFFFF)
			{
				long expanded = expander.Expand(address);

				MetaLocation = SegmentPointer.FromPointer(expanded, metaArea);
			}

			var groupIndex = (int) values.GetInteger("tag group index");
			if (groupIndex >= 0 && groupIndex < groupList.Count)
				Group = groupList[groupIndex];

			var salt = (ushort) values.GetInteger("datum index salt");
			if (salt != 0xFFFF)
				Index = new DatumIndex(salt, index);
			else
				Index = DatumIndex.Null;
		}
Beispiel #12
0
        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);
        }
Beispiel #13
0
        public void AnalyzeArea(IReader reader, long startAddress, MetaMap resultMap)
        {
            // Right now, this method only searches for the signatures of a few complex meta values.
            // Reflexives:      int32 entry count + uint32 address     + 4 bytes of padding
            // Data references: int32 size        + 8 bytes of padding + uint32 address
            // Tag references:  int32 class id    + 8 bytes of padding + uint32 datum index
            // ASCII strings:   characters with the values 0 or 0x20 - 0x7F

            // End at the next-highest address
            long endAddress = _memMap.GetNextHighestAddress(startAddress);

            if (endAddress == 0xFFFFFFFF)
            {
                throw new InvalidOperationException("Invalid start address for area analysis");
            }

            uint size          = (uint)(endAddress - startAddress); // The size of the block of data
            int  paddingLength = 0;                                 // The number of 4-byte padding values that have been read
            uint prePadding    = 0;                                 // The last non-padding uint32 that was read

            MetaValueGuess pendingGuess = null;                     // If not null and padding is encountered, this guess is confirmed

            for (int offset = 0; offset < size; offset += 4)
            {
                uint value = reader.ReadUInt32();

                long expValue = _expander.Expand(value);

                if (IsPadding(value))
                {
                    if (paddingLength == 0 && pendingGuess != null)
                    {
                        resultMap.AddGuess(pendingGuess);

                        // Add the address to the memory map
                        long address = pendingGuess.Pointer;
                        _memMap.AddAddress(address, (int)reader.Position);
                    }

                    // More padding! :D
                    paddingLength++;
                    pendingGuess = null;
                }
                else
                {
                    pendingGuess = null;
                    if (offset <= size - 8 &&
                        prePadding > 0 &&
                        prePadding < 0x80000000
                        // && (value & 3) == 0
                        && IsValidAddress(expValue) &&
                        expValue + prePadding > value &&
                        IsValidAddress(expValue + prePadding - 1) &&
                        !_memMap.BlockCrossesBoundary(expValue, (int)prePadding))
                    {
                        // Either a reflexive or a data reference
                        // Check the padding to determine which (see the comments at the beginning of this method)
                        if (paddingLength == 2 && offset >= 12 && (prePadding & 3) == 0)
                        {
                            // Found a data reference
                            uint dataSize = prePadding;
                            pendingGuess = new MetaValueGuess(offset - 12, MetaValueType.DataReference, expValue, dataSize);
                            // Guess with Pointer = address, Data1 = data size
                        }
                        else if (paddingLength == 0 && offset >= 4)
                        {
                            // Found a reflexive!
                            uint entryCount = prePadding;
                            pendingGuess = new MetaValueGuess(offset - 4, MetaValueType.Reflexive, expValue, entryCount);
                            // Guess with Pointer = address, Data1 = entry count
                        }
                    }
                    if (paddingLength == 2 && offset >= 12 &&
                        (_classIds.Contains((int)prePadding) || (prePadding == 0xFFFFFFFF && value == 0xFFFFFFFF)))
                    {
                        // Found a tag reference
                        uint classId    = prePadding;
                        uint datumIndex = value;
                        var  guess      = new MetaValueGuess(offset - 12, MetaValueType.TagReference, datumIndex, classId);
                        // Guess with Pointer = datum index, Data1 = class id
                        resultMap.AddGuess(guess);
                    }

                    // This obviously isn't a padding value because IsPadding returned false,
                    // so update padding run information accordingly
                    prePadding    = value;
                    paddingLength = 0;
                }
            }
        }
Beispiel #14
0
        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);
        }