mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Convert the MX decoder.
This commit is contained in:
@@ -23,53 +23,73 @@ const int SECTOR_SIZE = 256;
|
|||||||
*/
|
*/
|
||||||
const FluxPattern ID_PATTERN(32, 0xaaaaffaf);
|
const FluxPattern ID_PATTERN(32, 0xaaaaffaf);
|
||||||
|
|
||||||
void MxDecoder::beginTrack()
|
class MxDecoder : public AbstractDecoder
|
||||||
{
|
{
|
||||||
_currentSector = -1;
|
public:
|
||||||
_clock = 0;
|
MxDecoder(const DecoderProto& config):
|
||||||
|
AbstractDecoder(config)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void beginTrack()
|
||||||
|
{
|
||||||
|
_currentSector = -1;
|
||||||
|
_clock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordType advanceToNextRecord()
|
||||||
|
{
|
||||||
|
if (_currentSector == -1)
|
||||||
|
{
|
||||||
|
/* First sector in the track: look for the sync marker. */
|
||||||
|
const FluxMatcher* matcher = nullptr;
|
||||||
|
_sector->clock = _clock = _fmr->seekToPattern(ID_PATTERN, matcher);
|
||||||
|
readRawBits(32); /* skip the ID mark */
|
||||||
|
_logicalTrack = decodeFmMfm(readRawBits(32)).slice(0, 32).reader().read_be16();
|
||||||
|
}
|
||||||
|
else if (_currentSector == 10)
|
||||||
|
{
|
||||||
|
/* That was the last sector on the disk. */
|
||||||
|
return UNKNOWN_RECORD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise we assume the clock from the first sector is still valid.
|
||||||
|
* The decoder framwork will automatically stop when we hit the end of
|
||||||
|
* the track. */
|
||||||
|
_sector->clock = _clock;
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentSector++;
|
||||||
|
return SECTOR_RECORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decodeSectorRecord()
|
||||||
|
{
|
||||||
|
auto bits = readRawBits((SECTOR_SIZE+2)*16);
|
||||||
|
auto bytes = decodeFmMfm(bits).slice(0, SECTOR_SIZE+2).swab();
|
||||||
|
|
||||||
|
uint16_t gotChecksum = 0;
|
||||||
|
ByteReader br(bytes);
|
||||||
|
for (int i=0; i<(SECTOR_SIZE/2); i++)
|
||||||
|
gotChecksum += br.read_le16();
|
||||||
|
uint16_t wantChecksum = br.read_le16();
|
||||||
|
|
||||||
|
_sector->logicalTrack = _logicalTrack;
|
||||||
|
_sector->logicalSide = _track->physicalSide;
|
||||||
|
_sector->logicalSector = _currentSector;
|
||||||
|
_sector->data = bytes.slice(0, SECTOR_SIZE);
|
||||||
|
_sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nanoseconds_t _clock;
|
||||||
|
int _currentSector;
|
||||||
|
int _logicalTrack;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<AbstractDecoder> createMxDecoder(const DecoderProto& config)
|
||||||
|
{
|
||||||
|
return std::unique_ptr<AbstractDecoder>(new MxDecoder(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractDecoder::RecordType MxDecoder::advanceToNextRecord()
|
|
||||||
{
|
|
||||||
if (_currentSector == -1)
|
|
||||||
{
|
|
||||||
/* First sector in the track: look for the sync marker. */
|
|
||||||
const FluxMatcher* matcher = nullptr;
|
|
||||||
_sector->clock = _clock = _fmr->seekToPattern(ID_PATTERN, matcher);
|
|
||||||
readRawBits(32); /* skip the ID mark */
|
|
||||||
_logicalTrack = decodeFmMfm(readRawBits(32)).slice(0, 32).reader().read_be16();
|
|
||||||
}
|
|
||||||
else if (_currentSector == 10)
|
|
||||||
{
|
|
||||||
/* That was the last sector on the disk. */
|
|
||||||
return UNKNOWN_RECORD;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Otherwise we assume the clock from the first sector is still valid.
|
|
||||||
* The decoder framwork will automatically stop when we hit the end of
|
|
||||||
* the track. */
|
|
||||||
_sector->clock = _clock;
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentSector++;
|
|
||||||
return SECTOR_RECORD;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MxDecoder::decodeSectorRecord()
|
|
||||||
{
|
|
||||||
auto bits = readRawBits((SECTOR_SIZE+2)*16);
|
|
||||||
auto bytes = decodeFmMfm(bits).slice(0, SECTOR_SIZE+2).swab();
|
|
||||||
|
|
||||||
uint16_t gotChecksum = 0;
|
|
||||||
ByteReader br(bytes);
|
|
||||||
for (int i=0; i<(SECTOR_SIZE/2); i++)
|
|
||||||
gotChecksum += br.read_le16();
|
|
||||||
uint16_t wantChecksum = br.read_le16();
|
|
||||||
|
|
||||||
_sector->logicalTrack = _logicalTrack;
|
|
||||||
_sector->logicalSide = _track->physicalSide;
|
|
||||||
_sector->logicalSector = _currentSector;
|
|
||||||
_sector->data = bytes.slice(0, SECTOR_SIZE);
|
|
||||||
_sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
|
||||||
}
|
|
||||||
|
|||||||
18
arch/mx/mx.h
18
arch/mx/mx.h
@@ -3,24 +3,6 @@
|
|||||||
|
|
||||||
#include "decoders/decoders.h"
|
#include "decoders/decoders.h"
|
||||||
|
|
||||||
class MxDecoderProto;
|
|
||||||
|
|
||||||
class MxDecoder : public AbstractDecoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MxDecoder(const MxDecoderProto&) {}
|
|
||||||
virtual ~MxDecoder() {}
|
|
||||||
|
|
||||||
void beginTrack();
|
|
||||||
RecordType advanceToNextRecord();
|
|
||||||
void decodeSectorRecord();
|
|
||||||
|
|
||||||
private:
|
|
||||||
nanoseconds_t _clock;
|
|
||||||
int _currentSector;
|
|
||||||
int _logicalTrack;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern std::unique_ptr<AbstractDecoder> createMxDecoder(const DecoderProto& config);
|
extern std::unique_ptr<AbstractDecoder> createMxDecoder(const DecoderProto& config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ std::unique_ptr<AbstractDecoder> AbstractDecoder::create(const DecoderProto& con
|
|||||||
{ DecoderProto::kIbm, createIbmDecoder },
|
{ DecoderProto::kIbm, createIbmDecoder },
|
||||||
{ DecoderProto::kMacintosh, createMacintoshDecoder },
|
{ DecoderProto::kMacintosh, createMacintoshDecoder },
|
||||||
{ DecoderProto::kMicropolis, createMicropolisDecoder },
|
{ DecoderProto::kMicropolis, createMicropolisDecoder },
|
||||||
|
{ DecoderProto::kMx, createMxDecoder },
|
||||||
};
|
};
|
||||||
|
|
||||||
auto decoder = decoders.find(config.format_case());
|
auto decoder = decoders.find(config.format_case());
|
||||||
@@ -57,9 +58,6 @@ std::unique_ptr<AbstractDecoder> AbstractDecoder::create(const DecoderProto& con
|
|||||||
{
|
{
|
||||||
switch (config.format_case())
|
switch (config.format_case())
|
||||||
{
|
{
|
||||||
case DecoderProto::kMx:
|
|
||||||
return std::unique_ptr<AbstractDecoder>(new MxDecoder(config.mx()));
|
|
||||||
|
|
||||||
case DecoderProto::kTids990:
|
case DecoderProto::kTids990:
|
||||||
return std::unique_ptr<AbstractDecoder>(new Tids990Decoder(config.tids990()));
|
return std::unique_ptr<AbstractDecoder>(new Tids990Decoder(config.tids990()));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user