Example #1
0
        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;
        }
Example #2
0
		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;
		}
Example #3
0
        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);
        }
Example #8
0
		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);
        }
Example #10
0
		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;
		}
Example #11
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);
		}
Example #12
0
		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);
		}
Example #13
0
		/// <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;
		}
Example #14
0
 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);
 }
Example #15
0
        private void SeekToOffset(DataBlock block, uint offset)
        {
            int baseOffset = _cacheFile.MetaArea.PointerToOffset(block.OriginalAddress);

            _reader.SeekTo(baseOffset + offset);
        }
Example #16
0
        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);
        }
Example #17
0
        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);
            }
        }
Example #18
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);
		}
Example #19
0
        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);
            }
        }
Example #20
0
		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);
		}
Example #21
0
        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);
        }
Example #22
0
		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);
		}
Example #23
0
 /// <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;
 }
Example #24
0
		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);
		}
Example #25
0
		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;
		}
Example #26
0
		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;
		}
Example #27
0
		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);
			}
		}
Example #28
0
		private void SeekToOffset(DataBlock block, uint offset)
		{
			var baseOffset = _cacheFile.MetaArea.PointerToOffset(block.OriginalAddress);
			_reader.SeekTo(baseOffset + offset);
		}
Example #29
0
		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);
			}
		}
Example #30
0
        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);
            }
        }
Example #31
0
		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);
			}
		}
Example #32
0
        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);
        }