Update documentation for the new version.

This commit is contained in:
David Given
2021-05-20 22:41:03 +02:00
parent be97791428
commit 25656d81a1
17 changed files with 293 additions and 380 deletions

View File

@@ -16,8 +16,8 @@ Tested ones are:
I expect the others to work, but haven't tried them; [get in
touch](https://github.com/davidgiven/fluxengine/issues/new) if you have any
news. For ADFS S (single sided 40 track) you'll want `-s :s=0:t=0-79x2`. For
ADFS M (single sided 80 track) you'll want `-s :s=0`.
news. For ADFS S (single sided 40 track) you'll want `--heads 0 --cylinders
0-79x2`. For ADFS M (single sided 80 track) you'll want `--heads 0`.
Be aware that Acorn logical block numbering goes all the way up side 0 and
then all the way up side 1. However, FluxEngine uses traditional disk images
@@ -31,9 +31,9 @@ Reading discs
Just do:
```
fluxengine read adfs
fluxengine read acornadfs
```
You should end up with an `adfs.img` of the appropriate size for your disk
You should end up with an `acornadfs.img` of the appropriate size for your disk
format. This is an alias for `fluxengine read ibm` with preconfigured
parameters.

View File

@@ -7,11 +7,12 @@ special here.
DFS disks are all single sided, but allow the other side of the disk to be
used as another drive. FluxEngine supports these; read one side at a time
with `-s :s=0` or `-s :s=1`.
with `--heads 0` or `--heads 1`.
DFS comes in two varieties, 40 track and 80 track. These should both work.
For 40 track you'll want `-s :t=0-79x2`. Some rare disks are both at the same
time. FluxEngine can read these.
DFS comes in two varieties, 40 track and 80 track. These should both work. For
40 track you'll want `--cylinders 0-79x2`. Some rare disks are both at the same
time. FluxEngine can read these but it requires a bit of fiddling as they have
the same tracks on twice.
Reading discs
-------------
@@ -19,9 +20,9 @@ Reading discs
Just do:
```
fluxengine read dfs
fluxengine read acorndfs
```
You should end up with an `dfs.img` of the appropriate size for your disk
You should end up with an `acorndfs.img` of the appropriate size for your disk
format. This is an alias for `fluxengine read ibm` with preconfigured
parameters.

View File

@@ -36,6 +36,8 @@ Just do:
fluxengine read aeslanier
```
You'll end up with an `aeslanier.img` file.
Useful references
-----------------

View File

@@ -27,7 +27,7 @@ If you want the metadata as well, specify a 528 byte sector size for the
output image:
```
fluxengine read amiga -o amiga.adf:b=528
fluxengine read amiga -o amiga.adf --output.image.img.trackdata.sector_size=528
```
You will end up with a 929280 byte long image which you probably _can't_ use
@@ -43,7 +43,7 @@ Just do:
fluxengine write amiga -i amiga.adf
```
This will rake a normal 901120 byte long ADF file and write it to a DD disk.
This will take a normal 901120 byte long ADF file and write it to a DD disk.
Note that writing to an HD disk will probably not work (this will depend on
your drive and disk and potential FluxEngine bugs I'm still working on ---
please [get in touch](https://github.com/davidgiven/fluxengine/issues/new) if
@@ -53,7 +53,7 @@ If you want to write the metadata as well, specify a 528 byte sector size for
the output image and supply a 929280 byte long file as described above.
```
fluxengine write amiga -i amiga.adf:b=528
fluxengine write amiga -i amiga.adf --input.image.img.trackdata.sector_size=528
```
Useful references

View File

@@ -24,28 +24,26 @@ FluxEngine can also write Atari ST scheme disks.
The syntax is:
fluxengine write ibm -i input.st <options>
fluxengine write <format> -i input.st
The format of `input.st` will vary depending on the kind of disk you're
writing, which is configured by the options. You will almost certainly need to
pass one of these:
`<format>` can be one of these:
- `--ibm-preset-atarist-360`: a 360kB 3.5" disk, with 80 cylinders, 1 side,
and 9 sectors per track.
- `--ibm-preset-atarist-370`: a 370kB 3.5" disk, with 82 cylinders, 1 side,
and 9 sectors per track.
- `--ibm-preset-atarist-400`: a 400kB 3.5" disk, with 80 cylinders, 1 side,
and 10 sectors per track.
- `--ibm-preset-atarist-410`: a 410kB 3.5" disk, with 82 cylinders, 1 side,
and 10 sectors per track.
- `--ibm-preset-atarist-720`: a 720kB 3.5" disk, with 80 cylinders, 2 sides,
and 9 sectors per track.
- `--ibm-preset-atarist-740`: a 740kB 3.5" disk, with 82 cylinders, 2 sides,
and 9 sectors per track.
- `--ibm-preset-atarist-800`: a 800kB 3.5" disk, with 80 cylinders, 2 sides,
and 10 sectors per track.
- `--ibm-preset-atarist-820`: a 820kB 3.5" disk, with 82 cylinders, 2 sides,
and 10 sectors per track.
- `atarist360`: a 360kB 3.5" disk, with 80 cylinders, 1 side, and 9 sectors
per track.
- `atarist370`: a 370kB 3.5" disk, with 82 cylinders, 1 side, and 9 sectors
per track.
- `atarist400`: a 400kB 3.5" disk, with 80 cylinders, 1 side, and 10 sectors
per track.
- `atarist410`: a 410kB 3.5" disk, with 82 cylinders, 1 side, and 10 sectors
per track.
- `atarist720`: a 720kB 3.5" disk, with 80 cylinders, 2 sides, and 9 sectors
per track.
- `atarist740`: a 740kB 3.5" disk, with 82 cylinders, 2 sides, and 9 sectors
per track.
- `atarist800`: a 800kB 3.5" disk, with 80 cylinders, 2 sides, and 10 sectors
per track.
- `atarist820`: a 820kB 3.5" disk, with 82 cylinders, 2 sides, and 10 sectors
per track.
See [the IBM format documentation](disk-ibm.md) for more information.

View File

@@ -41,23 +41,19 @@ Just do:
fluxengine read brother
```
You should end up with a `brother.img` which is 239616 bytes long.
You should end up with a `brother.img` which is either 119808 or 239616 bytes
long.
Writing disks
-------------
Only 240kB disks can be written, currently ( [get in
touch](https://github.com/davidgiven/fluxengine/issues/new) if you want to
write 120kB disks).
Just do:
```
fluxengine write brother
fluxengine write `<format>` -i brother.img
```
...and it'll write a `brother.img` file which is 239616 bytes long to the
disk. (Use `-i` to specify a different input filename.)
...where `<format>` can be `brother120` or `brother240`.
Dealing with misaligned disks
-----------------------------

View File

@@ -55,10 +55,10 @@ fluxengine read ibm
Writing 1581 disks
------------------
These are handled by the IBM writer. Just do:
Just do:
```
fluxengine write ibm --ibm-preset-cbm1581 -i file.img
fluxengine write commodore1581 -i file.img
```
Useful references

View File

@@ -41,27 +41,28 @@ of the disk image will vary depending on the format.
Configuration options you'll want include:
- `--ibm-sector-id-base=N`: specifies the ID of the first sector; this defaults
to 1. Some formats (like the Acorn ones) start at 0. This can't be
autodetected because FluxEngine can't distinguish between a disk which
starts at sector 1 and a disk which starts at sector 0 but all the sector
0s are missing.
- `--decoder.ibm.sector_id_base=N`: specifies the ID of the first sector;
this defaults to 1. Some formats (like the Acorn ones) start at 0. This
can't be autodetected because FluxEngine can't distinguish between a disk
which starts at sector 1 and a disk which starts at sector 0 but all the
sector 0s are missing.
- `--ibm-ignore-side-byte=true|false`: each sector header describes the location of the
sector: sector ID, track and side. Some formats use the wrong side ID, so
the sectors on side 1 are labelled as belonging to side 0. This causes
FluxEngine to see duplicate sectors (as it can't distinguish between the
two sides). This option tells FluxEngine to ignore the side byte completely
and use the physical side instead.
- `--decoder.ibm.ignore_side_byte=true|false`: each sector header describes
the location of the sector: sector ID, track and side. Some formats use the
wrong side ID, so the sectors on side 1 are labelled as belonging to side
0. This causes FluxEngine to see duplicate sectors (as it can't distinguish
between the two sides). This option tells FluxEngine to ignore the side
byte completely and use the physical side instead.
- `--ibm-required-sectors=range`: if you know how many sectors to expect per
track, you can improve reads by telling FluxEngine what to expect here. If
a track is read and a sector on this list is _not_ present, then FluxEngine
assumes the read failed and will retry. This avoids the situation where
FluxEngine can't tell the difference between a sector missing because it's
bad or a sector missing because it was never written in the first place. If
sectors are seen outside the range here, it will still be read. You can use
the same syntax as for track specifiers: e.g. `0-9`, `0,1,2,3`, etc.
- `--decoder.ibm.required_sectors=range`: if you know how many sectors to
expect per track, you can improve reads by telling FluxEngine what to
expect here. If a track is read and a sector on this list is _not_ present,
then FluxEngine assumes the read failed and will retry. This avoids the
situation where FluxEngine can't tell the difference between a sector
missing because it's bad or a sector missing because it was never written
in the first place. If sectors are seen outside the range here, it will
still be read. You can use the same syntax as for track specifiers: e.g.
`0-9`, `0,1,2,3`, etc.
Writing disks
@@ -69,54 +70,15 @@ Writing disks
FluxEngine can also write IBM scheme disks. Unfortunately the format is
incredibly flexible and you need to specify every single parameter, which
makes things slightly awkward.
makes things slightly awkward. Preconfigured profiles are available.
The syntax is:
fluxengine write ibm -i input.img <options>
fluxengine write <format> -i input.img <options>
The format of `input.img` will vary depending on the kind of disk you're
writing, which is configured by the options. There are some presets, which
you will almost certainly want to use if possible:
- `--ibm-preset-720`: a standard 720kB DS DD 3.5" disk, with 80 cylinders,
2 sides, and 9 sectors per track.
- `--ibm-preset-1440`: a standard 1440kB DS HD 3.5" disk, with 80
cylinders, 2 sides, and 18 sectors per track.
These options simply preset the following, lower-level options. Note that
options are processed left to right, so it's possible to use a preset and
then change some settings. To see the values for a preset, simply append
`--help`.
- `--ibm-track-length-ms=N`: one disk rotation, in milliseconds. This is used
to determine whether all the data will fit on a track or not. `fluxengine
rpm` will tell you this; it'll be 200 for a normal 3.5" drive and 166 for a
normal 5.25" drive.
- `--ibm-sector-size=N`: the size of a sector, in bytes. Must be a power of
two.
- `--ibm-emit-iam=true|false`: whether to emit the IAM record at the top of
the track. The standard format requires it, but it's ignored by absolutely
everyone and you can fit a bit more data on the disk without it.
- `--ibm-start-sector-id=N`: the sector ID of the first sector. Normally 1,
except for non-standard formats like Acorn's, which use 0.
- `--ibm-use-fm=true|false`: uses FM rather than MFM.
- `--ibm-idam-byte=N`: the sixteen-bit raw bit pattern used for the IDAM ID
byte. Big-endian, clock bit first.
- `--ibm-dam-byte-N`: the sixteen-bit raw bit pattern used for the DAM ID
byte. Big-endian, clock bit first.
- `--ibm-gap0-bytes=N`: the size of gap 0 in bytes (between the start of
the track and the IAM record).
- `--ibm-gap1-bytes=N`: the size of gap 1 in bytes (between the IAM record
and the first sector record).
- `--ibm-gap2-bytes=N`: the size of gap 2 in bytes (between each sector
record and the data record).
- `--ibm-gap3-bytes=N`: the size of gap 3 in bytes (between the data record
and the next sector record).
- `--ibm-sector-skew=0123...`: a string representing the order in which to
write sectors: each character represents on sector, with `0` being the
first (always, regardless of `--ibm-start-sector-id` above). Sectors 10 and
above are represented as letters from `A` up.
The common PC formats are `ibm720` and `ibm1440`, but there are _many_ others,
and there's too many configuration options to usefully list. Try `fluxengine
write ibm1440 --config` to see a sample configuration.
Mixed-format disks
------------------
@@ -127,26 +89,12 @@ FM encoded and will be read by the machine's ROM; those tracks contain new
floppy drive handling code capable of coping with MFM data, and so the rest of
the disk will use that, allowing them to store more data.
FluxEngine copes with these fine, but the disk images are a bit weird. If track
0 is FM and contains five sectors, but track 1 is MFM with nine sectors (MFM is
more efficient and the sectors are physically smaller, allowing you to get more
on), then the resulting image will have nine sectors per track... but track 0
will only contain data in the first five.
FluxEngine can read these fine, but it tends to get a bit confused when it sees
tracks with differing numbers of sectors --- if track 0 has 32 sectors but
track 1 has 16, it will assume that sectors 16..31 are missing on track 1 and
size the image file accordingly. This can be worked around by specifying the
size of each track; see the `eco1` read profile for an example.
This is typically what you want as it makes locating the sectors in the image
easier, but emulators will typically require a different format. Please [get
Writing can be made to work too, but there is currently no example. Please [get
in touch](https://github.com/davidgiven/fluxengine/issues/new) if you have
specific requirements (nothing's come up yet). Alternatively, you can tell
FluxEngine to write a [`.ldbs`
file](http://www.seasip.info/Unix/LibDsk/ldbs.html) and then use
[libdsk](http://www.seasip.info/Unix/LibDsk/) to convert it to something
useful.
One easy option when reading these is to simply read the two sections of the
disk into two different image files.
FluxEngine can write these too, but in two different passes with different
options. It's possible to assemble a flux file by judicious use of `-D
something.flux --merge`, which can then be written in a single pass with
`fluxengine writeflux`, but it's usually not worth the bother: just write the
boot tracks, then write the data tracks, possibly with a script for automation.
specific requirements (nothing's come up yet).

View File

@@ -55,10 +55,10 @@ You should end up with a `mac.diskcopy` file which is compatible with DiskCopy
different sizes and the odd sector size. If you use a normal `.img` file, then
FluxEngine will store them in a simple 524 x 12 x 2 x 80 layout, with holes
where missing sectors should be; this was easiest, but is unlikely to work with
most Mac emulators and other software. In these files, the 12 bytes of
metadata _follow_ the 512 bytes of user payload in the sector image. If you
don't want it, specify a geometry in the output file with a 512-byte sectore
size like `-o mac.img:c=80:h=1:s=12:b=512`.
most Mac emulators and other software. In these files, the 12 bytes of metadata
_follow_ the 512 bytes of user payload in the sector image. If you don't want
it, specify that you want 512-byte sectors with
`--output.image.img.trackdata.sector_size=512`.
Writing discs
-------------

View File

@@ -28,8 +28,8 @@ fluxengine read micropolis
You should end up with a `micropolis.img` which is 630784 bytes long (for a
normal DD disk). The image is written in CHS order, but HCS is generally used
by CP/M tools so the image needs to be post-processed. For only half-full disks
or single-sided disks, you can use `-s :s=0` to read only one side of the disk
which works around the problem.
or single-sided disks, you can use `--heads 0` to read only one side of the
disk which works around the problem.
The [CP/M BIOS](https://www.seasip.info/Cpm/bios.html) defined SELDSK, SETTRK,
and SETSEC, but no function to select the head/side. Double-sided floppies

View File

@@ -47,10 +47,10 @@ fluxengine read mx
You should end up with an `mx.img` which will vary in length depending on the format. The default is double-sided 80-track. For the other formats, use:
* single-sided 40-track: `-s :s=0:t=0-79x2`
* double-sided 40-track: `-s :s=0-1:t=0-79x2`
* single-sided 40-track: `-s :s=0:t=0-79`
* double-sided 40-track: `-s :s=0-1:t=0-79`
* single-sided 40-track: `--cylinders 0-79x2 --heads 0`
* double-sided 40-track: `--cylinders 0-79x2 --heads 0-1`
* single-sided 80-track: `--cylinders 0-79 --heads 0`
* double-sided 80-track: `--cylinders 0-79 --heads 0-1`
Useful references

View File

@@ -22,16 +22,16 @@ Reading discs
Just do:
```
fluxengine read ibm
fluxengine read ibm -o trs80.jv3
```
You should end up with an `ibm.img` of the appropriate size. It's a simple
array of sectors in JV1 format.
You should end up with an `trs80.jv3` of the appropriate size. It's a simple
array of sectors in JV3 format.
If you've got a 40-track disk, use `-s :t=0-79x2`.
If you've got a 40-track disk, use `--cylinders=0-79x2`.
If you've got a single density disk, use `--read-fm=true`. (Double density is
the default.)
If you've got a single density disk, use
`--decoder.ibm.trackdata.read_fm=true`. (Double density is the default.)
Useful references

View File

@@ -20,7 +20,7 @@ fluxengine read victor9k
```
You should end up with an `victor9k.img` which is 774656 bytes long.
if you want the double-sided variety, use `-s :s=0-1`.
if you want the double-sided variety, use `--heads 0-1`.
**Big warning!** The image may not work in an emulator. Victor disk images are
complicated due to the way the tracks are different sizes and the odd sector

View File

@@ -26,7 +26,7 @@ by writing a sequence of timed pulses to the disk, then reading them back and
seeing what the drive actually reports. To use it, do:
```
fluxengine analyse driveresponse -d :d=1:t=0 \
fluxengine analyse driveresponse --cylinder 0 \
--min-interval-us=0 --max-interval-us=30 --interval-step-us=.1 \
--write-img=driveresponse.png
```

View File

@@ -33,7 +33,9 @@ Driver'. Once done, the GreaseWeazle will be visible to the FluxEngine client.
**Important note!** Unfortunately, now, the original GreaseWeazle client won't
work --- you can't use both drivers at once. I'm working on this. To switch
back to the original driver, for using the GreaseWeazle client software
instead, open up Zadig again, go through the same process, but make sure the left Driver box says `WinUSB` and the right one says `USB Serial (CDC)`. Now, when you press 'Replace Driver' the original driver will be restored.
instead, open up Zadig again, go through the same process, but make sure the
left Driver box says `WinUSB` and the right one says `USB Serial (CDC)`. Now,
when you press 'Replace Driver' the original driver will be restored.
What works
----------

View File

@@ -84,7 +84,14 @@ example:
Bits are then found by measuring the interval between pulses on the disk and
comparing to this clock rate.
However, floppy disk drives are extremely analogue devices and not necessarily calibrated very well, and the disk may be warped, or the rubber band which makes the drive work may have lost its bandiness, and so the bits are not necessarily precisely aligned. Because of this, FluxEngine can tolerate a certain amount of error. This is controlled by the `--bit-error-threshold` parameter. Varying this can have magical effects. For example, adding `--bit-error-threshold=0.4` turns the decode into this:
However, floppy disk drives are extremely analogue devices and not necessarily
calibrated very well, and the disk may be warped, or the rubber band which
makes the drive work may have lost its bandiness, and so the bits are not
necessarily precisely aligned. Because of this, FluxEngine can tolerate a
certain amount of error. This is controlled by the
`--decoder.bit_error_threshold` parameter. Varying this can have magical
effects. For example, adding `--decoder.bit_error_threshold=0.4` turns the
decode into this:
```
H.SS Tracks --->
@@ -124,9 +131,9 @@ can actually _increase_ the error rate --- which is why 0.4 isn't the default
That's the most common tuning parameter, but others are available:
`--pulse-debounce-threshold` controls whether FluxEngine ignores pairs of pulses in rapid succession. This is common on some disks (I've observed them on Brother word processor disks).
`--decoder.pulse_debounce_threshold` controls whether FluxEngine ignores pairs of pulses in rapid succession. This is common on some disks (I've observed them on Brother word processor disks).
`--clock-interval-bias` adds a constant bias to the intervals between pulses
`--decoder.clock_interval_bias` adds a constant bias to the intervals between pulses
before doing decodes. This is very occasionally necessary to get clean reads
--- for example, if the machine which wrote the disk always writes pulses
late. If you try this, use very small numbers (e.g. 0.02). Negative values
@@ -145,7 +152,7 @@ of the pulse intervals on the disk. (Note that the tool only works on one
track at a time.)
```
$ fluxengine inspect -s good.flux:t=0:s=0
$ fluxengine inspect -s good.flux -c 0 -h 0
Clock detection histogram:
3.58 737 ▉
3.67 3838 ████▊
@@ -197,7 +204,7 @@ So, what does my Victor 9000 histogram look like? Let's look at the
histogram for a single track:
```
$ fluxengine inspect -s dubious.flux:t=0:s=0
$ fluxengine inspect -s dubious.flux -c 0 -h 0
Clock detection histogram:
1.33 1904 █▉
1.42 21669 ██████████████████████▌

View File

@@ -13,21 +13,28 @@ described below.
### Core concepts
FluxEngine fundamentally takes file system images and puts them on disk; or
reads the disk and produces a file system image.
FluxEngine's job is to read magnetic data (called _flux_) off a disk, decode
it, and emit a filesystem image (called, er, an _image_); or, the other way
round, where an image is read, converted to flux, and written to a disk.
A file system image typically has the extension `.img`. It contains a
sector-by-sector record of the _decoded_ data on the disk. For example, on a
disk with 512 byte sectors, one sector will occupy 512 bytes. These are
typically what you want in everyday life.
typically what you want in everyday life. FluxEngine supports a variety of file
system image formats, including
[LDBS](http://www.seasip.info/Unix/LibDsk/ldbs.html), Macintosh's [DiskCopy
4.2](https://en.wikipedia.org/wiki/Disk_Copy) and some others, including
Amiga's `.adf`, Atari ST's `.st`, and so on.
FluxEngine can also record the raw magnetic data on the disk into a file, which
we call a _flux file_. This contains all the low-level data which the drive
produced as the disk rotated. These are continuous streams of samples from the
disk and are completely useless in day-to-day life. FluxEngine uses its own
format for this, `.flux`, although it's capable of limited interchange with
Kryoflux, Supercard Pro and Catweasel files. A flux file will typically contain
from 80 to 150 kilobytes of data per track.
Flux, however, is different. It represents the actual magnetic data on the
disk. This has to be decoded before anything useful can be done with it (like
turning it into a file system image). It's possible to read the flux data off
the disk and write it to a file, known as a _flux file_, which allows you to
fiddle with the decode parameters without having to touch the disk again, which
might be fragile. FluxEngine supports several different kinds of flux file,
including its own, SuperCard Pro's `.scp` format, and the Kryoflux stream
format. A flux file will typically contain from 80 to 150 kilobytes of data
per track.
In general, FluxEngine can use either a real disk or a flux file
interchangeably: you can specify either at (very nearly) any time. A very
@@ -40,152 +47,190 @@ To use, simply plug your FluxEngine into your computer and run the client. If a
single device is plugged in, it will be automatically detected and used.
If _more_ than one device is plugged in, you need to specify which one to use
with the `--device` parameter, which takes the device serial number as a
with the `--usb.device` parameter, which takes the device serial number as a
parameter. You can find out the serial numbers by running the command without
the `--device` parameter, and if more than one device is attached they will be
listed. The serial number is also shown whenever a connection is made.
the `--usb.device` parameter, and if more than one device is attached they will
be listed. The serial number is also shown whenever a connection is made.
You _can_ work with more than one FluxEngine at the same time, using different
invocations of the client; but be careful of USB bandwidth. If the devices are
connected via the same hub, the bandwidth will be shared.
### Logical and physical tracks
### Basic use
In general, FluxEngine will read one track off disk, and write it to one track
in a file, or vice versa. Sometimes these don't match. Two important FluxEngine
concepts are that of the _physical track_ and the _logical track_.
The FluxEngine client is a command line program. As parameters it takes one or
more words telling it what to do, and then a bunch of configuration options.
Configurations can be specified either on the command line or in text files.
_Physical tracks_ are how FluxEngine locates tracks on the disk. The numbering
used by 80-track drives is always used, even if you actually have a 40-track
drive attached (this actually makes things simpler).
_Logical tracks_ are where the data is in the filesystem. This doesn't need to
match the physical track. The logical track number is usually encoded on the
disk itself in the sector header. FluxEngine uses this for placing the data in
the output file.
The most common situation where these won't match is when you have a 40-track
disk in an 80-track drive. Because each 40-track track is twice the width of an
80-track track, you'll see logical track 0 on physical tracks 0 and 1, and
logical track 1 on physical tracks 2 and 3, and logical track 2 on physical
tracks 4 and 5, etc.
When reading from a disk, this will usually take care of itself as disks are
mostly self-describing --- FluxEngine can tell which logical track data is
located at from the sector header. However, when writing to a disk, this isn't
the case, and you may to supply extra parameters to tell FluxEngine the mapping
from data in the image to physical tracks. This is most likely to happen when
using 40-track disks.
### Source and destination specifiers
When reading from or writing _flux_ (either from or to a real disk, or a flux
file), use the `--source` (`-s`) and `--dest` (`-d`) options to tell FluxEngine
which bits of the disk you want to access. These use a common syntax:
Here are some sample invocations:
```
fluxengine read ibm -s fakedisk.flux:t=0-79:s=0
# Read an PC disk, producing a disk image with the default name (ibm.img),
# autodetecting all parameters
$ fluxengine read ibm
# Write a PC 1440kB disk to drive 1
$ fluxengine write ibm -i image.img -d drive:1
# Read a Eco1 CP/M disk, making a copy of the flux into a file
$ fluxengine read eco1 --copy-flux-to copy.flux -o eco1.ldbs
# Rerun the decode from the flux file, tweaking the parameters
$ fluxengine read eco1 -s copy.flux -o eco1.ldbs --cylinders=1
```
- To access a real disk, leave out the filename (so `:t=0-79:s=0`).
### Configuration
- To access only some tracks, use the `t=` modifier. To access only some
sides, use the `s=` modifier.
Configuration options are reperesented as a hierarchical structure. You can
either put them in a text file and load them from the command line:
- Inside a modifier, you can use a comma separated list of ranges. So
`:t=0-3` and `:t=0,1,2,3` are equivalent.
```
$ cat config.textpb
encoder {
ibm {
trackdata {
emit_iam: false
}
}
}
$ fluxengine write ibm1440 config.textpb -i image.img
```
- When specifying a range, you can also specify the step. For example,
`:t=0-79x2` would be used when accessing a 40-track disk with double
stepping.
...or you can specify them on the command line:
- To read from drive 1 instead of drive 0, use `:d=1`.
```
$ fluxengine write ibm1440 -i image.img --encoder.ibm.trackdata.emit_iam=false
```
- To read from a set of KryoFlux stream files, specify the path to the
directory containing the files _with a trailing slash_; so
`some/files/:t=0-10`. There must be a files for a single disk only
in the directory.
Both the above invocations are equivalent. The text files use [Google's
protobuf syntax](https://developers.google.com/protocol-buffers), which is
hierarchical, type-safe, and easy to read.
Source and destination specifiers work entirely in *physical units*. As
described above, FluxEngine is intended to be connected to an 80 (or 82) track
double sided drive, and these are the units used. If the format you're trying
to access lays out its tracks differently, then you'll need a specifier which
tells FluxEngine how to find those tracks. See the 40-track disk example above.
The `ibm1440` string above is actually a reference to an internal configuration
file containing all the settings for writing PC 1440kB disks. You can see all
these settings by doing:
If you _don't_ specify a modifier, you'll get the default, which should be
sensible for the command you're using.
```
$ fluxengine write ibm1440 --config
```
**Important note:** FluxEngine _always_ uses zero-based units (even if the
disk format says otherwise).
The `--config` option will cause the current configuration to be dumped to the
console, and then the program will halt.
### Input and output specifiers
Going into the details of the configuration is complicated and mostly futile as
it's likely to change as things get modified. Brief but up-to-date information
about each configuration setting is available with the `--doc` option. Note
that not all combinations of settings make sense.
When reading or writing _file system images_, use the `--input` (`-i`) and
`--output` (`-o`) options to specify the file and file format. These use a very
similar syntax to the source and destination specifiers (because they're based
on the same microformat library!) but with different specifiers. Also, the
exact format varies according to the extension:
### The tools
- `.img` or `.adf`: raw sector images in CHS order. Append
`:c=80:h=2:s=9:b=512` to set the geometry; that specifies 80 cylinders, 2
heads, 9 sectors, 512 bytes per sector. For output files (`--output`) the
geometry will be autodetected if left unspecified. For input files you
normally have to specify it.
The FluxEngine program has got multiple sub-tools, each of which performs a
different task. Run each one with `--help` to get a full list of
(non-configuration-setting) options; this describes only basic usage of the
more common tools.
If one logical track does not map directly onto on physical track, you can
change this with `:o=1:t=2`: `o` specifies the offset, and `t` specifies
the step. So, with this format, cylinder 1 in the image will be written to
track 3 on the disk.
- `fluxengine read <profile> -s <flux source> -o <image output>``
Reads flux (possibly from a disk) and decodes it into a file system
image. `<profile>` is a reference to an internal input configuration file
describing the format.
- `.ldbs`: John Elliott's [LDBS disk image
format](http://www.seasip.info/Unix/LibDsk/ldbs.html), which is
consumable by the [libdsk](http://www.seasip.info/Unix/LibDsk/) suite of
tools. This allows things like variable numbers of sectors per track
(e.g. Macintosh or Commodore 64) and also provides information about
whether sectors were read correctly. You can use libdsk to convert this
to other formats, using a command like this:
- `fluxengine write <profile> -i <image input> -d <flux destination>`
Reads a filesystem image and encodes it into flux (possibly writing to a
disk). `<profile>` is a reference to an internal output configuration file
describing the format.
```
$ dsktrans out.ldbs -otype tele out.td0
```
- `fluxengine rawread -s <flux source> -d <flux destination>`
Reads flux (possibly from a disk) and writes it to a flux file without
doing any decoding. You can specify a profile if you want to read a subset
of the disk.
...to convert to TeleDisk format. (Note you have to use dsktrans rather
than dskconv due to a minor bug in the geometry hadnling.)
- `fluxengine rawwrite -s <flux source> -d <flux destination>`
Reads flux from a file and writes it (possibly to a disk) without doing any
encoding. You can specify a profile if you want to write a subset of the
disk.
FluxEngine's LDBS support is currently limited to write only, and
it doesn't store a lot of the more esoteric LDBS features like format
types, timings, and data rates.
- `fluxengine rpm`
Measures the rotation speed of a drive. For hard-sectored disks, you
probably want to add the name of a read profile to configure the number of
sectors.
- `.d64`: the venerable Commodore 64 disk image format as used by the 1540,
1541, etc. This is a special-purpose format due to the weird layout of
1540 disks and while you can use this for non-Commodore disks the result
will be gibberish. Use this to image Commodore 64 disks and load the
result into an emulator.
- `fluxengine seek -c <cylinder>`
Seeks a drive to a particular cylinder.
FluxEngine's D64 support is currently limited to write only. It will work
with up to 40 logical tracks.
There are other tools; try `fluxengine --help`.
- `.diskcopy`: a Macintosh DiskCopy 4.2 file. This is a special-purpose
format due to the weird layout of Mac GCR disks, but it can also support
720kB and 1440kB IBM disks (although there's no real benefit).
**Important note on `rawread` and `rawwrite`:** You can't use these tools to
copy disks, in most circumstances. See [the FAQ](faq.md) for more information.
Also, `rawread` is not guaranteed to read correctly. Floppy disks are
fundamentally unreliable, and random bit errors may occur at any time; these
can only be detected by performing a decode and verifying the checksums on the
sectors. To perform a correct read, it's recommended to do `fluxengine read`
with the `--copy-flux-to` option, to perform a decode to a filesystem image
while also writing to a flux file.
- `.jv3`: a disk image format mainly used by the TRS-80. These images can be
read, but not yet written. You only get the data; the density and DAM bits
are ignored.
### Flux sources and destinations
- `.imd`: a disk image format created by [David Dunfield](http://dunfield.classiccmp.org/img/index.htm).
These images can be read, but not yet written. The stored comment will also
be shown on read. The geometry in the file will be used.
FluxEngine supports a number of ways to get or put flux. When using the `-s` or
`-d` options (for source and destination), you can use any of these strings:
- `drive:<n>` Read from or write to a specific drive.
- `<filename.flux>` Read from or write to a native FluxEngine flux file.
- `<filename.scp>` Read from or write to a Supercard Pro `.scp` flux file.
- `<filename.cwf>` Read from a Catweasel flux file. **Read only.**
- `kryoflux:<directory>` Read from a Kryoflux stream, where `<path>` is the
directory containing the stream files. **Read only.**
- `erase:` Read nothing --- writing this to a disk will magnetically erase
a track. **Read only.**
- `testpattern:` Read a test pattern, which can be written to a disk to
help diagnosis. **Read only.**
- `au:<directory>` Write to a series of `.au` files, one file per track,
which can be loaded into an audio editor (such as Audacity) as a simple
logic analyser. **Write only.**
- `vcd:<directory>` Write to a series of `.vcd` files, one file per track,
which can be loaded into a logic analyser (such as Pulseview) for
analysis. **Write only.**
### Image sources and destinations
FluxEngine also supports a number of file system image formats. When using the
`-i` or `-o` options (for input and output), you can use any of these strings:
- `<filename.adf>`, `<filename.d81>`, `<filename.img>`, `<filename.st>`
Read from or write to a simple headerless image file (all these formats
are the same). This will probably want configuration via the
`input/output.image.img.*` configuration settings to specify all the
parameters.
- `<filename.diskcopy>` Read from or write to a [DiskCopy
4.2](https://en.wikipedia.org/wiki/Disk_Copy) image file, commonly used
by Apple Macintosh emulators.
- `<filename.jv3>` Read from a JV3 image file, commonly used by TRS-80
emulators. **Read only.**
- `<filename.ldbs>` Write to a [LDBS generic image
file](https://www.seasip.info/Unix/LibDsk/ldbs.html). **Write only.**
- `<filename.d64>` Write to a [D64 image
file](http://unusedino.de/ec64/technical/formats/d64.html), commonly used
by Commodore 64 emulators. **Write only.**
### High density disks
High density disks use a different magnetic medium to low and double density
disks, and have different magnetic properties. 3.5" drives can usually
autodetect what kind of medium is inserted into the drive based on the hole
in the disk casing, but 5.25" drives can't. As a result, you need to
explicitly tell FluxEngine on the command line whether you're using a high
density disk or not with the `-H` flag.
autodetect what kind of medium is inserted into the drive based on the hole in
the disk casing, but 5.25" drives can't. As a result, you need to explicitly
tell FluxEngine on the command line whether you're using a high density disk or
not with the `--input/output.flux.drive.high_density` configuration setting.
**If you don't do this, your disks may not read correctly and will _certainly_
fail to write correctly.**
@@ -197,125 +242,38 @@ case, and reading the disk label is much more reliable.
[Lots more information on high density vs double density disks can be found
here.](http://www.retrotechnology.com/herbs_stuff/guzis.html)
### 40-track disks and drives
These require special handling.
- reading a 40-track disk from an 80-track drive: everything should just work
via autodetection.
- writing a 40-track disk to an 80-track drive: you want to write _all
physical tracks_, so `-d :t=0-79`. For `.img` files you will also need `-i
:t=2` to set the mapping between logical tracks in the image and physical
tracks on the disk.
- reading a 40-track disk from a 40-track drive: use `--40-track` to tell
FluxEngine you have a 40-track drive; everything should just work via
autodetection.
- writing a 40-track disk to a 40-track drive: you want to write _even tracks
only_, so `-d :t=0-79x2`, and for `.img` files you will also need `-i
:t=2`.
The `--40-track` or `-4` option tells FluxEngine that it's plugged into a
40-track drive. It will assume that each step of the drive corresponds to two
physical tracks. Only even tracks are accessible in this mode.
### Other important flags
These flags apply to many operations and are useful for modifying the overall
behaviour.
- `--revolutions=X`: when reading, spin the disk X times. X can be a floating
point number. The default is usually 1.25. Some formats default to 1.
Increasing the number will sample more data, and can be useful on dubious
disks to try and get a better read.
- `--input.flux.drive.revolutions=X`: when reading, spin the disk X times. X
can be a floating point number. The default is usually 1.2. Some formats
default to 1. Increasing the number will sample more data, and can be
useful on dubious disks to try and get a better read.
- `--sync-with-index=true|false`: wait for an index pulse before starting to
read the disk. (Ignored for write operations.) By default FluxEngine
doesn't, as it makes reads faster, but when diagnosing disk problems it's
helpful to have all your data start at the same place each time.
- `--input.flux.drive.sync_with_index=true|false`: wait for an index pulse
before starting to read the disk. (Ignored for write operations.) By
default FluxEngine doesn't, as it makes reads faster, but when diagnosing
disk problems it's helpful to have all your data start at the same place
each time.
- `--index-source=X`, `--write-index-source=X`: set the source of index
pulses when reading or writing respectively. This is for use with drives
which don't produce index pulse data. Use 0 to get index pulses from the
drive, 1 to fake 300RPM pulses, or 2 to fake 360RPM pulses. Note this has
no effect on the _drive_, so it doesn't help with flippy disks, but is
- `--input.flux.drive.index_source=X`, `--output.flux.drive.index_source=X`:
set the source of index pulses when reading or writing respectively. This
is for use with drives which don't produce index pulse data. `X` can be
`INDEXMODE_DRIVE` to get index pulses from the drive, `INDEXMODE_300` to
fake 300RPM pulses, or `INDEXMODE_360` to fake 360RPM pulses. Note this
has no effect on the _drive_, so it doesn't help with flippy disks, but is
useful for using very old drives with FluxEngine itself. If you use this
option, then any index marks in the sampled flux are, of course, garbage.
### The commands
The FluxEngine client software is a largely undocumented set of small tools.
You'll have to play with them. They all support `--help`. They're not
installed anywhere and after building you'll find them in the `.obj`
directory.
- `fluxengine erase`: wipes (all or part of) a disk --- erases it without
writing a pulsetrain.
- `fluxengine inspect`: dumps the raw pulsetrain / bitstream to stdout.
Mainly useful for debugging.
- `fluxengine read *`: reads various formats of disk. See the per-format
documentation linked from the table [in the index page](../README.md).
These all take an optional `--write-flux` option which will cause the raw
flux to be written to the specified file as well as the normal decode.
There are various `--dump` options for showing raw data during the decode
process, and `--write-csv` will write a copious CSV report of the state of
every sector in the file in machine-readable format.
- `fluxengine write *`: writes various formats of disk. Again, see the
per-format documentation [in the index page](../README.md).
- `fluxengine writeflux`: writes raw flux files. This is much less useful
than you might think: you can't reliably write flux files read from a disk
to another disk. (See the [FAQ](faq.md) for more information.) It's mainly
useful for flux files synthesised by the other `fluxengine write` commands.
- `fluxengine writetestpattern`: writes regular pulses (at a configurable
interval) to the disk. Useful for testing drive jitter, erasing disks in a
more secure fashion, or simply debugging. Goes well with `fluxengine
inspect`.
- `fluxengine rpm`: measures the RPM of the drive (requires a disk in the
drive). Mainly useful for testing.
- `fluxengine seek`: moves the head. Mainly useful for finding out whether
your drive can seek to track 82. (Mine can't.)
- `fluxengine test bandwidth`: measures your USB throughput. You don't need
a disk in the drive for this one.
- `fluxengine test voltages`: measures your FDD bus signal voltages, which is
useful for testing for termination issues.
- `fluxengine upgradefluxfile`: occasionally I need to upgrade the flux file
format in a non-backwards-compatible way; this tool will upgrade flux files
to the new format.
- `fluxengine convert`: converts files from various formats to various other
formats. The main use of this is probably `fluxengine convert image`, which
will convert a disk image from one format to another.
There are also subcommands for converting Catweasel flux files to
FluxEngine's native format, FluxEngine flux files to various other formats
useful for debugging (including VCD which can be loaded into
[sigrok](http://sigrok.org)), and bidirectional conversion to and from
Supercard Pro `.scp` format.
Commands which normally take `--source` or `--dest` get a sensible default if
left unspecified. `fluxengine read ibm` on its own will read drive 0 and
write an `ibm.img` file.
## Visualisation
When doing a read (either from a real disk or from a flux file) you can use
`--write-csv=output.csv` to write out CSV file containing information about the
location of every sector on the disk. You can then use `fluxengine analyse
layout` to produce a graphical visualisation of this. Here's a IBM PC 1232kB
disk:
When using `fluxengined read` (either from a real disk or from a flux file) you
can use `--decoder.write_csv_to=output.csv` to write out a CSV file containing
information about the location of every sector on the disk. You can then use
`fluxengine analyse layout` to produce a graphical visualisation of this.
Here's a IBM PC 1232kB disk:
![A disk visualisation](./visualiser.jpg)
@@ -343,16 +301,17 @@ containing valuable historical data, and you want to read them.
Typically I do this:
```
$ fluxengine read brother -s :d=0 -o brother.img --write-flux=brother.flux --overwrite --write-csv=brother.csv
$ fluxengine read brother -s drive:0 -o brother.img --copy-flux-to=brother.flux --decoder.write_csv_to=brother.csv
```
This will read the disk in drive 0 and write out an information CSV file. It'll
also copy the flux to `brother.flux` (replacing any old one) and write out an
SVG visualisation. If I then need to tweak the settings, I can rerun the decode
without having to physically touch the disk like this:
also copy the flux to `brother.flux` (replacing any old one) and write out a
CSV file for used when making a visualisation. If I then need to tweak the
settings, I can rerun the decode without having to physically touch the disk
like this:
```
$ fluxengine read brother -s brother.flux -o brother.img --write-svg=brother.svg
$ fluxengine read brother -s brother.flux -o brother.img --decoder.write_csv_to=brother.csv
```
Apart from being drastically faster, this avoids touching the (potentially