private static CachedTagData.PointerFixup FinalizeFixup(CachedTagData.PointerFixup fixup, uint dataOffset) { return(new CachedTagData.PointerFixup { TargetOffset = fixup.TargetOffset, WriteOffset = dataOffset + fixup.WriteOffset }); }
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; } }