Port the Brother decoder to the new *new* architecture.

This commit is contained in:
David Given
2019-04-29 23:28:12 +02:00
parent c0c1121b91
commit 4cc680057e
5 changed files with 156 additions and 93 deletions

View File

@@ -3,22 +3,23 @@
/* Brother word processor format (or at least, one of them) */
#define BROTHER_SECTOR_RECORD 0xFFFFFD57
#define BROTHER_DATA_RECORD 0xFFFFFDDB
#define BROTHER_DATA_RECORD_PAYLOAD 256
#define BROTHER_DATA_RECORD_CHECKSUM 3
#define BROTHER_SECTOR_RECORD 0xFFFFFD57
#define BROTHER_DATA_RECORD 0xFFFFFDDB
#define BROTHER_DATA_RECORD_PAYLOAD 256
#define BROTHER_DATA_RECORD_CHECKSUM 3
#define BROTHER_DATA_RECORD_ENCODED_SIZE 415
class Sector;
class Fluxmap;
class BrotherDecoder : public AbstractSoftSectorDecoder
class BrotherDecoder : public AbstractSimplifiedDecoder
{
public:
virtual ~BrotherDecoder() {}
SectorVector decodeToSectors(
const RawRecordVector& rawRecords, unsigned physicalTrack, unsigned physicalSide);
int recordMatcher(uint64_t fifo) const;
RecordType advanceToNextRecord();
void decodeSectorRecord();
void decodeDataRecord();
};
extern void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor,

View File

@@ -1,6 +1,7 @@
#include "globals.h"
#include "sql.h"
#include "fluxmap.h"
#include "fluxmapreader.h"
#include "decoders.h"
#include "record.h"
#include "brother.h"
@@ -9,6 +10,10 @@
#include "crc.h"
#include <ctype.h>
const FluxPattern SECTOR_RECORD_PATTERN(32, BROTHER_SECTOR_RECORD);
const FluxPattern DATA_RECORD_PATTERN(32, BROTHER_DATA_RECORD);
const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN });
static std::vector<uint8_t> outputbuffer;
/*
@@ -48,89 +53,56 @@ static int decode_header_gcr(uint16_t word)
return -1;
};
SectorVector BrotherDecoder::decodeToSectors(const RawRecordVector& rawRecords, unsigned, unsigned)
AbstractSimplifiedDecoder::RecordType BrotherDecoder::advanceToNextRecord()
{
std::vector<std::unique_ptr<Sector>> sectors;
bool headerIsValid = false;
unsigned nextTrack = 0;
unsigned nextSector = 0;
const FluxMatcher* matcher = nullptr;
_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
if (matcher == &SECTOR_RECORD_PATTERN)
return RecordType::SECTOR_RECORD;
if (matcher == &DATA_RECORD_PATTERN)
return RecordType::DATA_RECORD;
return RecordType::UNKNOWN_RECORD;
}
for (auto& rawrecord : rawRecords)
{
if (rawrecord->data.size() < 64)
{
headerIsValid = false;
continue;
}
void BrotherDecoder::decodeSectorRecord()
{
_fmr->readRawBits(32, _sector->clock);
const auto& rawbits = _fmr->readRawBits(32, _sector->clock);
const auto& bytes = toBytes(rawbits).slice(0, 4);
auto ii = rawrecord->data.cbegin();
uint32_t signature = toBytes(ii, ii+32).reader().read_be32();
switch (signature)
{
case BROTHER_SECTOR_RECORD:
{
headerIsValid = false;
if (rawrecord->data.size() < (32+32))
break;
ByteReader br(bytes);
_sector->logicalTrack = decode_header_gcr(br.read_be16());
_sector->logicalSector = decode_header_gcr(br.read_be16());
const auto& by = toBytes(ii+32, ii+64);
ByteReader br(by);
nextTrack = decode_header_gcr(br.read_be16());
nextSector = decode_header_gcr(br.read_be16());
/* Sanity check the values read; there's no header checksum and
* occasionally we get garbage due to bit errors. */
if (_sector->logicalSector > 11)
return;
if (_sector->logicalTrack > 79)
return;
/* Sanity check the values read; there's no header checksum and
* occasionally we get garbage due to bit errors. */
if (nextSector > 11)
break;
if (nextTrack > 79)
break;
_sector->status = Sector::DATA_MISSING;
}
headerIsValid = true;
break;
}
void BrotherDecoder::decodeDataRecord()
{
_fmr->readRawBits(32, _sector->clock);
case BROTHER_DATA_RECORD:
{
if (!headerIsValid)
break;
const auto& rawbits = _fmr->readRawBits(BROTHER_DATA_RECORD_ENCODED_SIZE*8, _sector->clock);
const auto& rawbytes = toBytes(rawbits).slice(0, BROTHER_DATA_RECORD_ENCODED_SIZE);
Bytes rawbytes = toBytes(rawrecord->data.cbegin()+32, rawrecord->data.cend());
const int totalsize = BROTHER_DATA_RECORD_PAYLOAD + BROTHER_DATA_RECORD_CHECKSUM;
Bytes output;
ByteWriter bw(output);
BitWriter bitw(bw);
for (uint8_t b : rawbytes)
{
uint32_t nibble = decode_data_gcr(b);
bitw.push(nibble, 5);
if (output.size() == totalsize)
break;
}
bitw.flush();
output.resize(totalsize);
Bytes payload = output.slice(0, BROTHER_DATA_RECORD_PAYLOAD);
uint32_t realCrc = crcbrother(payload);
uint32_t wantCrc = output.reader().seek(BROTHER_DATA_RECORD_PAYLOAD).read_be24();
int status = (realCrc == wantCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
auto sector = std::unique_ptr<Sector>(
new Sector(status, nextTrack, 0, nextSector, payload));
sectors.push_back(std::move(sector));
headerIsValid = false;
break;
}
}
Bytes bytes;
ByteWriter bw(bytes);
BitWriter bitw(bw);
for (uint8_t b : rawbytes)
{
uint32_t nibble = decode_data_gcr(b);
bitw.push(nibble, 5);
}
bitw.flush();
return sectors;
}
int BrotherDecoder::recordMatcher(uint64_t fifo) const
{
uint32_t masked = fifo & 0xffffffff;
if ((masked == BROTHER_SECTOR_RECORD) || (masked == BROTHER_DATA_RECORD))
return 32;
return 0;
_sector->data = bytes.slice(0, BROTHER_DATA_RECORD_PAYLOAD);
uint32_t realCrc = crcbrother(_sector->data);
uint32_t wantCrc = bytes.reader().seek(BROTHER_DATA_RECORD_PAYLOAD).read_be24();
_sector->status = (realCrc == wantCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
}

View File

@@ -169,6 +169,72 @@ nanoseconds_t AbstractDecoder::guessClockImpl(Track& track) const
return track.fluxmap->guessClock();
}
void AbstractSimplifiedDecoder::decodeToSectors(Track& track)
{
Sector sector;
sector.physicalSide = track.physicalSide;
sector.physicalTrack = track.physicalTrack;
FluxmapReader fmr(*track.fluxmap);
_track = &track;
_sector = &sector;
_fmr = &fmr;
for (;;)
{
Fluxmap::Position recordStart = sector.position = fmr.tell();
sector.clock = 0;
sector.status = Sector::MISSING;
sector.data.clear();
sector.logicalSector = sector.logicalSide = sector.logicalTrack = 0;
RecordType r = advanceToNextRecord();
if (fmr.eof() || !sector.clock)
return;
if ((r == UNKNOWN_RECORD) || (r == DATA_RECORD))
{
fmr.readNextMatchingOpcode(F_OP_PULSE);
continue;
}
/* Read the sector record. */
recordStart = fmr.tell();
decodeSectorRecord();
pushRecord(recordStart, fmr.tell());
if (sector.status == Sector::DATA_MISSING)
{
/* The data is in a separate record. */
r = advanceToNextRecord();
if (r == DATA_RECORD)
{
recordStart = fmr.tell();
decodeDataRecord();
pushRecord(recordStart, fmr.tell());
}
}
if (sector.status != Sector::MISSING)
track.sectors.push_back(sector);
}
}
void AbstractSimplifiedDecoder::pushRecord(const Fluxmap::Position& start, const Fluxmap::Position& end)
{
Fluxmap::Position here = _fmr->tell();
RawRecord record;
record.physicalSide = _track->physicalSide;
record.physicalTrack = _track->physicalTrack;
record.clock = _sector->clock;
record.position = start;
_fmr->seek(start);
record.data = toBytes(_fmr->readRawBits(end, _sector->clock));
_track->rawrecords.push_back(record);
_fmr->seek(here);
}
void AbstractStatefulDecoder::decodeToSectors(Track& track)
{
Sector sector;

View File

@@ -34,6 +34,30 @@ public:
virtual void decodeToSectors(Track& track) = 0;
};
class AbstractSimplifiedDecoder : public AbstractDecoder
{
public:
enum RecordType
{
SECTOR_RECORD,
DATA_RECORD,
UNKNOWN_RECORD
};
public:
void decodeToSectors(Track& track) override;
void pushRecord(const Fluxmap::Position& start, const Fluxmap::Position& end);
protected:
virtual RecordType advanceToNextRecord() = 0;
virtual void decodeSectorRecord() = 0;
virtual void decodeDataRecord() {};
FluxmapReader* _fmr;
Track* _track;
Sector* _sector;
};
class AbstractStatefulDecoder : public AbstractDecoder
{
public:

View File

@@ -151,15 +151,15 @@ apple2decoderlib = declare_dependency(
include_directories('lib/apple2')
)
#brotherdecoderlib = declare_dependency(
# link_with:
# shared_library('brotherdecoderlib',
# [ 'lib/brother/decoder.cc', ],
# dependencies: [fmtlib, felib, decoderlib, sqlite]),
# include_directories:
# include_directories('lib/brother')
#)
#
brotherdecoderlib = declare_dependency(
link_with:
shared_library('brotherdecoderlib',
[ 'lib/brother/decoder.cc', ],
dependencies: [fmtlib, felib, decoderlib, sqlite]),
include_directories:
include_directories('lib/brother')
)
#brotherencoderlib = declare_dependency(
# link_with:
# shared_library('brotherencoderlib',
@@ -239,7 +239,7 @@ executable('fe-readaeslanier', ['src/fe-readaeslanier.cc'], dependencies
executable('fe-readamiga', ['src/fe-readamiga.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, amigadecoderlib])
executable('fe-readampro', ['src/fe-readampro.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, ibmdecoderlib])
executable('fe-readapple2', ['src/fe-readapple2.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, apple2decoderlib])
#executable('fe-readbrother', ['src/fe-readbrother.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, brotherdecoderlib])
executable('fe-readbrother', ['src/fe-readbrother.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, brotherdecoderlib])
executable('fe-readc64', ['src/fe-readc64.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, c64decoderlib])
executable('fe-readdfs', ['src/fe-readdfs.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, ibmdecoderlib])
executable('fe-readf85', ['src/fe-readf85.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, f85decoderlib])