private static DataBlock ReadDataBlock(IReader reader, byte version) { if (version > 2) throw new InvalidOperationException("Unrecognized \"data\" block version"); // Block data uint originalAddress = reader.ReadUInt32(); int entryCount = (version >= 1) ? reader.ReadInt32() : 1; byte[] data = ReadByteArray(reader); var block = new DataBlock(originalAddress, entryCount, 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)); } } return block; }
public bool EnterPlugin(int baseSize) { // Read the tag data in based off the base size _reader.SeekTo(_tag.MetaLocation.AsOffset()); var data = _reader.ReadBlock(baseSize); // Create a block for it and push it onto the block stack var block = new DataBlock(_tag.MetaLocation.AsPointer(), 1, 4, data); DataBlocks.Add(block); var blockList = new List<DataBlock> {block}; _blockStack.Push(blockList); return true; }
public uint InjectDataBlock(DataBlock block, IStream stream) { if (block == null) throw new ArgumentNullException("block is null"); // Don't inject the block if it's already been injected uint newAddress; if (_dataBlockAddresses.TryGetValue(block, out newAddress)) return newAddress; // Allocate space for it and write it to the file newAddress = _cacheFile.Allocator.Allocate(block.Data.Length, stream); SegmentPointer location = SegmentPointer.FromPointer(newAddress, _cacheFile.MetaArea); WriteDataBlock(block, location, stream); return newAddress; }
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 FixResourceReferences(DataBlock block, IWriter buffer, IStream stream) { foreach (DataBlockResourceFixup fixup in block.ResourceFixups) { DatumIndex newIndex = InjectResource(fixup.OriginalIndex, stream); buffer.SeekTo(fixup.WriteOffset); buffer.WriteUInt32(newIndex.Value); } }
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); }
private static DataBlock ReadDataBlock(IReader reader, byte version) { if (version > 7) { 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; bool sort = false; if (version >= 7) { byte sortval = reader.ReadByte(); sort = sortval > 0; } byte[] data = ReadByteArray(reader); var block = new DataBlock(originalAddress, entryCount, align, sort, 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)); } } if (version >= 7) { int numInteropFixups = reader.ReadInt32(); for (int i = 0; i < numInteropFixups; i++) { uint dataAddress = reader.ReadUInt32(); int writeOffset = reader.ReadInt32(); int type = reader.ReadInt32(); block.InteropFixups.Add(new DataBlockInteropFixup(type, dataAddress, writeOffset)); } int numEffectFixups = reader.ReadInt32(); for (int i = 0; i < numEffectFixups; i++) { int index = reader.ReadInt32(); int writeOffset = reader.ReadInt32(); int type = reader.ReadInt32(); int effectDataSize = reader.ReadInt32(); byte[] effectData = reader.ReadBlock(effectDataSize); block.EffectFixups.Add(new DataBlockEffectFixup(type, index, writeOffset, effectData)); } } return(block); }
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; }
public DatumIndex InjectTag(ExtractedTag tag, IStream stream) { string tagnameuniqifier = ""; if (tag == null) { throw new ArgumentNullException("tag is null"); } // Don't inject the tag if it's already been injected DatumIndex newIndex; if (_tagIndices.TryGetValue(tag, out newIndex)) { return(newIndex); } // Make sure there isn't already a tag with the given name ITag existingTag = _cacheFile.Tags.FindTagByName(tag.Name, tag.Group, _cacheFile.FileNames); if (existingTag != null) { //check if we are doing shader tweaks if (_renameShaders && _shaderGroups.Contains(CharConstant.ToString(tag.Group))) { //append old tagid to make it unique tagnameuniqifier = "_" + tag.OriginalIndex.ToString(); //make sure the tag didnt come from this exact map if (existingTag.Index == tag.OriginalIndex) { return(existingTag.Index); } //make sure the appended name isn't already present existingTag = _cacheFile.Tags.FindTagByName(tag.Name + tagnameuniqifier, tag.Group, _cacheFile.FileNames); if (existingTag != null) { return(existingTag.Index); } } else { return(existingTag.Index); } } if (!_keepSound && tag.Group == SoundGroup) { return(DatumIndex.Null); } //PCA resource type is not always present, so get rid of 'em for now if (tag.Group == PCAGroup) { return(DatumIndex.Null); } // Look up the tag's datablock to get its size and allocate a tag for it DataBlock tagData = _container.FindDataBlock(tag.OriginalAddress); if (_resources == null && BlockNeedsResources(tagData)) { // If the tag relies on resources and that info isn't available, throw it out LoadResourceTable(stream); if (_resources == null) { return(DatumIndex.Null); } } if (_soundResources == null && BlockNeedsSounds(tagData)) { // If the tag relies on sound resources and that info isn't available, throw it out LoadSoundResourceTable(stream); if (_soundResources == null) { return(DatumIndex.Null); } } ITag newTag = _cacheFile.Tags.AddTag(tag.Group, tagData.Data.Length, stream); _tagIndices[tag] = newTag.Index; _cacheFile.FileNames.SetTagName(newTag, tag.Name + tagnameuniqifier); // Write the data WriteDataBlock(tagData, newTag.MetaLocation, stream, newTag); // Make the tag load LoadZoneSets(stream); if (_zoneSets != null) { _zoneSets.ExpandAllTags(newTag.Index.Index); if (_zoneSets.GlobalZoneSet != null) { _zoneSets.GlobalZoneSet.ActivateTag(newTag, true); } } // If its group matches one of the valid simulation group names, add it to the simulation definition table if (_cacheFile.SimulationDefinitions != null && _simulationGroups.Contains(CharConstant.ToString(newTag.Group.Magic))) { _cacheFile.SimulationDefinitions.Add(newTag); } return(newTag.Index); }
private DataBlock ReadDataBlock(uint pointer, int entrySize, int entryCount, int align) { _reader.SeekTo(_cacheFile.MetaArea.PointerToOffset(pointer)); var data = _reader.ReadBlock(entrySize*entryCount); var block = new DataBlock(pointer, entryCount, align, data); DataBlocks.Add(block); return block; }
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); }
private void ReadStringId(DataBlock block, uint offset) { SeekToOffset(block, offset); var sid = new StringID(_reader.ReadUInt32()); if (sid == StringID.Null) return; var str = _cacheFile.StringIDs.GetString(sid); if (str == null) return; var fixup = new DataBlockStringIDFixup(str, (int) offset); block.StringIDFixups.Add(fixup); }
/// <summary> /// Adds a data block to the container. /// </summary> /// <param name="block">The block to add.</param> public void AddDataBlock(DataBlock block) { _dataBlocksByAddress[block.OriginalAddress] = block; }
private void ReadShader(DataBlock block, uint offset, ShaderType type) { SeekToOffset(block, offset); var data = _cacheFile.ShaderStreamer.ExportShader(_reader, type); var fixup = new DataBlockShaderFixup((int)offset, data); block.ShaderFixups.Add(fixup); }
private void SeekToOffset(DataBlock block, uint offset) { int baseOffset = _cacheFile.MetaArea.PointerToOffset(block.OriginalAddress); _reader.SeekTo(baseOffset + offset); }
public DatumIndex InjectTag(ExtractedTag tag, IStream stream) { if (tag == null) { throw new ArgumentNullException("tag is null"); } // Don't inject the tag if it's already been injected DatumIndex newIndex; if (_tagIndices.TryGetValue(tag, out newIndex)) { return(newIndex); } // Make sure there isn't already a tag with the given name ITag existingTag = _cacheFile.Tags.FindTagByName(tag.Name, tag.Class, _cacheFile.FileNames); if (existingTag != null) { return(existingTag.Index); } // If the tag has made it this far but is a sound, make everyone (especially gerit) shut up. if (tag.Class == SoundClass) { return(DatumIndex.Null); } // Look up the tag's datablock to get its size and allocate a tag for it DataBlock tagData = _container.FindDataBlock(tag.OriginalAddress); if (_resources == null && BlockNeedsResources(tagData)) { // If the tag relies on resources and that info isn't available, throw it out LoadResourceTable(stream); if (_resources == null) { return(DatumIndex.Null); } } ITag newTag = _cacheFile.Tags.AddTag(tag.Class, tagData.Data.Length, stream); _tagIndices[tag] = newTag.Index; _cacheFile.FileNames.SetTagName(newTag, tag.Name); // Write the data WriteDataBlock(tagData, newTag.MetaLocation, stream, newTag); // Make the tag load LoadZoneSets(stream); if (_zoneSets != null && _zoneSets.GlobalZoneSet != null) { _zoneSets.GlobalZoneSet.ActivateTag(newTag, true); } // If its class matches one of the valid simulation class names, add it to the simulation definition table if (_cacheFile.SimulationDefinitions != null && _simulationClasses.Contains(CharConstant.ToString(newTag.Class.Magic))) { _cacheFile.SimulationDefinitions.Add(newTag); } return(newTag.Index); }
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 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 ReadSound(DataBlock block, uint offset) { if (_soundLayout == null) { return; } ContainsSoundReferences = true; SeekToOffset(block, 0); var values = StructureReader.ReadStructure(_reader, _soundLayout); int codec = (short)values.GetInteger("codec index"); int pitchRangeCount = (short)values.GetInteger("pitch range count"); int firstPitchRange = (short)values.GetInteger("first pitch range index"); int firstLangPitchRange = (short)values.GetInteger("first language duration pitch range index"); int playback = (short)values.GetInteger("playback index"); int scale = (short)values.GetInteger("scale index"); int promotion = (sbyte)values.GetInteger("promotion index"); int customPlayback = (sbyte)values.GetInteger("custom playback index"); int extraInfo = (short)values.GetIntegerOrDefault("extra info index", 0xFFFF); block.SoundFixups.Add(new DataBlockSoundFixup( codec, pitchRangeCount, firstPitchRange, firstLangPitchRange, playback, scale, promotion, customPlayback, extraInfo)); if (codec != -1) { ReferencedSoundCodecs.Add(codec); } for (int i = 0; i < pitchRangeCount; i++) { if (firstPitchRange != -1) { ReferencedSoundPitchRanges.Add(firstPitchRange + i); } if (firstLangPitchRange != -1) { ReferencedSoundLanguagePitchRanges.Add(firstLangPitchRange + i); } } if (playback != -1) { ReferencedSoundPlaybacks.Add(playback); } if (scale != -1) { ReferencedSoundScales.Add(scale); } if (promotion != -1) { ReferencedSoundPromotions.Add(promotion); } if (customPlayback != -1) { ReferencedSoundCustomPlaybacks.Add(customPlayback); } if (extraInfo != -1) { ReferencedSoundExtraInfo.Add(extraInfo); } }
private void ReadDataReference(DataBlock block, uint offset, int align) { // Read the size and pointer SeekToOffset(block, offset); var values = StructureReader.ReadStructure(_reader, _dataRefLayout); var size = (int) values.GetInteger("size"); var pointer = values.GetInteger("pointer"); if (size <= 0 || !_cacheFile.MetaArea.ContainsBlockPointer(pointer, size)) return; // Read the block and create a fixup for it ReadDataBlock(pointer, size, 1, align); var fixup = new DataBlockAddressFixup(pointer, (int) offset + _dataRefLayout.GetFieldOffset("pointer")); block.AddressFixups.Add(fixup); }
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); } FixInteropReferences(block, bufferWriter, stream, location); FixEffectReferences(block, bufferWriter); if (!_dupeReuseSoundGestalt) { FixSoundReferences(block, bufferWriter, stream); } // 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 ReadReflexive(DataBlock block, uint offset, uint entrySize, int align) { // Read the count and pointer SeekToOffset(block, offset); var values = StructureReader.ReadStructure(_reader, _tagBlockLayout); var count = (int) values.GetInteger("entry count"); var pointer = values.GetInteger("pointer"); if (count <= 0 || !_cacheFile.MetaArea.ContainsBlockPointer(pointer, (int) (count*entrySize))) return; var newBlock = ReadDataBlock(pointer, (int)entrySize, count, align); // Now create a fixup for the block var fixup = new DataBlockAddressFixup(pointer, (int) offset + _tagBlockLayout.GetFieldOffset("pointer")); block.AddressFixups.Add(fixup); // Add it to _reflexiveBlocks so it'll be recursed into _reflexiveBlocks.Add(newBlock); }
private void ReadShader(DataBlock block, uint offset, ShaderType type) { SeekToOffset(block, offset); //Don't bother if the pointer is null. if (_reader.ReadInt32() == 0) return; _reader.Skip(-4); var data = _cacheFile.ShaderStreamer.ExportShader(_reader, type); var fixup = new DataBlockShaderFixup((int)offset, data); block.ShaderFixups.Add(fixup); }
private bool BlockNeedsResources(DataBlock block) { if (block.ResourceFixups.Count > 0) return true; foreach (var addrFixup in block.AddressFixups) { var subBlock = _container.FindDataBlock(addrFixup.OriginalAddress); if (BlockNeedsResources(subBlock)) return true; } return false; }
private void GlobalShaderFixup(DataBlock block, uint offset) { SeekToOffset(block, offset); var index = _reader.ReadInt32(); var shaderAddr = _reader.ReadUInt32(); //check if we need to grab the shader if (shaderAddr == 0) { if (index != -1) { //make the index -1 in the datablock for (var i = 0; i < 4; i++) block.Data[offset + i] = 0xFF; //Grab the shader from gpix _reader.SeekTo(_cacheFile.Tags.FindTagByClass("gpix").MetaLocation.AsOffset() + 0x14); var gpixBase = _reader.ReadUInt32() - _cacheFile.MetaArea.PointerMask; _reader.SeekTo(gpixBase + (0x58 * index) + 0x54); //Make a shader fixup using the gpix shader var data = _cacheFile.ShaderStreamer.ExportShader(_reader, ShaderType.Pixel); var fixup = new DataBlockShaderFixup((int)offset + 4, data); block.ShaderFixups.Add(fixup); } } else return; }
private void FixBlockReferences(DataBlock block, IWriter buffer, IStream stream) { foreach (DataBlockAddressFixup fixup in block.AddressFixups) { uint newAddress = InjectDataBlock(fixup.OriginalAddress, stream); buffer.SeekTo(fixup.WriteOffset); buffer.WriteUInt32(newAddress); } }
private void SeekToOffset(DataBlock block, uint offset) { var baseOffset = _cacheFile.MetaArea.PointerToOffset(block.OriginalAddress); _reader.SeekTo(baseOffset + offset); }
private void FixStringIdReferences(DataBlock block, IWriter buffer) { foreach (DataBlockStringIDFixup fixup in block.StringIDFixups) { StringID newSID = InjectStringID(fixup.OriginalString); buffer.SeekTo(fixup.WriteOffset); buffer.WriteUInt32(newSID.Value); } }
private void FixStringIDReferences(DataBlock block, IWriter buffer) { foreach (DataBlockStringIDFixup fixup in block.StringIDFixups) { // Try to find the string, and if it's not found, inject it StringID newSID = _cacheFile.StringIDs.FindStringID(fixup.OriginalString); if (newSID == StringID.Null) { newSID = _cacheFile.StringIDs.AddString(fixup.OriginalString); _injectedStrings.Add(newSID); } buffer.SeekTo(fixup.WriteOffset); buffer.WriteUInt32(newSID.Value); } }
private void FixUnicListReferences(DataBlock block, ITag tag, IWriter buffer, IStream stream) { foreach (DataBlockUnicListFixup fixup in block.UnicListFixups) { var pack = _languageCache.LoadLanguage((GameLanguage)fixup.LanguageIndex, stream); var stringList = new LocalizedStringList(tag); foreach (var str in fixup.Strings) { var id = InjectStringID(str.StringID); stringList.Strings.Add(new LocalizedString(id, str.String)); } pack.AddStringList(stringList); } }
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); }