Exemple #1
0
		/// <summary>
		///     Initializes a new instance of the <see cref="ExtractedTag" /> class.
		/// </summary>
		/// <param name="originalIndex">The original datum index of the tag.</param>
		/// <param name="originalAddress">The original address of the tag's data.</param>
		/// <param name="tagClass">The tag's class ID.</param>
		/// <param name="name">The tag's name.</param>
		public ExtractedTag(DatumIndex originalIndex, uint originalAddress, int tagClass, string name)
		{
			OriginalIndex = originalIndex;
			OriginalAddress = originalAddress;
			Class = tagClass;
			Name = name;
		}
Exemple #2
0
        void Load(StructureValueCollection values, ushort index, FileSegmentGroup metaArea, IList<ITagClass> classList)
        {
            uint address = values.GetInteger("memory address");
            if (address != 0 && address != 0xFFFFFFFF)
            {
                int classIndex = (int)values.GetInteger("class index");
                Class = classList[classIndex];

                ushort salt = (ushort)values.GetInteger("datum index salt");
                Index = new DatumIndex(salt, index);

                MetaLocation = SegmentPointer.FromPointer(address, metaArea);
            }
        }
		public DatumIndex InjectResource(ExtractedResourceInfo resource, IStream stream)
		{
			if (_resources == null)
				return DatumIndex.Null;
			if (resource == null)
				throw new ArgumentNullException("resource is null");

			// Don't inject the resource if it's already been injected
			DatumIndex newIndex;
			if (_resourceIndices.TryGetValue(resource, out newIndex))
				return newIndex;

			// Create a new datum index for it (0x4152 = 'AR') and associate it
			LoadResourceTable(stream);
			newIndex = new DatumIndex(0x4152, (ushort) _resources.Resources.Count);
			_resourceIndices[resource] = newIndex;

			// Create a native resource for it
			var newResource = new Resource();
			_resources.Resources.Add(newResource);
			newResource.Index = newIndex;
			newResource.Flags = resource.Flags;
			newResource.Type = resource.Type;
			newResource.Info = resource.Info;
			if (resource.OriginalParentTagIndex.IsValid)
			{
				DatumIndex parentTagIndex = InjectTag(resource.OriginalParentTagIndex, stream);
				newResource.ParentTag = _cacheFile.Tags[parentTagIndex];
			}
			if (resource.Location != null)
			{
				newResource.Location = new ResourcePointer();

				// Primary page pointers
				if (resource.Location.OriginalPrimaryPageIndex >= 0)
				{
					int primaryPageIndex = InjectResourcePage(resource.Location.OriginalPrimaryPageIndex, stream);
					newResource.Location.PrimaryPage = _resources.Pages[primaryPageIndex];
				}
				newResource.Location.PrimaryOffset = resource.Location.PrimaryOffset;
				newResource.Location.PrimaryUnknown = resource.Location.PrimaryUnknown;

				// Secondary page pointers
				if (resource.Location.OriginalSecondaryPageIndex >= 0)
				{
					int secondaryPageIndex = InjectResourcePage(resource.Location.OriginalSecondaryPageIndex, stream);
					newResource.Location.SecondaryPage = _resources.Pages[secondaryPageIndex];
				}
				newResource.Location.SecondaryOffset = resource.Location.SecondaryOffset;
				newResource.Location.SecondaryUnknown = resource.Location.SecondaryUnknown;
			}

			newResource.ResourceFixups.AddRange(resource.ResourceFixups);
			newResource.DefinitionFixups.AddRange(resource.DefinitionFixups);

			newResource.Unknown1 = resource.Unknown1;
			newResource.Unknown2 = resource.Unknown2;
			newResource.Unknown3 = resource.Unknown3;

			// Make it load
			LoadZoneSets(stream);
			if (_zoneSets != null && _zoneSets.GlobalZoneSet != null)
				_zoneSets.GlobalZoneSet.ActivateResource(newResource, true);

			return newIndex;
		}
		public DatumIndex InjectTag(DatumIndex originalIndex, IStream stream)
		{
			return InjectTag(_container.FindTag(originalIndex), stream);
		}
Exemple #5
0
        public void VisitTagRef(TagRefData field)
        {
            SeekToOffset(field.Offset);

            TagClass tagClass = null;
            DatumIndex index;
            if (field.WithClass)
            {
                // Read the datum index based upon the layout
                StructureValueCollection values = StructureReader.ReadStructure(_reader, _tagRefLayout);
                index = new DatumIndex(values.GetInteger("datum index"));

                // Check the class, in case the datum index is null
                var magic = values.GetInteger("class magic");
                var str = CharConstant.ToString((int)magic);
                tagClass = field.Tags.Classes.FirstOrDefault(c => c.TagClassMagic == str);
            }
            else
            {
                // Just read the datum index at the current position
                index = DatumIndex.ReadFrom(_reader);
            }

            TagEntry tag = null;
            if (index.IsValid && index.Index < field.Tags.Entries.Count)
            {
                tag = field.Tags.Entries[index.Index];
                if (tag == null || tag.RawTag == null || tag.RawTag.Index != index)
                    tag = null;
            }

            if (tag != null)
            {
                field.Class = field.Tags.Classes.FirstOrDefault(c => c.RawClass == tag.RawTag.Class);
                field.Value = tag;
            }
            else
            {
                field.Class = tagClass;
                field.Value = null;
            }
        }
		private static DataBlock ReadDataBlock(IReader reader, byte version)
		{
			if (version > 6)
				throw new InvalidOperationException("Unrecognized \"data\" block version");

			// Block data
			uint originalAddress = reader.ReadUInt32();
			int entryCount = (version >= 1) ? reader.ReadInt32() : 1;
			int align = (version >= 3) ? reader.ReadInt32() : 4;
			byte[] data = ReadByteArray(reader);
			var block = new DataBlock(originalAddress, entryCount, align, data);

			// Address fixups
			int numAddressFixups = reader.ReadInt32();
			for (int i = 0; i < numAddressFixups; i++)
			{
				uint dataAddress = reader.ReadUInt32();
				int writeOffset = reader.ReadInt32();
				block.AddressFixups.Add(new DataBlockAddressFixup(dataAddress, writeOffset));
			}

			// Tagref fixups
			int numTagFixups = reader.ReadInt32();
			for (int i = 0; i < numTagFixups; i++)
			{
				var datum = new DatumIndex(reader.ReadUInt32());
				int writeOffset = reader.ReadInt32();
				block.TagFixups.Add(new DataBlockTagFixup(datum, writeOffset));
			}

			// Resource reference fixups
			int numResourceFixups = reader.ReadInt32();
			for (int i = 0; i < numResourceFixups; i++)
			{
				var datum = new DatumIndex(reader.ReadUInt32());
				int writeOffset = reader.ReadInt32();
				block.ResourceFixups.Add(new DataBlockResourceFixup(datum, writeOffset));
			}

			if (version >= 2)
			{
				// StringID fixups
				int numSIDFixups = reader.ReadInt32();
				for (int i = 0; i < numSIDFixups; i++)
				{
					string str = reader.ReadAscii();
					int writeOffset = reader.ReadInt32();
					block.StringIDFixups.Add(new DataBlockStringIDFixup(str, writeOffset));
				}
			}

			if (version >= 4)
			{
				// Shader fixups
				int numShaderFixups = reader.ReadInt32();
				for (int i = 0; i < numShaderFixups; i++)
				{
					int writeOffset = reader.ReadInt32();
					int shaderDataSize = reader.ReadInt32();
					byte[] shaderData = reader.ReadBlock(shaderDataSize);
					block.ShaderFixups.Add(new DataBlockShaderFixup(writeOffset, shaderData));
				}
			}

			if (version >= 5)
			{
				// Unicode string list fixups
				int numUnicListFixups = reader.ReadInt32();
				for (int i = 0; i < numUnicListFixups; i++)
				{
					// Version 5 is buggy and doesn't include a language index :x
					int languageIndex = i;
					if (version >= 6)
						languageIndex = reader.ReadInt32();

					int writeOffset = reader.ReadInt32();
					int numStrings = reader.ReadInt32();
					UnicListFixupString[] strings = new UnicListFixupString[numStrings];
					for (int j = 0; j < numStrings; j++)
					{
						string stringId = reader.ReadAscii();
						string str = reader.ReadUTF8();
						strings[j] = new UnicListFixupString(stringId, str);
					}
					block.UnicListFixups.Add(new DataBlockUnicListFixup(languageIndex, writeOffset, strings));
				}
			}

			return block;
		}
		private static ExtractedResourceInfo ReadResource(IReader reader, byte version)
		{
			if (version != 1)
				throw new InvalidOperationException("Unrecognized \"rsrc\" block version");

			var originalIndex = new DatumIndex(reader.ReadUInt32());
			var resource = new ExtractedResourceInfo(originalIndex);
			resource.Flags = reader.ReadUInt32();
			resource.Type = reader.ReadAscii();
			if (string.IsNullOrEmpty(resource.Type))
				resource.Type = null;
			resource.Info = ReadByteArray(reader);
			resource.OriginalParentTagIndex = new DatumIndex(reader.ReadUInt32());
			byte hasLocation = reader.ReadByte();
			if (hasLocation != 0)
			{
				resource.Location = new ExtractedResourcePointer();
				resource.Location.OriginalPrimaryPageIndex = reader.ReadInt32();
				resource.Location.PrimaryOffset = reader.ReadInt32();
				resource.Location.PrimaryUnknown = reader.ReadInt32();
				resource.Location.OriginalSecondaryPageIndex = reader.ReadInt32();
				resource.Location.SecondaryOffset = reader.ReadInt32();
				resource.Location.SecondaryUnknown = reader.ReadInt32();
			}
			resource.Unknown1 = reader.ReadInt32();
			resource.Unknown2 = reader.ReadInt32();
			resource.Unknown3 = reader.ReadInt32();

			int numResourceFixups = reader.ReadInt32();
			for (int i = 0; i < numResourceFixups; i++)
			{
				var fixup = new ResourceFixup();
				fixup.Offset = reader.ReadInt32();
				fixup.Address = reader.ReadUInt32();
				resource.ResourceFixups.Add(fixup);
			}

			int numDefinitionFixups = reader.ReadInt32();
			for (int i = 0; i < numDefinitionFixups; i++)
			{
				var fixup = new ResourceDefinitionFixup();
				fixup.Offset = reader.ReadInt32();
				fixup.Type = reader.ReadInt32();
				resource.DefinitionFixups.Add(fixup);
			}

			return resource;
		}
		private static ExtractedTag ReadTag(IReader reader, byte version)
		{
			if (version > 0)
				throw new InvalidOperationException("Unrecognized \"tag!\" block version");

			var datum = new DatumIndex(reader.ReadUInt32());
			uint address = reader.ReadUInt32();
			int tagClass = reader.ReadInt32();
			string name = reader.ReadAscii();
			return new ExtractedTag(datum, address, tagClass, name);
		}
		/// <summary>
		///     Initializes a new instance of the <see cref="ExtractedResourceInfo" /> class.
		/// </summary>
		/// <param name="originalIndex">The original datum index of the resource.</param>
		public ExtractedResourceInfo(DatumIndex originalIndex)
		{
			OriginalIndex = originalIndex;
			ResourceFixups = new List<ResourceFixup>();
			DefinitionFixups = new List<ResourceDefinitionFixup>();
		}
        private static DataBlock ReadDataBlock(IReader reader, byte version)
        {
            if (version > 4)
                throw new InvalidOperationException("Unrecognized \"data\" block version");

            // Block data
            uint originalAddress = reader.ReadUInt32();
            int entryCount = (version >= 1) ? reader.ReadInt32() : 1;
            int align = (version >= 3) ? reader.ReadInt32() : 4;
            byte[] data = ReadByteArray(reader);
            var block = new DataBlock(originalAddress, entryCount, align, data);

            // Address fixups
            int numAddressFixups = reader.ReadInt32();
            for (int i = 0; i < numAddressFixups; i++)
            {
                uint dataAddress = reader.ReadUInt32();
                int writeOffset = reader.ReadInt32();
                block.AddressFixups.Add(new DataBlockAddressFixup(dataAddress, writeOffset));
            }

            // Tagref fixups
            int numTagFixups = reader.ReadInt32();
            for (int i = 0; i < numTagFixups; i++)
            {
                var datum = new DatumIndex(reader.ReadUInt32());
                int writeOffset = reader.ReadInt32();
                block.TagFixups.Add(new DataBlockTagFixup(datum, writeOffset));
            }

            // Resource reference fixups
            int numResourceFixups = reader.ReadInt32();
            for (int i = 0; i < numResourceFixups; i++)
            {
                var datum = new DatumIndex(reader.ReadUInt32());
                int writeOffset = reader.ReadInt32();
                block.ResourceFixups.Add(new DataBlockResourceFixup(datum, writeOffset));
            }

            if (version >= 2)
            {
                // StringID fixups
                int numSIDFixups = reader.ReadInt32();
                for (int i = 0; i < numSIDFixups; i++)
                {
                    string str = reader.ReadAscii();
                    int writeOffset = reader.ReadInt32();
                    block.StringIDFixups.Add(new DataBlockStringIDFixup(str, writeOffset));
                }
            }

            if (version >= 4)
            {
                // Shader fixups
                int numShaderFixups = reader.ReadInt32();
                for (int i = 0; i < numShaderFixups; i++)
                {
                    int writeOffset = reader.ReadInt32();
                    int shaderDataSize = reader.ReadInt32();
                    byte[] shaderData = reader.ReadBlock(shaderDataSize);
                    block.ShaderFixups.Add(new DataBlockShaderFixup(writeOffset, shaderData));
                }
            }

            return block;
        }
Exemple #11
0
		private void ReadTagReference(DataBlock block, uint offset, bool withClass)
		{
			SeekToOffset(block, offset);

			DatumIndex index;
			int fixupOffset;
			bool valid;
			if (withClass)
			{
				// Class info - do a flexible structure read to get the index
				var values = StructureReader.ReadStructure(_reader, _tagRefLayout);
				var classMagic = (int) values.GetInteger("class magic");
				index = new DatumIndex(values.GetInteger("datum index"));
				fixupOffset = (int) offset + _tagRefLayout.GetFieldOffset("datum index");
				valid = _cacheFile.Tags.IsValidIndex(index);
			}
			else
			{
				// No tag class - the datum index is at the offset
				index = new DatumIndex(_reader.ReadUInt32());
				fixupOffset = (int) offset;
				valid = _cacheFile.Tags.IsValidIndex(index);
			}

			if (!valid) return;

			// Add the tagref fixup to the block
			var fixup = new DataBlockTagFixup(index, fixupOffset);
			block.TagFixups.Add(fixup);
			ReferencedTags.Add(index);
		}
Exemple #12
0
		private void ReadResourceFixup(DataBlock block, uint offset)
		{
			SeekToOffset(block, offset);
			var index = new DatumIndex(_reader.ReadUInt32());
			if (!index.IsValid) return;

			var fixup = new DataBlockResourceFixup(index, (int) offset);
			block.ResourceFixups.Add(fixup);
			ReferencedResources.Add(index);
		}
Exemple #13
0
		/// <summary>
		///     Finds the resource which has a specified original datum index.
		/// </summary>
		/// <param name="originalIndex">The original datum index of the resource to find.</param>
		/// <returns>The <see cref="ExtractedResourceInfo" /> with the original datum index, or <c>null</c> if not found.</returns>
		public ExtractedResourceInfo FindResource(DatumIndex originalIndex)
		{
			ExtractedResourceInfo result;
			_resourcesByIndex.TryGetValue(originalIndex, out result);
			return result;
		}
Exemple #14
0
		/// <summary>
		///     Finds the tag which has a specified original datum index.
		/// </summary>
		/// <param name="originalIndex">The original datum index of the tag to find.</param>
		/// <returns>The <see cref="ExtractedTag" /> with the original datum index, or <c>null</c> if not found.</returns>
		public ExtractedTag FindTag(DatumIndex originalIndex)
		{
			ExtractedTag result;
			_tagsByIndex.TryGetValue(originalIndex, out result);
			return result;
		}
Exemple #15
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="DataBlockTagFixup" /> class.
 /// </summary>
 /// <param name="originalIndex">The original datum index of the tag.</param>
 /// <param name="writeOffset">The offset within the data block's data to write the new datum index of the tag to.</param>
 public DataBlockTagFixup(DatumIndex originalIndex, int writeOffset)
 {
     OriginalIndex = originalIndex;
     WriteOffset = writeOffset;
 }
		public DatumIndex InjectResource(DatumIndex originalIndex, IStream stream)
		{
			return InjectResource(_container.FindResource(originalIndex), stream);
		}
Exemple #17
0
        public void VisitTagRef(TagRefData field)
        {
            SeekToOffset(field.Offset);

            DatumIndex index;
            if (field.WithClass)
            {
                // Read the datum index based upon the layout
                StructureValueCollection values = StructureReader.ReadStructure(_reader, _tagRefLayout);
                index = new DatumIndex(values.GetInteger("datum index"));
            }
            else
            {
                // Just read the datum index at the current position
                index = DatumIndex.ReadFrom(_reader);
            }

            TagEntry tag = null;
            if (index.IsValid && index.Index < field.Tags.Entries.Count)
                tag = field.Tags.Entries[index.Index];

            if (tag != null)
            {
                field.Class = tag.ParentClass;
                field.Value = tag;
            }
            else
            {
                field.Class = null;
                field.Value = null;
            }
        }
		/// <summary>
		///     Initializes a new instance of the <see cref="ExtractedResourceInfo" /> class.
		/// </summary>
		/// <param name="originalIndex">The original datum index of the resource.</param>
		/// <param name="baseResource">The <see cref="Resource" /> to initialize the instance with.</param>
		public ExtractedResourceInfo(DatumIndex originalIndex, Resource baseResource)
		{
			if (originalIndex.Index != baseResource.Index.Index)
				throw new InvalidOperationException("originalIndex.Index != baseResource.Index.Index");

			OriginalIndex = originalIndex;
			Flags = baseResource.Flags;
			Type = baseResource.Type;
			Info = baseResource.Info;
			OriginalParentTagIndex = (baseResource.ParentTag != null) ? baseResource.ParentTag.Index : DatumIndex.Null;
			Location = (baseResource.Location != null) ? new ExtractedResourcePointer(baseResource.Location) : null;
			ResourceFixups = new List<ResourceFixup>(baseResource.ResourceFixups);
			DefinitionFixups = new List<ResourceDefinitionFixup>(baseResource.DefinitionFixups);
			Unknown1 = baseResource.Unknown1;
			Unknown2 = baseResource.Unknown2;
			Unknown3 = baseResource.Unknown3;
		}