mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
76 lines
2.1 KiB
C++
76 lines
2.1 KiB
C++
#include "globals.h"
|
|
#include "decoders/decoders.h"
|
|
#include "mx/mx.h"
|
|
#include "crc.h"
|
|
#include "fluxmap.h"
|
|
#include "decoders/fluxmapreader.h"
|
|
#include "sector.h"
|
|
#include "record.h"
|
|
#include "track.h"
|
|
#include <string.h>
|
|
|
|
const int SECTOR_SIZE = 256;
|
|
|
|
/*
|
|
* MX disks are a bunch of sectors glued together with no gaps or sync markers,
|
|
* following a single beginning-of-track synchronisation and identification
|
|
* sequence.
|
|
*/
|
|
|
|
/* FM beginning of track marker:
|
|
* 1010 1010 1010 1010 1111 1111 1010 1111
|
|
* a a a a f f a f
|
|
*/
|
|
const FluxPattern ID_PATTERN(32, 0xaaaaffaf);
|
|
|
|
void MxDecoder::beginTrack()
|
|
{
|
|
_currentSector = -1;
|
|
_clock = 0;
|
|
}
|
|
|
|
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;
|
|
}
|