mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Add a reverse-engineered checksum routine, and some documentation.
This commit is contained in:
@@ -81,6 +81,7 @@ physical disks with these formats and so know they work.
|
||||
| [Commodore 64 1541](doc/disk-c64.md) | 🦖 | | and probably the other GCR formats |
|
||||
| [Brother 120kB](doc/disk-brother.md) | 🦄 | | |
|
||||
| [Brother 240kB](doc/disk-brother.md) | 🦄 | 🦄 | |
|
||||
| [Brother FB-100](doc/disk-fb100.md) | 🦖 | | Tandy Model 100, Husky Hunter, knitting machines |
|
||||
| [Macintosh 800kB](doc/disk-macintosh.md) | 🦖 | | and probably the 400kB too |
|
||||
| [TRS-80](doc/disk-trs80.md) | 🦖 | | a minor variation of the IBM scheme |
|
||||
{: .datatable }
|
||||
@@ -100,6 +101,7 @@ at least, check the CRC so what data's there is probably good.
|
||||
| [Victor 9000](doc/disk-victor9k.md) | 🦖 | | 8-inch |
|
||||
| [Zilog MCZ](doc/disk-zilogmcz.md) | 🦖 | | 8-inch _and_ hard sectors |
|
||||
{: .datatable }
|
||||
|
||||
### Notes
|
||||
|
||||
- IBM PC disks are the lowest-common-denominator standard. A number of other
|
||||
|
||||
32
doc/disk-fb100.md
Normal file
32
doc/disk-fb100.md
Normal file
@@ -0,0 +1,32 @@
|
||||
Disk: Brother FB-100
|
||||
====================
|
||||
|
||||
The Brother FB-100 is a serial-attached smart floppy drive used by a several
|
||||
different machines for mass storage, including the Tandy Model 100 and
|
||||
clones, the Husky Hunter 2, and (bizarrely) several knitting machines. It was
|
||||
usually rebadged, sometimes with a cheap paper label stuck over the Brother
|
||||
logo: the most common variant appears to be the Tandy Portable Disk Drive or
|
||||
TPDD:
|
||||
|
||||
<a href="http://www.old-computers.com/museum/computer.asp?c=233&st=1"> <img src="tdpp.jpg" alt="A Tandy Portable Disk Drive"/></a>
|
||||
|
||||
It's a bit of an oddball: the disk encoding is FM with a very custom record
|
||||
scheme: 40-track single-sided 3.5" disks storing 100kB or so each. Each track
|
||||
had only _two_ sectors, each 1280 bytes, but with an additional 17 bytes of
|
||||
ID data used for filesystem management.
|
||||
|
||||
There was also apparently a TPDD-2 which could store twice as much data, but
|
||||
I don't have access to one of those disks.
|
||||
|
||||
Reading discs
|
||||
-------------
|
||||
|
||||
Just do:
|
||||
|
||||
```
|
||||
.obj/fe-readfb100
|
||||
```
|
||||
|
||||
You should end up with an `fb11.img` of the appropriate size. It's a simple
|
||||
array of 80 1297-byte sectors (17 bytes for the ID record plus 1280 bytes for
|
||||
the data).
|
||||
@@ -30,6 +30,89 @@ static bool search(const RawBits& rawbits, size_t& cursor)
|
||||
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)
|
||||
{
|
||||
@@ -58,14 +141,19 @@ void Fb100Decoder::decodeToSectors(const RawBits& rawbits, unsigned,
|
||||
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 = Sector::BAD_CHECKSUM;
|
||||
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));
|
||||
|
||||
Reference in New Issue
Block a user