Convert the Macintosh decoder.

This commit is contained in:
David Given
2021-07-11 15:58:40 +02:00
parent 25ebad2448
commit 928ffbd7af
4 changed files with 90 additions and 97 deletions

View File

@@ -184,5 +184,3 @@ std::unique_ptr<AbstractDecoder> createIbmDecoder(const DecoderProto& config)
return std::unique_ptr<AbstractDecoder>(new IbmDecoder(config));
}

View File

@@ -124,85 +124,98 @@ uint8_t decode_side(uint8_t side)
return !!(side & 0x20);
}
AbstractDecoder::RecordType MacintoshDecoder::advanceToNextRecord()
class MacintoshDecoder : public AbstractDecoder
{
const FluxMatcher* matcher = nullptr;
_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
if (matcher == &SECTOR_RECORD_PATTERN)
return SECTOR_RECORD;
if (matcher == &DATA_RECORD_PATTERN)
return DATA_RECORD;
return UNKNOWN_RECORD;
}
public:
MacintoshDecoder(const DecoderProto& config):
AbstractDecoder(config)
{}
void MacintoshDecoder::decodeSectorRecord()
RecordType advanceToNextRecord()
{
const FluxMatcher* matcher = nullptr;
_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
if (matcher == &SECTOR_RECORD_PATTERN)
return SECTOR_RECORD;
if (matcher == &DATA_RECORD_PATTERN)
return DATA_RECORD;
return UNKNOWN_RECORD;
}
void decodeSectorRecord()
{
/* Skip ID (as we know it's a MAC_SECTOR_RECORD). */
readRawBits(24);
/* Read header. */
auto header = toBytes(readRawBits(7*8)).slice(0, 7);
uint8_t encodedTrack = decode_data_gcr(header[0]);
if (encodedTrack != (_track->physicalTrack & 0x3f))
return;
uint8_t encodedSector = decode_data_gcr(header[1]);
uint8_t encodedSide = decode_data_gcr(header[2]);
uint8_t formatByte = decode_data_gcr(header[3]);
uint8_t wantedsum = decode_data_gcr(header[4]);
if (encodedSector > 11)
return;
_sector->logicalTrack = _track->physicalTrack;
_sector->logicalSide = decode_side(encodedSide);
_sector->logicalSector = encodedSector;
uint8_t gotsum = (encodedTrack ^ encodedSector ^ encodedSide ^ formatByte) & 0x3f;
if (wantedsum == gotsum)
_sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
}
void decodeDataRecord()
{
auto id = toBytes(readRawBits(24)).reader().read_be24();
if (id != MAC_DATA_RECORD)
return;
/* Read data. */
readRawBits(8); /* skip spare byte */
auto inputbuffer = toBytes(readRawBits(MAC_ENCODED_SECTOR_LENGTH*8))
.slice(0, MAC_ENCODED_SECTOR_LENGTH);
for (unsigned i=0; i<inputbuffer.size(); i++)
inputbuffer[i] = decode_data_gcr(inputbuffer[i]);
_sector->status = Sector::BAD_CHECKSUM;
Bytes userData = decode_crazy_data(inputbuffer, _sector->status);
_sector->data.clear();
_sector->data.writer().append(userData.slice(12, 512)).append(userData.slice(0, 12));
}
std::set<unsigned> requiredSectors(Track& track) const
{
int count;
if (track.physicalTrack < 16)
count = 12;
else if (track.physicalTrack < 32)
count = 11;
else if (track.physicalTrack < 48)
count = 10;
else if (track.physicalTrack < 64)
count = 9;
else
count = 8;
std::set<unsigned> sectors;
while (count--)
sectors.insert(count);
return sectors;
}
};
std::unique_ptr<AbstractDecoder> createMacintoshDecoder(const DecoderProto& config)
{
/* Skip ID (as we know it's a MAC_SECTOR_RECORD). */
readRawBits(24);
/* Read header. */
auto header = toBytes(readRawBits(7*8)).slice(0, 7);
uint8_t encodedTrack = decode_data_gcr(header[0]);
if (encodedTrack != (_track->physicalTrack & 0x3f))
return;
uint8_t encodedSector = decode_data_gcr(header[1]);
uint8_t encodedSide = decode_data_gcr(header[2]);
uint8_t formatByte = decode_data_gcr(header[3]);
uint8_t wantedsum = decode_data_gcr(header[4]);
if (encodedSector > 11)
return;
_sector->logicalTrack = _track->physicalTrack;
_sector->logicalSide = decode_side(encodedSide);
_sector->logicalSector = encodedSector;
uint8_t gotsum = (encodedTrack ^ encodedSector ^ encodedSide ^ formatByte) & 0x3f;
if (wantedsum == gotsum)
_sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
}
void MacintoshDecoder::decodeDataRecord()
{
auto id = toBytes(readRawBits(24)).reader().read_be24();
if (id != MAC_DATA_RECORD)
return;
/* Read data. */
readRawBits(8); /* skip spare byte */
auto inputbuffer = toBytes(readRawBits(MAC_ENCODED_SECTOR_LENGTH*8))
.slice(0, MAC_ENCODED_SECTOR_LENGTH);
for (unsigned i=0; i<inputbuffer.size(); i++)
inputbuffer[i] = decode_data_gcr(inputbuffer[i]);
_sector->status = Sector::BAD_CHECKSUM;
Bytes userData = decode_crazy_data(inputbuffer, _sector->status);
_sector->data.clear();
_sector->data.writer().append(userData.slice(12, 512)).append(userData.slice(0, 12));
}
std::set<unsigned> MacintoshDecoder::requiredSectors(Track& track) const
{
int count;
if (track.physicalTrack < 16)
count = 12;
else if (track.physicalTrack < 32)
count = 11;
else if (track.physicalTrack < 48)
count = 10;
else if (track.physicalTrack < 64)
count = 9;
else
count = 8;
std::set<unsigned> sectors;
while (count--)
sectors.insert(count);
return sectors;
return std::unique_ptr<AbstractDecoder>(new MacintoshDecoder(config));
}

View File

@@ -18,19 +18,6 @@ class Fluxmap;
class MacintoshDecoderProto;
class MacintoshEncoderProto;
class MacintoshDecoder : public AbstractDecoder
{
public:
MacintoshDecoder(const MacintoshDecoderProto&) {}
virtual ~MacintoshDecoder() {}
RecordType advanceToNextRecord();
void decodeSectorRecord();
void decodeDataRecord();
std::set<unsigned> requiredSectors(Track& track) const;
};
class MacintoshEncoder : public AbstractEncoder
{
public:

View File

@@ -41,6 +41,7 @@ std::unique_ptr<AbstractDecoder> AbstractDecoder::create(const DecoderProto& con
{ DecoderProto::kF85, createDurangoF85Decoder },
{ DecoderProto::kFb100, createFb100Decoder },
{ DecoderProto::kIbm, createIbmDecoder },
{ DecoderProto::kMacintosh, createMacintoshDecoder },
};
auto decoder = decoders.find(config.format_case());
@@ -55,12 +56,6 @@ std::unique_ptr<AbstractDecoder> AbstractDecoder::create(const DecoderProto& con
{
switch (config.format_case())
{
case DecoderProto::kIbm:
return std::unique_ptr<AbstractDecoder>(new IbmDecoder(config.ibm()));
case DecoderProto::kMacintosh:
return std::unique_ptr<AbstractDecoder>(new MacintoshDecoder(config.macintosh()));
case DecoderProto::kMicropolis:
return std::unique_ptr<AbstractDecoder>(new MicropolisDecoder(config.micropolis()));