mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-31 11:17:01 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			135 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "globals.h"
 | 
						|
#include "fluxmap.h"
 | 
						|
#include "decoders/fluxmapreader.h"
 | 
						|
#include "protocol.h"
 | 
						|
#include "record.h"
 | 
						|
#include "decoders/decoders.h"
 | 
						|
#include "sector.h"
 | 
						|
#include "fb100.h"
 | 
						|
#include "crc.h"
 | 
						|
#include "bytes.h"
 | 
						|
#include "decoders/rawbits.h"
 | 
						|
#include "track.h"
 | 
						|
#include "fmt/format.h"
 | 
						|
#include <string.h>
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
const FluxPattern SECTOR_ID_PATTERN(16, 0xabaa);
 | 
						|
 | 
						|
/* 
 | 
						|
 * Reverse engineered from a dump of the floppy drive's ROM. I have no idea how
 | 
						|
 * it works.
 | 
						|
 * 
 | 
						|
 * LF8BA:
 | 
						|
 *         clra
 | 
						|
 *         staa    X00B0
 | 
						|
 *         staa    X00B1
 | 
						|
 *         ldx     #$8000
 | 
						|
 * LF8C2:  ldaa    $00,x
 | 
						|
 *         inx
 | 
						|
 *         bsr     LF8CF
 | 
						|
 *         cpx     #$8011
 | 
						|
 *         bne     LF8C2
 | 
						|
 *         ldd     X00B0
 | 
						|
 *         rts
 | 
						|
 * LF8CF:
 | 
						|
 *         eora    X00B0
 | 
						|
 *         staa    X00CF
 | 
						|
 *         asla
 | 
						|
 *         asla
 | 
						|
 *         asla
 | 
						|
 *         asla
 | 
						|
 *         eora    X00CF
 | 
						|
 *         staa    X00CF
 | 
						|
 *         rola
 | 
						|
 *         rola
 | 
						|
 *         rola
 | 
						|
 *         tab
 | 
						|
 *         anda    #$F8
 | 
						|
 *         eora    X00B1
 | 
						|
 *         staa    X00B0
 | 
						|
 *         rolb
 | 
						|
 *         rolb
 | 
						|
 *         andb    #$0F
 | 
						|
 *         eorb    X00B0
 | 
						|
 *         stab    X00B0
 | 
						|
 *         rolb
 | 
						|
 *         eorb    X00CF
 | 
						|
 *         stab    X00B1
 | 
						|
 *         rts
 | 
						|
 */
 | 
						|
 | 
						|
static void rol(uint8_t& b, bool& c)
 | 
						|
{
 | 
						|
    bool newc = b & 0x80;
 | 
						|
    b <<= 1;
 | 
						|
    b |= c;
 | 
						|
    c = newc;
 | 
						|
}
 | 
						|
 | 
						|
static uint16_t checksum(const Bytes& bytes)
 | 
						|
{
 | 
						|
    uint8_t crclo = 0;
 | 
						|
    uint8_t crchi = 0;
 | 
						|
    for (uint8_t a : bytes)
 | 
						|
    {
 | 
						|
        a ^= crchi;
 | 
						|
        uint8_t t1 = a;
 | 
						|
        a <<= 4;
 | 
						|
        bool c = a & 0x10;
 | 
						|
        a ^= t1;
 | 
						|
        t1 = a;
 | 
						|
        rol(a, c);
 | 
						|
        rol(a, c);
 | 
						|
        rol(a, c);
 | 
						|
        uint8_t b = a;
 | 
						|
        a &= 0xf8;
 | 
						|
        a ^= crclo;
 | 
						|
        crchi = a;
 | 
						|
        rol(b, c);
 | 
						|
        rol(b, c);
 | 
						|
        b &= 0x0f;
 | 
						|
        b ^= crchi;
 | 
						|
        crchi = b;
 | 
						|
        rol(b, c);
 | 
						|
        b ^= t1;
 | 
						|
        crclo = b;
 | 
						|
    }
 | 
						|
 | 
						|
    return (crchi << 8) | crclo;
 | 
						|
}
 | 
						|
 | 
						|
AbstractDecoder::RecordType Fb100Decoder::advanceToNextRecord()
 | 
						|
{
 | 
						|
	const FluxMatcher* matcher = nullptr;
 | 
						|
	_sector->clock = _fmr->seekToPattern(SECTOR_ID_PATTERN, matcher);
 | 
						|
    if (matcher == &SECTOR_ID_PATTERN)
 | 
						|
		return RecordType::SECTOR_RECORD;
 | 
						|
	return RecordType::UNKNOWN_RECORD;
 | 
						|
}
 | 
						|
 | 
						|
void Fb100Decoder::decodeSectorRecord()
 | 
						|
{
 | 
						|
    auto rawbits = readRawBits(FB100_RECORD_SIZE*16);
 | 
						|
 | 
						|
    const Bytes bytes = decodeFmMfm(rawbits).slice(0, FB100_RECORD_SIZE);
 | 
						|
    ByteReader br(bytes);
 | 
						|
    br.seek(1);
 | 
						|
    const Bytes id = br.read(FB100_ID_SIZE);
 | 
						|
    uint16_t wantIdCrc = br.read_be16();
 | 
						|
    uint16_t gotIdCrc = checksum(id);
 | 
						|
    const Bytes payload = br.read(FB100_PAYLOAD_SIZE);
 | 
						|
    uint16_t wantPayloadCrc = br.read_be16();
 | 
						|
    uint16_t gotPayloadCrc = checksum(payload);
 | 
						|
 | 
						|
    if (wantIdCrc != gotIdCrc)
 | 
						|
        return;
 | 
						|
 | 
						|
    uint8_t abssector = id[2];
 | 
						|
    _sector->logicalTrack = abssector >> 1;
 | 
						|
    _sector->logicalSide = 0;
 | 
						|
    _sector->logicalSector = abssector & 1;
 | 
						|
    _sector->data.writer().append(id.slice(5, 12)).append(payload);
 | 
						|
 | 
						|
    _sector->status = (wantPayloadCrc == gotPayloadCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
						|
} |