diff --git a/arch/amiga/decoder.cc b/arch/amiga/decoder.cc index 6af128d7..9b535112 100644 --- a/arch/amiga/decoder.cc +++ b/arch/amiga/decoder.cc @@ -74,6 +74,11 @@ class AmigaDecoder : public AbstractDecoder return sectors; } + bool recordsSeekable() const override + { + return false; + } + private: const AmigaDecoderProto& _config; nanoseconds_t _clock; diff --git a/lib/decoders/decoders.cc b/lib/decoders/decoders.cc index 633ad594..fde049f5 100644 --- a/lib/decoders/decoders.cc +++ b/lib/decoders/decoders.cc @@ -89,40 +89,42 @@ std::shared_ptr AbstractDecoder::decodeToSectors( /* Read the sector record. */ - Fluxmap::Position before = fmr.tell(); + Fluxmap::Position before_sector = fmr.tell(); decodeSectorRecord(); - Fluxmap::Position after = fmr.tell(); - pushRecord(before, after); + Fluxmap::Position after_sector = fmr.tell(); + pushRecord(before_sector, after_sector); if (_sector->status != Sector::DATA_MISSING) { - _sector->position = before.bytes; - _sector->dataStartTime = before.ns(); - _sector->dataEndTime = after.ns(); + _sector->position = before_sector.bytes; + _sector->dataStartTime = before_sector.ns(); + _sector->dataEndTime = after_sector.ns(); } else { /* The data is in a separate record. */ + Fluxmap::Position before_data = before_sector; + Fluxmap::Position after_data = after_sector; for (;;) { - _sector->headerStartTime = before.ns(); - _sector->headerEndTime = after.ns(); + _sector->headerStartTime = before_data.ns(); + _sector->headerEndTime = after_data.ns(); _sector->clock = advanceToNextRecord(); if (fmr.eof() || !_sector->clock) break; - before = fmr.tell(); + before_data = fmr.tell(); decodeDataRecord(); - after = fmr.tell(); + after_data = fmr.tell(); if (_sector->status != Sector::DATA_MISSING) { - _sector->position = before.bytes; - _sector->dataStartTime = before.ns(); - _sector->dataEndTime = after.ns(); - pushRecord(before, after); + _sector->position = before_data.bytes; + _sector->dataStartTime = before_data.ns(); + _sector->dataEndTime = after_data.ns(); + pushRecord(before_data, after_data); break; } @@ -131,6 +133,13 @@ std::shared_ptr AbstractDecoder::decodeToSectors( } } + /* Allow decode of overlapping records. + * Note that this seeks to after the sector record, but before + * the data record, so it relies on a lone data record being + * ignored. */ + if (this->recordsSeekable()) + fmr.seek(after_sector); + if (_sector->status != Sector::MISSING) _trackdata->sectors.push_back(_sector); } diff --git a/lib/decoders/decoders.h b/lib/decoders/decoders.h index 90e1c544..6d0726f7 100644 --- a/lib/decoders/decoders.h +++ b/lib/decoders/decoders.h @@ -91,6 +91,14 @@ class AbstractDecoder virtual std::set requiredSectors(const Location& location) const; + /* Indicates whether records have a unique start pattern, e.g. whether + * must be read contiguously (Amiga) or can be search for from any + * position (IBM). */ + virtual bool recordsSeekable() const + { + return true; + } + protected: virtual void beginTrack(){}; virtual nanoseconds_t advanceToNextRecord() = 0;