Clean up the Amiga decoder.

This commit is contained in:
David Given
2021-07-11 12:34:40 +02:00
parent 155e8c2a4b
commit 326969e488
4 changed files with 81 additions and 53 deletions

View File

@@ -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<unsigned> requiredSectors(Track& track) const;
};
class AmigaEncoder : public AbstractEncoder
{
public:
@@ -41,6 +29,8 @@ private:
const AmigaEncoderProto& _config;
};
extern std::unique_ptr<AbstractDecoder> 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);

View File

@@ -8,6 +8,7 @@
#include "amiga.h"
#include "bytes.h"
#include "fmt/format.h"
#include "lib/decoders/decoders.pb.h"
#include <string.h>
#include <algorithm>
@@ -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<unsigned> AmigaDecoder::requiredSectors(Track& track) const
{
static std::set<unsigned> 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<unsigned> requiredSectors(Track& track) const
{
static std::set<unsigned> sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
return sectors;
}
private:
const AmigaDecoderProto& _config;
};
std::unique_ptr<AbstractDecoder> createAmigaDecoder(const DecoderProto& config)
{
return std::unique_ptr<AbstractDecoder>(new AmigaDecoder(config));
}

View File

@@ -27,6 +27,22 @@
#include "fmt/format.h"
#include <numeric>
std::unique_ptr<AbstractDecoder> AbstractDecoder::create(const DecoderProto& config)
{
static const std::map<int,
std::function<std::unique_ptr<AbstractDecoder>(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> AbstractDecoder::create(const DecoderProto& config)
{
switch (config.format_case())
@@ -79,6 +95,7 @@ std::unique_ptr<AbstractDecoder> AbstractDecoder::create(const DecoderProto& con
return std::unique_ptr<AbstractDecoder>();
}
#endif
void AbstractDecoder::decodeToSectors(Track& track)
{

View File

@@ -31,6 +31,9 @@ static inline Bytes decodeFmMfm(const std::vector<bool> bits)
class AbstractDecoder
{
public:
AbstractDecoder() {} // REMOVE ME
AbstractDecoder(const DecoderProto& config) {}
virtual ~AbstractDecoder() {}
static std::unique_ptr<AbstractDecoder> create(const DecoderProto& config);