From 326969e488162bf36c5e0f7e545d810861e3b9ba Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 11 Jul 2021 12:34:40 +0200 Subject: [PATCH] Clean up the Amiga decoder. --- arch/amiga/amiga.h | 14 +----- arch/amiga/decoder.cc | 100 +++++++++++++++++++++++---------------- lib/decoders/decoders.cc | 17 +++++++ lib/decoders/decoders.h | 3 ++ 4 files changed, 81 insertions(+), 53 deletions(-) diff --git a/arch/amiga/amiga.h b/arch/amiga/amiga.h index ace04fae..139c87e2 100644 --- a/arch/amiga/amiga.h +++ b/arch/amiga/amiga.h @@ -15,18 +15,6 @@ class SectorSet; class AmigaDecoderProto; class AmigaEncoderProto; -class AmigaDecoder : public AbstractDecoder -{ -public: - AmigaDecoder(const AmigaDecoderProto&) {} - virtual ~AmigaDecoder() {} - - RecordType advanceToNextRecord(); - void decodeSectorRecord(); - - std::set requiredSectors(Track& track) const; -}; - class AmigaEncoder : public AbstractEncoder { public: @@ -41,6 +29,8 @@ private: const AmigaEncoderProto& _config; }; +extern std::unique_ptr createAmigaDecoder(const DecoderProto& config); + extern uint32_t amigaChecksum(const Bytes& bytes); extern Bytes amigaInterleave(const Bytes& input); extern Bytes amigaDeinterleave(const uint8_t*& input, size_t len); diff --git a/arch/amiga/decoder.cc b/arch/amiga/decoder.cc index 10e45cd1..9d05df25 100644 --- a/arch/amiga/decoder.cc +++ b/arch/amiga/decoder.cc @@ -8,6 +8,7 @@ #include "amiga.h" #include "bytes.h" #include "fmt/format.h" +#include "lib/decoders/decoders.pb.h" #include #include @@ -21,47 +22,64 @@ static const FluxPattern SECTOR_PATTERN(48, AMIGA_SECTOR_RECORD); -AbstractDecoder::RecordType AmigaDecoder::advanceToNextRecord() +class AmigaDecoder : public AbstractDecoder { - _sector->clock = _fmr->seekToPattern(SECTOR_PATTERN); - if (_fmr->eof() || !_sector->clock) - return UNKNOWN_RECORD; - return SECTOR_RECORD; -} - -void AmigaDecoder::decodeSectorRecord() -{ - const auto& rawbits = readRawBits(AMIGA_RECORD_SIZE*16); - if (rawbits.size() < (AMIGA_RECORD_SIZE*16)) - return; - const auto& rawbytes = toBytes(rawbits).slice(0, AMIGA_RECORD_SIZE*2); - const auto& bytes = decodeFmMfm(rawbits).slice(0, AMIGA_RECORD_SIZE); - - const uint8_t* ptr = bytes.begin() + 3; - - Bytes header = amigaDeinterleave(ptr, 4); - Bytes recoveryinfo = amigaDeinterleave(ptr, 16); - - _sector->logicalTrack = header[1] >> 1; - _sector->logicalSide = header[1] & 1; - _sector->logicalSector = header[2]; - - uint32_t wantedheaderchecksum = amigaDeinterleave(ptr, 4).reader().read_be32(); - uint32_t gotheaderchecksum = amigaChecksum(rawbytes.slice(6, 40)); - if (gotheaderchecksum != wantedheaderchecksum) - return; - - uint32_t wanteddatachecksum = amigaDeinterleave(ptr, 4).reader().read_be32(); - uint32_t gotdatachecksum = amigaChecksum(rawbytes.slice(62, 1024)); - - _sector->data.clear(); - _sector->data.writer().append(amigaDeinterleave(ptr, 512)).append(recoveryinfo); - _sector->status = (gotdatachecksum == wanteddatachecksum) ? Sector::OK : Sector::BAD_CHECKSUM; -} - -std::set AmigaDecoder::requiredSectors(Track& track) const -{ - static std::set sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - return sectors; +public: + AmigaDecoder(const DecoderProto& config): + AbstractDecoder(config), + _config(config.amiga()) + {} + + RecordType advanceToNextRecord() + { + _sector->clock = _fmr->seekToPattern(SECTOR_PATTERN); + if (_fmr->eof() || !_sector->clock) + return UNKNOWN_RECORD; + return SECTOR_RECORD; + } + + void decodeSectorRecord() + { + const auto& rawbits = readRawBits(AMIGA_RECORD_SIZE*16); + if (rawbits.size() < (AMIGA_RECORD_SIZE*16)) + return; + const auto& rawbytes = toBytes(rawbits).slice(0, AMIGA_RECORD_SIZE*2); + const auto& bytes = decodeFmMfm(rawbits).slice(0, AMIGA_RECORD_SIZE); + + const uint8_t* ptr = bytes.begin() + 3; + + Bytes header = amigaDeinterleave(ptr, 4); + Bytes recoveryinfo = amigaDeinterleave(ptr, 16); + + _sector->logicalTrack = header[1] >> 1; + _sector->logicalSide = header[1] & 1; + _sector->logicalSector = header[2]; + + uint32_t wantedheaderchecksum = amigaDeinterleave(ptr, 4).reader().read_be32(); + uint32_t gotheaderchecksum = amigaChecksum(rawbytes.slice(6, 40)); + if (gotheaderchecksum != wantedheaderchecksum) + return; + + uint32_t wanteddatachecksum = amigaDeinterleave(ptr, 4).reader().read_be32(); + uint32_t gotdatachecksum = amigaChecksum(rawbytes.slice(62, 1024)); + + _sector->data.clear(); + _sector->data.writer().append(amigaDeinterleave(ptr, 512)).append(recoveryinfo); + _sector->status = (gotdatachecksum == wanteddatachecksum) ? Sector::OK : Sector::BAD_CHECKSUM; + } + + std::set requiredSectors(Track& track) const + { + static std::set sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + return sectors; + } + +private: + const AmigaDecoderProto& _config; +}; + +std::unique_ptr createAmigaDecoder(const DecoderProto& config) +{ + return std::unique_ptr(new AmigaDecoder(config)); } diff --git a/lib/decoders/decoders.cc b/lib/decoders/decoders.cc index e1473c07..86f4aead 100644 --- a/lib/decoders/decoders.cc +++ b/lib/decoders/decoders.cc @@ -27,6 +27,22 @@ #include "fmt/format.h" #include +std::unique_ptr AbstractDecoder::create(const DecoderProto& config) +{ + static const std::map(const DecoderProto&)>> decoders = + { + { DecoderProto::kAmiga, createAmigaDecoder }, + }; + + auto decoder = decoders.find(config.format_case()); + if (decoder == decoders.end()) + Error() << "no decoder specified"; + + return (decoder->second)(config); +} + +#if 0 std::unique_ptr AbstractDecoder::create(const DecoderProto& config) { switch (config.format_case()) @@ -79,6 +95,7 @@ std::unique_ptr AbstractDecoder::create(const DecoderProto& con return std::unique_ptr(); } +#endif void AbstractDecoder::decodeToSectors(Track& track) { diff --git a/lib/decoders/decoders.h b/lib/decoders/decoders.h index 555d127a..452dd476 100644 --- a/lib/decoders/decoders.h +++ b/lib/decoders/decoders.h @@ -31,6 +31,9 @@ static inline Bytes decodeFmMfm(const std::vector bits) class AbstractDecoder { public: + AbstractDecoder() {} // REMOVE ME + AbstractDecoder(const DecoderProto& config) {} + virtual ~AbstractDecoder() {} static std::unique_ptr create(const DecoderProto& config);