void ProcessBlockRecursive(Block block, Map map, int address, int count, ref Report report) { br.BaseStream.Position = address - magic; #region Check Alignement if (br.BaseStream.Position % block.Alignment != 0) { //if (OnAddressError != null) //{ // OnAddressError(this, new AddressingErrorArgs() // { // Block = block, // Offset = startAddress, // Length = length, // Type = AddressingErrorArgs.ErrorType.InvalidAlignment // }); //} } #endregion #region Read Sector bool internalSector = (address - magic) >= startAddress && (address - magic) < startAddress + length; report.Sectors.Add(new Sector(address - magic, block.Size * count, block.Alignment, block) { IsInternal = internalSector }); //if (OnSectorRead != null) //{ // bool internalSector = (address - magic) >= startAddress && (address - magic) < startAddress + length; // OnSectorRead(this, new ReadSectorArgs() // { // Sector = new Sector(address - magic, block.Size * count, block.Alignment, block) { IsInternal = internalSector } // }); //} #endregion int blockAddress = (int)br.BaseStream.Position; #region Check Values for (int i = 0; i < count; i++) { for (int j = 0; j < block.Values.Length; j++) { int offset = blockAddress + (block.Size * i) + block.Values[j].Offset; br.BaseStream.Seek(offset, SeekOrigin.Begin); switch (block.Values[j].Type) { #region Check StringReference Values case Sunfish.Developmental.Value.ValueType.StringId: ValueTypes.StringId stringRef = br.ReadStringReference(); int index = Strings.BinarySearch(map.StringIdNames[stringRef.Index]); if (index < 0) Strings.Insert(~index, map.StringIdNames[stringRef.Index]); if (stringRef.Index < 0 || stringRef.Index > map.StringIdNames.Count || map.StringIdNames[stringRef.Index].Length != stringRef.Length) { //if (OnValueError != null) //{ // OnValueError(this, new ValueErrorArgs() // { // Type = ValueErrorArgs.ErrorType.InvalidStringReference, // Block = block, // ValueIndex = j, // Offset = offset // }); //} } break; #endregion #region Check TagIndex Values case Sunfish.Developmental.Value.ValueType.TagId: ValueTypes.TagIndex tagIndex = br.ReadTagIndex(); if (tagIndex != -1 && !(tagIndex.Index < map.Index.TagInfoCount && tagIndex.Index > 0 && map.Index.TagEntries[tagIndex.Index].Index.Index == tagIndex)) { //if (OnValueError != null) //{ // OnValueError(this, new ValueErrorArgs() // { // Type = ValueErrorArgs.ErrorType.InvalidTagIndex, // Block = block, // ValueIndex = j, // Offset = offset, // Value = tagIndex, // }); //} } break; #endregion #region Check TagReference Value case Sunfish.Developmental.Value.ValueType.TagReference: TagType tagType = br.ReadTagType(); tagIndex = br.ReadTagIndex(); if (tagIndex == -1) { if (tagType == TagType.Null) { break; } bool matched = false; foreach (TagType tt in Sunfish.Index.Types) { if (tt == tagType) matched = true; } if (!matched) { //if (OnValueError != null) //{ // OnValueError(this, new ValueErrorArgs() // { // Type = ValueErrorArgs.ErrorType.InvalidTagType, // Block = block, // ValueIndex = j, // Offset = offset, // Value = tagType, // }); //} } } else if (!(tagIndex.Index < map.Index.TagInfoCount && tagIndex.Index > 0 && map.Index.TagEntries[tagIndex.Index].Index.Index == tagIndex)) { //if (OnValueError != null) //{ // OnValueError(this, new ValueErrorArgs() // { // Type = ValueErrorArgs.ErrorType.InvalidTagIndex, // Block = block, // ValueIndex = j, // Offset = offset, // Value = tagIndex, // }); //} } break; #endregion } } } #endregion #region Cache Raws //if (block.Raws.Length > 0) //{ // for (int i = 0; i < count; i++) // { // foreach (ResourceReference r in block.Raws) // { // ResourceReference raw = r; // raw.Offset0 = blockAddress + (block.Size * i) + r.Offset0; // raw.Offset1 = blockAddress + (block.Size * i) + r.Offset1; // } // } //} #endregion #region Process Nested Blocks if (block.NestedBlocks.Length > 0) { for (int i = 0; i < count; i++) { foreach (Block nestedBlock in block.NestedBlocks) { br.BaseStream.Position = (address - magic) + (i * block.Size) + nestedBlock.Offset; int nestedBlockCount = br.ReadInt32(); if (nestedBlockCount == 0) continue; int nestedBlockAddress = br.ReadInt32(); int offset = nestedBlockAddress - magic; if (nestedBlockCount < 0) { //if (OnValueError != null) //{ // OnValueError(this, new ValueErrorArgs() // { // Type = ValueErrorArgs.ErrorType.InvalidArrayCount, // Offset = offset // }); //} } if (offset < 0 || offset > map.BaseStream.Length) { //if (OnValueError != null) //{ // OnValueError(this, new ValueErrorArgs() // { // Type = ValueErrorArgs.ErrorType.InvalidPointer, // Offset = offset // }); //} } else ProcessBlockRecursive(nestedBlock, map, nestedBlockAddress, nestedBlockCount, ref report); } } } #endregion }
Report ProcessBlock(Block block, Map map, int address, int magic) { br = new BinaryReader(map.BaseStream); this.magic = magic; Report report = new Report(); report.Sectors = new List<Sector>(); ProcessBlockRecursive(block, map, address, 1, ref report); return report; }