| 575 | } |
| 576 | |
| 577 | bool Reader::getSubRecordHeader() |
| 578 | { |
| 579 | bool result = false; |
| 580 | // NOTE: some SubRecords have 0 dataSize (e.g. SUB_RDSD in one of REC_REGN records in Oblivion.esm). |
| 581 | if (mCtx.recordHeader.record.dataSize - mCtx.recordRead >= sizeof(mCtx.subRecordHeader)) |
| 582 | { |
| 583 | result = getExact(mCtx.subRecordHeader); |
| 584 | // HACK: below assumes sub-record data will be read or skipped in full; |
| 585 | // this hack aims to avoid updating mCtx.recordRead each time anything is read |
| 586 | mCtx.recordRead += (sizeof(mCtx.subRecordHeader) + mCtx.subRecordHeader.dataSize); |
| 587 | } |
| 588 | else if (mCtx.recordRead > mCtx.recordHeader.record.dataSize) |
| 589 | { |
| 590 | // try to correct any overshoot, seek to the end of the expected data |
| 591 | // this will only work if mCtx.subRecordHeader.dataSize was fully read or skipped |
| 592 | // (i.e. it will only correct mCtx.subRecordHeader.dataSize being incorrect) |
| 593 | // TODO: not tested |
| 594 | std::uint32_t overshoot = (std::uint32_t)mCtx.recordRead - mCtx.recordHeader.record.dataSize; |
| 595 | |
| 596 | std::size_t pos = mStream->tellg(); |
| 597 | mStream->seekg(pos - overshoot); |
| 598 | |
| 599 | return false; |
| 600 | } |
| 601 | |
| 602 | // Extended storage subrecord redefines the following subrecord's size. |
| 603 | // Would need to redesign the loader to support that, so skip over both subrecords. |
| 604 | if (result && mCtx.subRecordHeader.typeId == ESM::fourCC("XXXX")) |
| 605 | { |
| 606 | std::uint32_t extDataSize; |
| 607 | get(extDataSize); |
| 608 | if (!getSubRecordHeader()) |
| 609 | return false; |
| 610 | |
| 611 | skipSubRecordData(extDataSize); |
| 612 | mCtx.recordRead += extDataSize - mCtx.subRecordHeader.dataSize; |
| 613 | return getSubRecordHeader(); |
| 614 | } |
| 615 | |
| 616 | return result; |
| 617 | } |
| 618 | |
| 619 | void Reader::skipSubRecordData() |
| 620 | { |