mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
161 lines
3.6 KiB
C++
161 lines
3.6 KiB
C++
#include "globals.h"
|
|
#include "fluxmap.h"
|
|
#include "protocol.h"
|
|
#include "record.h"
|
|
#include "decoders.h"
|
|
#include "sector.h"
|
|
#include "fb100.h"
|
|
#include "crc.h"
|
|
#include "bytes.h"
|
|
#include "rawbits.h"
|
|
#include "fmt/format.h"
|
|
#include <string.h>
|
|
#include <algorithm>
|
|
|
|
static bool search(const RawBits& rawbits, size_t& cursor)
|
|
{
|
|
uint16_t fifo = 0;
|
|
|
|
while (cursor < rawbits.size())
|
|
{
|
|
fifo = (fifo << 1) | rawbits[cursor++];
|
|
|
|
if (fifo == 0xabaa)
|
|
{
|
|
cursor -= 16;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
|
|
void Fb100Decoder::decodeToSectors(const RawBits& rawbits, unsigned,
|
|
RawRecordVector& rawrecords, SectorVector& sectors)
|
|
{
|
|
size_t cursor = 0;
|
|
|
|
for (;;)
|
|
{
|
|
if (!search(rawbits, cursor))
|
|
break;
|
|
|
|
unsigned record_start = cursor;
|
|
cursor = std::min(cursor + FB100_RECORD_SIZE*16, rawbits.size());
|
|
std::vector<bool> recordbits(rawbits.begin() + record_start, rawbits.begin() + cursor);
|
|
|
|
rawrecords.push_back(
|
|
std::unique_ptr<RawRecord>(
|
|
new RawRecord(
|
|
record_start,
|
|
recordbits.begin(),
|
|
recordbits.end())
|
|
)
|
|
);
|
|
|
|
const Bytes bytes = decodeFmMfm(recordbits).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)
|
|
continue;
|
|
|
|
uint8_t abssector = id[2];
|
|
uint8_t track = abssector >> 1;
|
|
uint8_t sectorid = abssector & 1;
|
|
|
|
int status = (wantPayloadCrc == gotPayloadCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
|
|
auto sector = std::unique_ptr<Sector>(
|
|
new Sector(status, track, 0, sectorid, payload));
|
|
sectors.push_back(std::move(sector));
|
|
}
|
|
} |