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); } // Write shader fixups (they can't be done in-memory because they require cache file expansion) FixShaderReferences(block, stream, (int)location.AsOffset()); }
public SecondGenTag(DatumIndex index, ITagGroup tagGroup, SegmentPointer metaLocation, int size) { Index = index; Group = tagGroup; MetaLocation = metaLocation; Offset = (int)MetaLocation.AsPointer(); DataSize = size; }
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); } FixModelDataReferences(block, bufferWriter, stream, location); FixEffectReferences(block, bufferWriter); // sort after fixups if (block.Sortable && block.EntrySize >= 4) { var entries = new List <Tuple <uint, byte[]> >(); var bufferReader = new EndianReader(buffer, stream.Endianness); for (int i = 0; i < block.EntryCount; i++) { buffer.Position = i * block.EntrySize; uint sid = bufferReader.ReadUInt32(); byte[] rest = bufferReader.ReadBlock(block.EntrySize - 4); entries.Add(new Tuple <uint, byte[]>(sid, rest)); } buffer.Position = 0; foreach (var entry in entries.OrderBy(e => e.Item1)) { bufferWriter.WriteUInt32(entry.Item1); bufferWriter.WriteBlock(entry.Item2); } } // Write the buffer to the file stream.SeekTo(location.AsOffset()); stream.WriteBlock(buffer.ToArray(), 0, (int)buffer.Length); } // Write shader fixups (they can't be done in-memory because they require cache file expansion) FixShaderReferences(block, stream, location); }
private void FixInteropReferences(DataBlock block, IWriter buffer, IStream stream, SegmentPointer location) { foreach (DataBlockInteropFixup fixup in block.InteropFixups) { long newAddress = InjectDataBlock(fixup.OriginalAddress, stream); uint cont = _cacheFile.PointerExpander.Contract(newAddress); buffer.SeekTo(fixup.WriteOffset); buffer.WriteUInt32(cont); uint contp = _cacheFile.PointerExpander.Contract(location.AsPointer() + fixup.WriteOffset); _cacheFile.TagInteropTable.Add(new Blam.ThirdGen.Structures.ThirdGenTagInterop(contp, fixup.Type)); } }
public bool EnterPlugin(int baseSize) { // Read the tag data in based off the base size _reader.SeekTo(_tagLocation.AsOffset()); byte[] data = _reader.ReadBlock(baseSize); // Create a block for it and push it onto the block stack var block = new DataBlock(_tagLocation.AsPointer(), 1, 4, data); DataBlocks.Add(block); var blockList = new List <DataBlock>(); blockList.Add(block); _blockStack.Push(blockList); return(true); }