Пример #1
0
 private static CachedTagData.PointerFixup FinalizeFixup(CachedTagData.PointerFixup fixup, uint dataOffset)
 {
     return(new CachedTagData.PointerFixup
     {
         TargetOffset = fixup.TargetOffset,
         WriteOffset = dataOffset + fixup.WriteOffset
     });
 }
Пример #2
0
        private void AnalyzeStructure(BinaryReader reader, uint baseOffset, uint size, TagLayoutGuess result)
        {
            var lookBehind = new uint[4];

            CachedTagData.PointerFixup potentialGuess = null;
            for (uint offset = 0; offset < size; offset += 4)
            {
                var val = reader.ReadUInt32();
                if (_resourceFixupsByWriteOffset.Contains(baseOffset + offset))
                {
                    // Value is a resource reference
                    result.Add(offset, new ResourceReferenceGuess());
                }
                else if (_dataFixupsByWriteOffset.TryGetValue(baseOffset + offset, out CachedTagData.PointerFixup fixup))
                {
                    // Value is a pointer
                    if (offset >= 0x4)
                    {
                        // Tag block or data reference - need another padding value to confirm it
                        potentialGuess = fixup;
                    }
                }
                else if (offset >= 0xC && lookBehind[0] == 0 && lookBehind[1] == 0 && _tagGroups.Contains(new Tag((int)lookBehind[2])))
                {
                    // Tag reference
                    if (val != 0xFFFFFFFF && val < _cache.Index.Count)
                    {
                        var referencedTag = _cache.Index[(int)val];
                        if (referencedTag != null && referencedTag.Group.Tag.Value == (int)lookBehind[2])
                        {
                            result.Add(offset - 0xC, new TagReferenceGuess());
                        }
                    }
                }
                else if (val == 0 && potentialGuess != null)
                {
                    // Found a potential padding value - check if we can confirm the potential guess's type
                    if (lookBehind[1] != 0)
                    {
                        // Tag block - seek to it and analyze it
                        reader.BaseStream.Position = potentialGuess.TargetOffset;
                        var elementLayout = AnalyzeStructure(reader, lookBehind[1]);
                        reader.BaseStream.Position = baseOffset + offset + 4;
                        result.Add(offset - 0x8, new TagBlockGuess(elementLayout, CalculateAlignment(lookBehind[0])));
                    }
                    else if (offset >= 0x10 && lookBehind[1] == 0 && lookBehind[2] == 0 && lookBehind[3] != 0)
                    {
                        // Data reference
                        result.Add(offset - 0x10, new DataReferenceGuess(CalculateAlignment(lookBehind[0])));
                    }
                    potentialGuess = null;
                }
                else
                {
                    // Tag block and data reference guesses must be followed by padding
                    potentialGuess = null;
                }
                for (var i = 3; i > 0; i--)
                {
                    lookBehind[i] = lookBehind[i - 1];
                }
                lookBehind[0] = val;
            }
        }