keirf / greaseweazle

Tools for accessing a floppy drive at the raw flux level
The Unlicense
892 stars 90 forks source link

Support for Sinclair QL and Thor discs #391

Open SimonGoodwin opened 6 months ago

SimonGoodwin commented 6 months ago

720K Sinclair QL discs (the most common sort, also standard on CST Thor computers) can be sector-imaged as if they were Atari ST DS media, e.g.

gw read --drive=0 --format=atarist.720 ThorSCSI.img

Not that it really matters (the QL path separator is an underscore) the extension .img seems to be used for images made or used with GoTek drives or Qemulator.

The number of sides, tracks and interleave are all encoded in the first sector, which is 512 bytes for DD and HD media upto 1.44MB capacity. The standard 3.2 MB format uses 2K sectors but it appears Greaseweasel lacks support for ED media and drives, though ED drives can be used to read lower-density floppies, on a real QL with a Gold Card or later controller.

5.25", 3" and 3.5" drives are handled identically. It's common for commercially-distributed discs to be formatted only to the number of tracks required Copy protection is unheard-of. GW 4.1 reports ** FATAL ERROR: Track0 signal absent after seek to cylinder 0 when connected to the drives I use for HD and ED QL media and asked to READ any format, though the RPM test gw rpm --drive=0 works, so I've only been able to check this with 720K discs in DD drives normally used on QL and ZX systems.

This edited snip from section 8.1 of https://www.8bit-wiki.de/fileadmin/8bit-wiki/Sinclair/QL/manual/QDOS%20SMS%20Reference%20Manual.pdf tells you all you need to know to identify the dimensions of a disk.

Interleave is controlled by mapping tables on each disk, typically 1 in 3 with side swapping but 1:1 for speed on scatter loads (normally used for screen images, tasks etc, where the OS reads sectors as they're found and slots them into preallocated memory till it's got the lot) and without the side-swapping for Amiga Qdos, Classic Qdos and other QL implementations that don't rely on the 177x controller.

This standard was based on the original Sinclair Research proposals, and compatibility between the dozen or so different interface manufacturers is 100% as Tony Tebby ended up writing almost all of them.

Floppy disks will be sectored in 512 byte sectors. 5.25" compatible disks will have 9 sectors per track (MFM 200ms rotation), for a 40 track drive, single sided, this gives 180k bytes and for an 80 track drive, double sided, this gives 720k bytes capacity.

Tracks are numbered from 0, sectors on a track are numbered, by ones, from sector 1 immediately after the index mark. The physical format is basically IBM System 34 (8" MFM) with four changes. There is no index mark recorded, the sector length flag is $02, the data record is 512 bytes long, and the write splice gap is increased.

For IBM standard format on MFM recording with 256 bytes sectors, the write splice gap at the end of a data record is 54 bytes. This is increased to 84 bytes allowing for a short term speed variation of + or - 4%. Using this, each sector is recorded in 658 bytes, this sets the gap between sector 9 and 1 to approximately 6250-5922 (328) bytes, allowing a long term speed variation of + or - 2.75%.

Regardless of the physical characteristics, all floppy disks have the same directory structure. Track zero holds the map of sector allocations. The first block of the map is sector 1 side 0 track 0. The first bytes of the sector map hold big-endian information about the format of the rest of the drive:

Bytes 0..3 format ID, usually QL5A, QL5B is rare, as QL5A but no physical-logical translation 4..13 medium name (space filled) 14..15 random number set during format 16..19 count of updates 20..21 free sectors 22..23 good sectors 24..25 total sectors (sectors*tracks) 26..27 sectors per track (<=9) 28..29 sectors per cylinder (e.g. 9 or 18) 30..31 number of tracks (cylinders) 32..33 allocation size (sectors per alloc group) 34..37 current end of directory (block and byte offset) 38..39 sector offset 40..57 logical to physical sector translate 58..75 physical to logical sector translate (standard)

In the logical to physical translate table, the MSB of the translate byte indicates the side number, while the remaining 7 bits give the sector number (numbered from 0 to 8). In the physical to logical translate table the first nine bytes correspond to sectors 0 to 8 on side 0, and the next 9 bytes to sectors 0 to 8 on side 1. (Note that the internal numbering of sectors on a track starts at 0 for convenience in calculation: 1 is added to the sector number immediately before recording or reading).

E.g. for the most common 1 in 3 interleave, 18 sectors per cylinder, in hexadecimal the tables are:

00030680 83860104 07818487 02050882 8588 00060c01 070d0208 0e03090f 040a1005 0b11

For each track an additional offset allows for steps between adjacent tracks. So the final physical sector is calculated as (translated sector + track * sector offset) MOD sectors per track

Hope this helps someone.

keirf commented 6 months ago

I'll have to consider all this, however I will note that "track0 absent after seek to cylinder 0" is often a drive-select issue. You will need to specify --drive=0 on the command line, for a straight ribbon cable and a drive which is jumpered for DS0.

The wiki probably needs an "imaging your first disk" page.

keirf commented 6 months ago

Also, if you have existing images, flux or otherwise, that you would like to use to run gw tools through their paces, you can experiment with gw convert command for transcoding between formats, without even needing Greaseweazle hardware attached! It acts rather like gw read but imports from an image file rather than a physical disk.

SimonGoodwin commented 6 months ago

Yep I used --drive=0 on both my examples above. I think cable-swaps are an IBM-only thing, never seen them on my other micros (but then those tend to support 4 or 8 drives so there's some actual decoding going on).

Those ED drives work when plugged into 1772 based DD controllers - indeed I had to use them at a Crash show when my SAM Coupe prototype (SAM's use one VL1772 per drive) turned its nose up at my DD 3.5" MGT 'lifetime' (sic) drive but was happy to read 800K media with the ED/HD/DD pair I'd taken for my QL. I was careful not to write to DD from the ED drives!

So it's not --drive=0 but maybe some other line the ED drive exposes which upsets GW 4.1 but not WDC controllers (or the VLSI clones of those - I suspect they came bundled with MGT ASICs!). Any other ideas?

I understand about the raw stuff from years programming Paula and a little later dabbling with Jen's PCI/Zorro contraption. I started out with 35TSSSD, 87.5K formatted - a genuine SA400.

Early days for GW but thanks for your help and I hope I can fill in some gaps in the 80s micro media support from my PCW-columnist memories.

Time to get back to my KS2 Spectrum Next now.

keirf commented 6 months ago

ED drives do have some special extra lines, but I think they are only for mode select and not particularly important to Greaseweazle. Or FlashFloppy for that matter, which works okay in PCs which support ED drives. I also have a (few) positive reports about ED support on Greaseweazle. The USB line rate at Full Speed is theoretically too slow but in practice the Greaseweazle v4 has enough RAM to buffer anyway (at least when using latest firmware v1.5). However you're not getting as far as actually trying to read a track...

The drive-head movement should be nothing special in an ED drive. I wonder if ED drives need more juice than can be supplied though a typical USB port when not in a power-delivery mode? Yeah, I'd start by providing external power to the drive. You could also try slowing down the step rate, but default is 10ms/step which I'm sure should be very much slow enough for an ED drive.

SimonGoodwin commented 6 months ago

My drives are all externally powered but it was worth asking. Pretty sure the step rate is 6ms or less, but ditto. I"ll try again at some point, cheers.

keirf commented 6 months ago

I suppose another possibility is that those drives are jumpered DS1 and would respond as --drive=1. But if gw rpm --drive=0 is working, that seems less likely to be the problem. Perhaps this will remain a mystery for now!