/// <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; }
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); }
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; }
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); }
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); }
/// <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; }
/// <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; }
/// <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); }
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; }