mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-31 11:17:01 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			84 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "lib/globals.h"
 | 
						|
#include "lib/decoders/decoders.h"
 | 
						|
#include "arch/mx/mx.h"
 | 
						|
#include "lib/crc.h"
 | 
						|
#include "lib/fluxmap.h"
 | 
						|
#include "lib/decoders/fluxmapreader.h"
 | 
						|
#include "lib/sector.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:
 | 
						|
 *         0         0         f         3 decoded nibbles
 | 
						|
 *  0 0  0 0  0 0  0 0  1 1  1 1  0 0  1 1
 | 
						|
 * 1010 1010 1010 1010 1111 1111 1010 1111
 | 
						|
 *    a    a    a    a    f    f    a    f encoded nibbles
 | 
						|
 */
 | 
						|
const FluxPattern ID_PATTERN(32, 0xaaaaffaf);
 | 
						|
 | 
						|
class MxDecoder : public Decoder
 | 
						|
{
 | 
						|
public:
 | 
						|
    MxDecoder(const DecoderProto& config): Decoder(config) {}
 | 
						|
 | 
						|
    void beginTrack() override
 | 
						|
    {
 | 
						|
        _clock = _sector->clock = seekToPattern(ID_PATTERN);
 | 
						|
        _currentSector = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    nanoseconds_t advanceToNextRecord() override
 | 
						|
    {
 | 
						|
        if (_currentSector == 11)
 | 
						|
        {
 | 
						|
            /* That was the last sector on the disk. */
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
        else
 | 
						|
            return _clock;
 | 
						|
    }
 | 
						|
 | 
						|
    void decodeSectorRecord() override
 | 
						|
    {
 | 
						|
        /* Skip the ID pattern and track word, which is only present on the
 | 
						|
         * first sector. We don't trust the track word because some driver
 | 
						|
         * don't write it correctly. */
 | 
						|
 | 
						|
        if (_currentSector == 0)
 | 
						|
            readRawBits(64);
 | 
						|
 | 
						|
        auto bits = readRawBits((SECTOR_SIZE + 2) * 16);
 | 
						|
        auto bytes = decodeFmMfm(bits).slice(0, SECTOR_SIZE + 2);
 | 
						|
 | 
						|
        uint16_t gotChecksum = 0;
 | 
						|
        ByteReader br(bytes);
 | 
						|
        for (int i = 0; i < (SECTOR_SIZE / 2); i++)
 | 
						|
            gotChecksum += br.read_be16();
 | 
						|
        uint16_t wantChecksum = br.read_be16();
 | 
						|
 | 
						|
        _sector->logicalTrack = _sector->physicalTrack;
 | 
						|
        _sector->logicalSide = _sector->physicalSide;
 | 
						|
        _sector->logicalSector = _currentSector;
 | 
						|
        _sector->data = bytes.slice(0, SECTOR_SIZE).swab();
 | 
						|
        _sector->status =
 | 
						|
            (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
						|
        _currentSector++;
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    nanoseconds_t _clock;
 | 
						|
    int _currentSector;
 | 
						|
};
 | 
						|
 | 
						|
std::unique_ptr<Decoder> createMxDecoder(const DecoderProto& config)
 | 
						|
{
 | 
						|
    return std::unique_ptr<Decoder>(new MxDecoder(config));
 | 
						|
}
 |