public ThirdGenTagTable(IReader reader, SegmentPointer indexHeaderLocation, FileSegmentGroup metaArea, MetaAllocator allocator, EngineDescription buildInfo) { _indexHeaderLocation = indexHeaderLocation; _metaArea = metaArea; _allocator = allocator; _buildInfo = buildInfo; Load(reader); }
/// <summary> /// Initializes a new instance of the <see cref="DataBlockBuilder" /> class. /// </summary> /// <param name="reader">The stream to read from.</param> /// <param name="tagLocation">The location of the tag to load data blocks for.</param> /// <param name="cacheFile">The cache file.</param> /// <param name="buildInfo">The build info for the cache file.</param> public DataBlockBuilder(IReader reader, SegmentPointer tagLocation, ICacheFile cacheFile, EngineDescription buildInfo) { _reader = reader; _tagLocation = tagLocation; _cacheFile = cacheFile; _tagRefLayout = buildInfo.Layouts.GetLayout("tag reference"); _reflexiveLayout = buildInfo.Layouts.GetLayout("reflexive"); _dataRefLayout = buildInfo.Layouts.GetLayout("data reference"); DataBlocks = new List<DataBlock>(); ReferencedTags = new HashSet<DatumIndex>(); ReferencedResources = new HashSet<DatumIndex>(); }
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); } }
private void Load(StructureValueCollection values, FileSegmentGroup metaArea, Dictionary<int, ITagClass> classesById) { uint offset = values.GetInteger("offset"); if (offset > 0) MetaLocation = SegmentPointer.FromPointer(offset, metaArea); // Load the tag class by looking up the magic value that's stored var classMagic = (int) values.GetInteger("class magic"); if (classMagic != -1) Class = classesById[classMagic]; Index = new DatumIndex(values.GetInteger("datum index")); DataSize = (int) values.GetInteger("data size"); }
/// <summary> /// Adds a segment to the group. /// </summary> /// <param name="segment">The segment to add.</param> /// <returns>A SegmentPointer pointing to the beginning of the segment.</returns> public SegmentPointer AddSegment(FileSegment segment) { int offset = segment.Offset; if (_segmentsByOffset.ContainsKey(offset)) { throw new ArgumentException("A segment has already been added at the given offset."); } _segmentsByOffset[segment.Offset] = segment; segment.Resized += SegmentResized; return(SegmentPointer.FromOffset(segment.Offset, this)); }
public void ReadRequestedStrings(IReader reader, SegmentPointer baseLocation, CachedStringTable output) { int baseOffset = baseLocation.AsOffset(); int lastEnd = -1; foreach (int offset in _requestedStrings) { if (offset <= lastEnd) continue; reader.SeekTo(baseOffset + offset); string str = reader.ReadAscii(); output.CacheString(offset, str); lastEnd = offset + str.Length; } }
private void Load(StructureValueCollection values, ushort index, FileSegmentGroup metaArea, IList<ITagClass> classList) { uint address = values.GetInteger("memory address"); if (address != 0 && address != 0xFFFFFFFF) MetaLocation = SegmentPointer.FromPointer(address, 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 void FixShaderReferences(DataBlock block, IStream stream, SegmentPointer baseOffset) { foreach (DataBlockShaderFixup fixup in block.ShaderFixups) { stream.SeekTo(baseOffset.AsOffset() + fixup.WriteOffset); _cacheFile.ShaderStreamer.ImportShader(fixup.Data, stream); } }
private void WriteDataBlock(DataBlock block, SegmentPointer location, IStream stream, ITag tag = null) { if (tag == null && _dataBlockAddresses.ContainsKey(block)) // Don't write anything if the block has already been written return; // Associate the location with the block _dataBlockAddresses[block] = location.AsPointer(); // Create a MemoryStream and write the block data to it (so fixups can be performed before writing it to the file) using (var buffer = new MemoryStream(block.Data.Length)) { var bufferWriter = new EndianWriter(buffer, stream.Endianness); bufferWriter.WriteBlock(block.Data); // Apply fixups FixBlockReferences(block, bufferWriter, stream); FixTagReferences(block, bufferWriter, stream); FixResourceReferences(block, bufferWriter, stream); FixStringIdReferences(block, bufferWriter); if (tag != null) FixUnicListReferences(block, tag, bufferWriter, stream); // Write the buffer to the file stream.SeekTo(location.AsOffset()); stream.WriteBlock(buffer.GetBuffer(), 0, (int) buffer.Length); } // Write shader fixups (they can't be done in-memory because they require cache file expansion) FixShaderReferences(block, stream, location); }
/// <summary> /// Creates a new Partition object, given a base pointer and a size. /// </summary> /// <param name="basePointer">The pointer to the start of the partition.</param> /// <param name="size">The partition's size.</param> public Partition(SegmentPointer basePointer, uint size) { BasePointer = basePointer; Size = size; }
public FourthGenTag(DatumIndex index, ITagClass tagClass, SegmentPointer headerLocation, SegmentPointer metaLocation) { Index = index; Class = tagClass; MetaLocation = metaLocation; HeaderLocation = headerLocation; }
private void WriteDataBlock(DataBlock block, SegmentPointer location, IStream stream) { // Don't write anything if the block has already been written if (_dataBlockAddresses.ContainsKey(block)) return; // Associate the location with the block _dataBlockAddresses[block] = location.AsPointer(); // Create a MemoryStream and write the block data to it (so fixups can be performed before writing it to the file) using (var buffer = new MemoryStream(block.Data.Length)) { var bufferWriter = new EndianWriter(buffer, stream.Endianness); bufferWriter.WriteBlock(block.Data); // Apply fixups FixBlockReferences(block, bufferWriter, stream); FixTagReferences(block, bufferWriter, stream); FixResourceReferences(block, bufferWriter, stream); FixStringIDReferences(block, bufferWriter); // Write the buffer to the file stream.SeekTo(location.AsOffset()); stream.WriteBlock(buffer.GetBuffer(), 0, (int) buffer.Length); } }
private List<ITag> LoadTags(IReader reader, StructureValueCollection headerValues, IList<ITagClass> classes) { /* StructureLayout layout = _buildInfo.Layouts.GetLayout("tag entry"); StructureValueCollection[] entries = ReflexiveReader.ReadReflexive(reader, count, address, layout, _metaArea); return entries.Select<StructureValueCollection, ITag>((e, i) => new FourthGenTag(e, (ushort) i, _metaArea, classes)) .ToList(); */ List<ITag> tags = new List<ITag>(); // New list of tags reader.SeekTo(0); var count = (int) headerValues.GetInteger("number of tags"); uint address = headerValues.GetInteger("tag table address"); StructureLayout layout = _buildInfo.Layouts.GetLayout("tag entry"); // File Segment FileSegmenter segmenter = new FileSegmenter(); segmenter.DefineSegment(0, (int)reader.Length, 0x4, SegmentResizeOrigin.Beginning); // Define a segment for the header //_eofSegment = segmenter.WrapEOF((int)map_values.GetInteger("file size")); FileSegment segment = new FileSegment(0, segmenter); FileSegmentGroup segmentgroup = new FileSegmentGroup(); // Find all of the tag offsets reader.BaseStream.Position = address; // Start at the beginning og the offsets List<uint> tagOffsets = new List<uint>(); for (int i = 0; i < count; i++) tagOffsets.Add(reader.ReadUInt32()); reader.BaseStream.Position = tagOffsets[0]; for (int i = 0; i < count; i++) // Loop through each offset { //if (tagOffsets[i] == 0) tags.Add(null); //else if (tagOffsets[i] != 0) { //var headerOffset = (uint)reader.BaseStream.Position; /* var checksum = reader.ReadUInt32(); // 0x00 uint32 checksum? var totalSize = reader.ReadUInt32(); // 0x04 uint32 total size var numDependencies = reader.ReadInt16(); // 0x08 int16 dependencies count var numDataFixups = reader.ReadInt16(); // 0x0A int16 data fixup count var numResourceFixups = reader.ReadInt16(); // 0x0C int16 resource fixup count reader.BaseStream.Position += 2; // 0x0E int16 (padding) var mainStructOffset = reader.ReadUInt32(); // 0x10 uint32 main struct offset var tagClass = reader.ReadInt32(); // 0x14 int32 class var parentClass = reader.ReadInt32(); // 0x18 int32 parent class var grandparentClass = reader.ReadInt32(); // 0x1C int32 grandparent class var classId = reader.ReadUInt32(); // 0x20 uint32 class stringid */ /* reader.BaseStream.Position = tagOffsets[i]; StructureValueCollection tag_entry_values = StructureReader.ReadStructure(reader, layout); uint id = tag_entry_values.GetInteger("magic"); if(id == 0x3c66783e ) { uint x = id; } //ITagClass tagclass = TryAddClass(tag_entry_values); //FourthGenTag tag = new FourthGenTag(new DatumIndex(headerOffset), tagclass, headerOffset); uint tag_offset = tagOffsets[i]; //SegmentPointer pointer = new SegmentPointer(segment, segmentgroup, (int)tag_offset); uint dep_size = (tag_entry_values.GetInteger("dependencies count") * 4 + tag_entry_values.GetInteger("data fixups count") * 4 + tag_entry_values.GetInteger("resource fixups count") * 4); tag_offset += tag_entry_values.GetInteger("total size") - (tag_entry_values.GetInteger("main struct offset") + dep_size); ITagClass tagclass = TryAddClass(tag_entry_values); //FourthGenTag tag = new FourthGenTag(new DatumIndex(headerOffset), tagclass, headerOffset); SegmentPointer pointer = new SegmentPointer(segment, segmentgroup, (int)(tag_offset)); FourthGenTag tag = new FourthGenTag(new DatumIndex(tag_offset), tagclass, pointer); tags.Add(tag); * */ var headerOffset = tagOffsets[i]; reader.BaseStream.Position = headerOffset; StructureValueCollection tag_entry_values = StructureReader.ReadStructure(reader, layout); reader.BaseStream.Position = tagOffsets[i] + 0x24; int structOffset = (int)tag_entry_values.GetInteger("main struct offset"); int metaOffset = (int)tagOffsets[i] + structOffset; ITagClass tagclass = TryAddClass(tag_entry_values); //SegmentPointer pointer = new SegmentPointer(segment, segmentgroup, metaOffset); //FourthGenTag tag = new FourthGenTag(new DatumIndex((uint)i), tagclass, pointer); SegmentPointer hdrPointer = new SegmentPointer(segment, segmentgroup, (int)headerOffset); SegmentPointer pointer = new SegmentPointer(segment, segmentgroup, metaOffset); FourthGenTag tag = new FourthGenTag(new DatumIndex((uint)i), tagclass, hdrPointer, pointer); tags.Add(tag); } else // Null Tag { FourthGenTag tag = new FourthGenTag(new DatumIndex((uint)i), null, null, null); tags.Add(tag); } } return tags.Where(t => t != null).ToList(); // Remove NULL Entries }
public ThirdGenTag(DatumIndex index, ITagClass tagClass, SegmentPointer metaLocation) { Index = index; Class = tagClass; MetaLocation = metaLocation; }
private List<IScript> LoadScripts(StructureValueCollection values, IReader reader, FileSegmentGroup metaArea, StringIDSource stringIDs, ExpressionTable expressions, StructureLayout entryLayout, BuildInformation buildInfo) { int scriptCount = (int)values.GetInteger("number of scripts"); if (scriptCount == 0) return new List<IScript>(); ScriptsLocation = SegmentPointer.FromPointer(values.GetInteger("script table address"), metaArea); // Read all of the script entries first, then go back and create the objects // ThirdGenScript reads parameters from its constructor - this may or may not need cleaning up to make this more obvious reader.SeekTo(ScriptsLocation.AsOffset()); List<StructureValueCollection> scriptData = new List<StructureValueCollection>(); for (int i = 0; i < scriptCount; i++) scriptData.Add(StructureReader.ReadStructure(reader, entryLayout)); List<IScript> result = new List<IScript>(); foreach (StructureValueCollection scriptValues in scriptData) result.Add(new ThirdGenScript(reader, scriptValues, metaArea, stringIDs, expressions, buildInfo)); return result; }
private List<ITag> ReadTags(IReader reader, SegmentPointer tagTableLocation, int numTags, BuildInformation buildInfo, FileSegmentGroup metaArea) { StructureLayout layout = buildInfo.GetLayout("tag entry"); List<ITag> result = new List<ITag>(); reader.SeekTo(tagTableLocation.AsOffset()); for (int i = 0; i < numTags; i++) { StructureValueCollection values = StructureReader.ReadStructure(reader, layout); result.Add(new ThirdGenTag(values, (ushort)i, metaArea, _classes)); } return result; }
private List<ITagClass> ReadClasses(IReader reader, SegmentPointer classTableLocation, int numClasses, BuildInformation buildInfo) { StructureLayout layout = buildInfo.GetLayout("class entry"); List<ITagClass> result = new List<ITagClass>(); reader.SeekTo(classTableLocation.AsOffset()); for (int i = 0; i < numClasses; i++) { StructureValueCollection values = StructureReader.ReadStructure(reader, layout); result.Add(new ThirdGenTagClass(values)); } return result; }
/// <summary> /// Adds a tag to the table and allocates space for its base data. /// </summary> /// <param name="classMagic">The magic number (ID) of the tag's class.</param> /// <param name="baseSize">The size of the data to initially allocate for the tag.</param> /// <param name="stream">The stream to write to.</param> /// <returns> /// The tag that was allocated. /// </returns> public override ITag AddTag(int classMagic, int baseSize, IStream stream) { /* //if (_indexHeaderLocation == null) // throw new InvalidOperationException("Tags cannot be added to a shared map"); ITagClass tagClass = Classes.FirstOrDefault(c => (c.Magic == classMagic)); if (tagClass == null) throw new InvalidOperationException("Invalid tag class"); uint address = _allocator.Allocate(baseSize, stream); var index = new DatumIndex(0x4153, (ushort) _tags.Count); // 0x4153 = 'AS' because the salt doesn't matter var result = new FourthGenTag(index, tagClass, (uint)stream.Position); _tags.Add(result); return result; * */ ITagClass tagClass = Classes.FirstOrDefault(c => (c.Magic == classMagic)); if (tagClass == null) throw new InvalidOperationException("Invalid tag class"); var offset = stream.BaseStream.Position; uint address = _allocator.Allocate(baseSize, stream); var index = new DatumIndex(0x4153, (ushort)_tags.Count); // 0x4153 = 'AS' because the salt doesn't matter // File Segment FileSegmenter segmenter = new FileSegmenter(); segmenter.DefineSegment(0, (int)stream.Length, 0x4, SegmentResizeOrigin.Beginning); // Define a segment for the header //_eofSegment = segmenter.WrapEOF((int)map_values.GetInteger("file size")); FileSegment segment = new FileSegment(0, segmenter); FileSegmentGroup segmentgroup = new FileSegmentGroup(); SegmentPointer pointer = new SegmentPointer(segment, segmentgroup, (int)offset); FourthGenTag result = new FourthGenTag(index, tagClass, pointer, pointer); _tags.Add(result); return result; }