From bf8f6ae68739e9441a5f8402074252905bc9ea56 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 21 Apr 2021 00:41:36 +0200 Subject: [PATCH 1/5] Add imagereader offset and step modes, and hardware forty-track modes. Not sure this is the right way to do it. --- doc/using.md | 5 +++++ lib/dataspec.cc | 14 +++++++++++--- lib/dataspec.h | 8 +++++++- lib/fluxsink/hardwarefluxsink.cc | 14 +++++++++++++- lib/fluxsource/hardwarefluxsource.cc | 15 ++++++++++++++- lib/imagereader/imgimagereader.cc | 6 +++++- tests/dataspec.cc | 19 ++++++++++++++++--- 7 files changed, 71 insertions(+), 10 deletions(-) diff --git a/doc/using.md b/doc/using.md index d077ae56..895c82c1 100644 --- a/doc/using.md +++ b/doc/using.md @@ -104,6 +104,11 @@ exact format varies according to the extension: geometry will be autodetected if left unspecified. For input files you normally have to specify it. + If one image 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. + - `.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 diff --git a/lib/dataspec.cc b/lib/dataspec.cc index d3daa482..aa41bc1b 100644 --- a/lib/dataspec.cc +++ b/lib/dataspec.cc @@ -162,6 +162,8 @@ ImageSpec::ImageSpec(const DataSpec& spec) if (!spec.has("c") && !spec.has("h") && !spec.has("s") && !spec.has("b")) { cylinders = heads = sectors = bytes = 0; + physicalOffset = 0; + physicalStep = 1; initialised = false; } else @@ -170,6 +172,8 @@ ImageSpec::ImageSpec(const DataSpec& spec) heads = spec.at("h").only(); sectors = spec.at("s").only(); bytes = spec.at("b").only(); + physicalOffset = spec.atOr("o", 0); + physicalStep = spec.atOr("t", 1); initialised = true; } } @@ -181,18 +185,22 @@ ImageSpec::ImageSpec(const DataSpec& spec) for (const auto& e : spec.modifiers) { const auto name = e.second.name; - if ((name != "c") && (name != "h") && (name != "s") && (name != "b")) - Error() << fmt::format("unknown fluxspec modifier '{}'", name); + static const std::set modifiers { "c", "h", "s", "b", "o", "t" }; + if (modifiers.find(name) == modifiers.end()) + Error() << fmt::format("unknown imagespec modifier '{}'", name); } } ImageSpec::ImageSpec(const std::string filename, - unsigned cylinders, unsigned heads, unsigned sectors, unsigned bytes): + unsigned cylinders, unsigned heads, unsigned sectors, unsigned bytes, + int physicalOffset, int physicalStep): filename(filename), cylinders(cylinders), heads(heads), sectors(sectors), bytes(bytes), + physicalOffset(physicalOffset), + physicalStep(physicalStep), initialised(true) {} diff --git a/lib/dataspec.h b/lib/dataspec.h index c527ea19..6f1dcc06 100644 --- a/lib/dataspec.h +++ b/lib/dataspec.h @@ -48,6 +48,9 @@ public: const Modifier& at(const std::string& mod) const; bool has(const std::string& mod) const; + unsigned atOr(const std::string& mod, unsigned value) const + { return has(mod) ? at(mod).only() : value; } + std::string filename; std::map modifiers; }; @@ -82,7 +85,8 @@ class ImageSpec public: ImageSpec(const DataSpec& dataspec); ImageSpec(const std::string filename, - unsigned cylinders, unsigned heads, unsigned sectors, unsigned bytes); + unsigned cylinders, unsigned heads, unsigned sectors, unsigned bytes, + int physicalOffset=0, int physicalStep=1); public: std::string filename; @@ -90,6 +94,8 @@ public: unsigned heads; unsigned sectors; unsigned bytes; + int physicalOffset; + int physicalStep; bool initialised : 1; }; diff --git a/lib/fluxsink/hardwarefluxsink.cc b/lib/fluxsink/hardwarefluxsink.cc index ee20e863..243d5967 100644 --- a/lib/fluxsink/hardwarefluxsink.cc +++ b/lib/fluxsink/hardwarefluxsink.cc @@ -21,6 +21,11 @@ static IntFlag hardSectorCount( "number of hard sectors on the disk (0=soft sectors)", 0); +static BoolFlag fortyTrack( + { "--write-40-track" }, + "indicates a 40 track drive when writing", + false); + void setHardwareFluxSinkDensity(bool high_density) { ::high_density = high_density; @@ -57,7 +62,14 @@ public: void writeFlux(int track, int side, Fluxmap& fluxmap) { usbSetDrive(_drive, high_density, indexMode); - usbSeek(track); + if (fortyTrack) + { + if (track & 1) + Error() << "cannot write to odd physical tracks in 40-track mode"; + usbSeek(track / 2); + } + else + usbSeek(track); return usbWrite(side, fluxmap.rawBytes(), _hardSectorThreshold); } diff --git a/lib/fluxsource/hardwarefluxsource.cc b/lib/fluxsource/hardwarefluxsource.cc index c2de1e19..9581fcc1 100644 --- a/lib/fluxsource/hardwarefluxsource.cc +++ b/lib/fluxsource/hardwarefluxsource.cc @@ -29,6 +29,11 @@ static IntFlag hardSectorCount( "number of hard sectors on the disk (0=soft sectors)", 0); +static BoolFlag fortyTrack( + { "--read-40-track" }, + "indicates a 40 track drive for reading", + false); + static bool high_density = false; void setHardwareFluxSourceDensity(bool high_density) @@ -60,7 +65,15 @@ public: std::unique_ptr readFlux(int track, int side) { usbSetDrive(_drive, high_density, indexMode); - usbSeek(track); + if (fortyTrack) + { + if (track & 1) + Error() << "cannot read from odd physical tracks in 40-track mode"; + usbSeek(track / 2); + } + else + usbSeek(track); + Bytes data = usbRead( side, synced, revolutions * _oneRevolution, _hardSectorThreshold); auto fluxmap = std::make_unique(); diff --git a/lib/imagereader/imgimagereader.cc b/lib/imagereader/imgimagereader.cc index be194e88..fad2721a 100644 --- a/lib/imagereader/imgimagereader.cc +++ b/lib/imagereader/imgimagereader.cc @@ -30,6 +30,9 @@ public: spec.sectors, spec.bytes, spec.cylinders * trackSize / 1024) << std::endl; + if ((spec.physicalOffset != 0) || (spec.physicalStep != 1)) + std::cout << fmt::format("logical to physical track mapping: physical = logical*{} + {}\n", + spec.physicalStep, spec.physicalOffset); SectorSet sectors; for (int track = 0; track < spec.cylinders; track++) @@ -46,7 +49,8 @@ public: std::unique_ptr& sector = sectors.get(track, head, sectorId); sector.reset(new Sector); sector->status = Sector::OK; - sector->logicalTrack = sector->physicalTrack = track; + sector->logicalTrack = track; + sector->physicalTrack = track*spec.physicalStep + spec.physicalOffset; sector->logicalSide = sector->physicalSide = head; sector->logicalSector = sectorId; sector->data = data; diff --git a/tests/dataspec.cc b/tests/dataspec.cc index 25cdd4cb..e239251d 100644 --- a/tests/dataspec.cc +++ b/tests/dataspec.cc @@ -111,15 +111,28 @@ static void test_fluxspec(void) static void test_imagespec(void) { - DataSpec spec("foo:c=9:h=2:s=99:b=256"); - { + DataSpec spec("foo:c=9:h=2:s=99:b=256"); ImageSpec ispec(spec); assert(ispec.filename == "foo"); assert(ispec.cylinders == 9); assert(ispec.heads == 2); assert(ispec.sectors == 99); - assert(ispec.bytes = 256); + assert(ispec.bytes == 256); + assert(ispec.physicalOffset == 0); + assert(ispec.physicalStep == 1); + } + + { + DataSpec spec("foo:c=9:h=2:s=99:b=256:o=2:t=9"); + ImageSpec ispec(spec); + assert(ispec.filename == "foo"); + assert(ispec.cylinders == 9); + assert(ispec.heads == 2); + assert(ispec.sectors == 99); + assert(ispec.bytes == 256); + assert(ispec.physicalOffset == 2); + assert(ispec.physicalStep == 9); } } From d00681f62304bb60e9cefaf9a25035dcf42ba12c Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 7 May 2021 00:21:13 +0200 Subject: [PATCH 2/5] Make the new 40-track flag common between source and sink. --- lib/flaggroups/fluxsourcesink.cc | 12 ++++++++++++ lib/flaggroups/fluxsourcesink.h | 12 ++++++++++++ lib/fluxsink/hardwarefluxsink.cc | 9 +++------ lib/fluxsource/hardwarefluxsource.cc | 9 +++------ mkninja.sh | 1 + 5 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 lib/flaggroups/fluxsourcesink.cc create mode 100644 lib/flaggroups/fluxsourcesink.h diff --git a/lib/flaggroups/fluxsourcesink.cc b/lib/flaggroups/fluxsourcesink.cc new file mode 100644 index 00000000..4a98511b --- /dev/null +++ b/lib/flaggroups/fluxsourcesink.cc @@ -0,0 +1,12 @@ +#include "globals.h" +#include "flags.h" +#include "flaggroups/fluxsourcesink.h" + +FlagGroup fluxSourceSinkFlags; + +BoolFlag fluxSourceSinkFortyTrack( + { "--40-track" }, + "indicates a 40 track drive", + false); + + diff --git a/lib/flaggroups/fluxsourcesink.h b/lib/flaggroups/fluxsourcesink.h new file mode 100644 index 00000000..9f947173 --- /dev/null +++ b/lib/flaggroups/fluxsourcesink.h @@ -0,0 +1,12 @@ +#ifndef FLUXSOURCESINK_H +#define FLUXSOURCESINK_H + +#include "flags.h" + +extern FlagGroup fluxSourceSinkFlags; + +extern BoolFlag fluxSourceSinkFortyTrack; + +#endif + + diff --git a/lib/fluxsink/hardwarefluxsink.cc b/lib/fluxsink/hardwarefluxsink.cc index 243d5967..f02da4ee 100644 --- a/lib/fluxsink/hardwarefluxsink.cc +++ b/lib/fluxsink/hardwarefluxsink.cc @@ -3,9 +3,11 @@ #include "fluxmap.h" #include "usb/usb.h" #include "fluxsink/fluxsink.h" +#include "flaggroups/fluxsourcesink.h" #include "fmt/format.h" FlagGroup hardwareFluxSinkFlags = { + &fluxSourceSinkFlags, &usbFlags, }; @@ -21,11 +23,6 @@ static IntFlag hardSectorCount( "number of hard sectors on the disk (0=soft sectors)", 0); -static BoolFlag fortyTrack( - { "--write-40-track" }, - "indicates a 40 track drive when writing", - false); - void setHardwareFluxSinkDensity(bool high_density) { ::high_density = high_density; @@ -62,7 +59,7 @@ public: void writeFlux(int track, int side, Fluxmap& fluxmap) { usbSetDrive(_drive, high_density, indexMode); - if (fortyTrack) + if (fluxSourceSinkFortyTrack) { if (track & 1) Error() << "cannot write to odd physical tracks in 40-track mode"; diff --git a/lib/fluxsource/hardwarefluxsource.cc b/lib/fluxsource/hardwarefluxsource.cc index 9581fcc1..0e51406c 100644 --- a/lib/fluxsource/hardwarefluxsource.cc +++ b/lib/fluxsource/hardwarefluxsource.cc @@ -3,9 +3,11 @@ #include "fluxmap.h" #include "usb/usb.h" #include "fluxsource/fluxsource.h" +#include "flaggroups/fluxsourcesink.h" #include "fmt/format.h" FlagGroup hardwareFluxSourceFlags = { + &fluxSourceSinkFlags, &usbFlags }; @@ -29,11 +31,6 @@ static IntFlag hardSectorCount( "number of hard sectors on the disk (0=soft sectors)", 0); -static BoolFlag fortyTrack( - { "--read-40-track" }, - "indicates a 40 track drive for reading", - false); - static bool high_density = false; void setHardwareFluxSourceDensity(bool high_density) @@ -65,7 +62,7 @@ public: std::unique_ptr readFlux(int track, int side) { usbSetDrive(_drive, high_density, indexMode); - if (fortyTrack) + if (fluxSourceSinkFortyTrack) { if (track & 1) Error() << "cannot read from odd physical tracks in 40-track mode"; diff --git a/mkninja.sh b/mkninja.sh index 213c3edb..609a81ab 100644 --- a/mkninja.sh +++ b/mkninja.sh @@ -194,6 +194,7 @@ buildlibrary libbackend.a \ lib/decoders/fluxmapreader.cc \ lib/decoders/fmmfm.cc \ lib/encoders/encoders.cc \ + lib/flaggroups/fluxsourcesink.cc \ lib/flags.cc \ lib/fluxmap.cc \ lib/fluxsink/fluxsink.cc \ From e912152784a2aee2eda2c25df40b8e8bce227bba Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 7 May 2021 00:27:10 +0200 Subject: [PATCH 3/5] Common out the high-density flag too. --- lib/flaggroups/fluxsourcesink.cc | 9 ++++++--- lib/flaggroups/fluxsourcesink.h | 3 ++- lib/fluxsink/fluxsink.h | 1 - lib/fluxsink/hardwarefluxsink.cc | 11 ++--------- lib/fluxsource/fluxsource.h | 1 - lib/fluxsource/hardwarefluxsource.cc | 11 ++--------- lib/reader.cc | 6 ------ lib/writer.cc | 7 ------- src/fe-fluxtoau.cc | 5 ----- src/fe-fluxtovcd.cc | 5 ----- 10 files changed, 12 insertions(+), 47 deletions(-) diff --git a/lib/flaggroups/fluxsourcesink.cc b/lib/flaggroups/fluxsourcesink.cc index 4a98511b..832858a5 100644 --- a/lib/flaggroups/fluxsourcesink.cc +++ b/lib/flaggroups/fluxsourcesink.cc @@ -4,9 +4,12 @@ FlagGroup fluxSourceSinkFlags; -BoolFlag fluxSourceSinkFortyTrack( +SettableFlag fluxSourceSinkFortyTrack( { "--40-track" }, - "indicates a 40 track drive", - false); + "indicates a 40 track drive"); + +SettableFlag fluxSourceSinkHighDensity( + { "--high-density", "-H" }, + "set the drive to high density mode"); diff --git a/lib/flaggroups/fluxsourcesink.h b/lib/flaggroups/fluxsourcesink.h index 9f947173..4edd63c0 100644 --- a/lib/flaggroups/fluxsourcesink.h +++ b/lib/flaggroups/fluxsourcesink.h @@ -5,7 +5,8 @@ extern FlagGroup fluxSourceSinkFlags; -extern BoolFlag fluxSourceSinkFortyTrack; +extern SettableFlag fluxSourceSinkFortyTrack; +extern SettableFlag fluxSourceSinkHighDensity; #endif diff --git a/lib/fluxsink/fluxsink.h b/lib/fluxsink/fluxsink.h index b6d4814e..43e77b8a 100644 --- a/lib/fluxsink/fluxsink.h +++ b/lib/fluxsink/fluxsink.h @@ -23,7 +23,6 @@ public: virtual void writeFlux(int track, int side, Fluxmap& fluxmap) = 0; }; -extern void setHardwareFluxSinkDensity(bool high_density); extern void setHardwareFluxSinkHardSectorCount(int sectorCount); #endif diff --git a/lib/fluxsink/hardwarefluxsink.cc b/lib/fluxsink/hardwarefluxsink.cc index f02da4ee..761a8681 100644 --- a/lib/fluxsink/hardwarefluxsink.cc +++ b/lib/fluxsink/hardwarefluxsink.cc @@ -11,8 +11,6 @@ FlagGroup hardwareFluxSinkFlags = { &usbFlags, }; -static bool high_density = false; - static IntFlag indexMode( { "--write-index-mode" }, "index pulse source (0=drive, 1=300 RPM fake source, 2=360 RPM fake source", @@ -23,11 +21,6 @@ static IntFlag hardSectorCount( "number of hard sectors on the disk (0=soft sectors)", 0); -void setHardwareFluxSinkDensity(bool high_density) -{ - ::high_density = high_density; -} - void setHardwareFluxSinkHardSectorCount(int sectorCount) { ::hardSectorCount.setDefaultValue(sectorCount); @@ -41,7 +34,7 @@ public: { if (hardSectorCount != 0) { - usbSetDrive(_drive, high_density, indexMode); + usbSetDrive(_drive, fluxSourceSinkHighDensity, indexMode); std::cerr << "Measuring rotational speed... " << std::flush; nanoseconds_t oneRevolution = usbGetRotationalPeriod(hardSectorCount); _hardSectorThreshold = oneRevolution * 3 / (4 * hardSectorCount); @@ -58,7 +51,7 @@ public: public: void writeFlux(int track, int side, Fluxmap& fluxmap) { - usbSetDrive(_drive, high_density, indexMode); + usbSetDrive(_drive, fluxSourceSinkHighDensity, indexMode); if (fluxSourceSinkFortyTrack) { if (track & 1) diff --git a/lib/fluxsource/fluxsource.h b/lib/fluxsource/fluxsource.h index 12b4fc38..2b2876df 100644 --- a/lib/fluxsource/fluxsource.h +++ b/lib/fluxsource/fluxsource.h @@ -28,7 +28,6 @@ public: }; extern void setHardwareFluxSourceRevolutions(double revolutions); -extern void setHardwareFluxSourceDensity(bool high_density); extern void setHardwareFluxSourceSynced(bool synced); extern void setHardwareFluxSourceHardSectorCount(int sectorCount); diff --git a/lib/fluxsource/hardwarefluxsource.cc b/lib/fluxsource/hardwarefluxsource.cc index 0e51406c..4b510289 100644 --- a/lib/fluxsource/hardwarefluxsource.cc +++ b/lib/fluxsource/hardwarefluxsource.cc @@ -31,20 +31,13 @@ static IntFlag hardSectorCount( "number of hard sectors on the disk (0=soft sectors)", 0); -static bool high_density = false; - -void setHardwareFluxSourceDensity(bool high_density) -{ - ::high_density = high_density; -} - class HardwareFluxSource : public FluxSource { public: HardwareFluxSource(unsigned drive): _drive(drive) { - usbSetDrive(_drive, high_density, indexMode); + usbSetDrive(_drive, fluxSourceSinkHighDensity, indexMode); std::cerr << "Measuring rotational speed... " << std::flush; _oneRevolution = usbGetRotationalPeriod(hardSectorCount); if (hardSectorCount != 0) @@ -61,7 +54,7 @@ public: public: std::unique_ptr readFlux(int track, int side) { - usbSetDrive(_drive, high_density, indexMode); + usbSetDrive(_drive, fluxSourceSinkHighDensity, indexMode); if (fluxSourceSinkFortyTrack) { if (track & 1) diff --git a/lib/reader.cc b/lib/reader.cc index 1ccdde05..3bba8422 100644 --- a/lib/reader.cc +++ b/lib/reader.cc @@ -58,10 +58,6 @@ static IntFlag retries( "How many times to retry each track in the event of a read failure.", 5); -static SettableFlag highDensityFlag( - { "--high-density", "--hd" }, - "set the drive to high density mode"); - static StringFlag csvFile( { "--write-csv" }, "write a CSV report of the disk state", @@ -117,8 +113,6 @@ std::vector> readTracks() std::cout << "Reading from: " << source << std::endl; - setHardwareFluxSourceDensity(highDensityFlag); - if (!destination.get().empty()) { std::cout << "Writing a copy of the flux to " << destination.get() << std::endl; diff --git a/lib/writer.cc b/lib/writer.cc index c7a94176..f1f08a71 100644 --- a/lib/writer.cc +++ b/lib/writer.cc @@ -27,10 +27,6 @@ static DataSpecFlag input( "input image file to read from", ""); -static SettableFlag highDensityFlag( - { "--high-density", "-H" }, - "set the drive to high density mode"); - static sqlite3* outdb; void setWriterDefaultDest(const std::string& dest) @@ -60,9 +56,6 @@ void writeTracks( std::cout << "Writing to: " << dest << std::endl; - setHardwareFluxSourceDensity(highDensityFlag); - setHardwareFluxSinkDensity(highDensityFlag); - std::shared_ptr fluxSink = FluxSink::create(spec); for (const auto& location : spec.locations) diff --git a/src/fe-fluxtoau.cc b/src/fe-fluxtoau.cc index 18b75160..cd837289 100644 --- a/src/fe-fluxtoau.cc +++ b/src/fe-fluxtoau.cc @@ -22,10 +22,6 @@ static StringFlag output( "output AU file to write", "output.au"); -static SettableFlag highDensityFlag( - { "--high-density", "--hd" }, - "set the drive to high density mode"); - static SettableFlag withIndex( { "--with-index" }, "place index markers in the right hand channel"); @@ -41,7 +37,6 @@ int mainConvertFluxToAu(int argc, const char* argv[]) const auto& location = *(locations.begin()); std::cerr << "Reading source flux...\n"; - setHardwareFluxSourceDensity(highDensityFlag); std::shared_ptr fluxsource = FluxSource::create(spec); const auto& fluxmap = fluxsource->readFlux(location.track, location.side); unsigned totalTicks = fluxmap->ticks() + 2; diff --git a/src/fe-fluxtovcd.cc b/src/fe-fluxtovcd.cc index 800b0644..5e556754 100644 --- a/src/fe-fluxtovcd.cc +++ b/src/fe-fluxtovcd.cc @@ -22,10 +22,6 @@ static StringFlag output( "output VCD file to write", "output.vcd"); -static SettableFlag highDensityFlag( - { "--high-density", "--hd" }, - "set the drive to high density mode"); - int mainConvertFluxToVcd(int argc, const char* argv[]) { flags.parseFlags(argc, argv); @@ -37,7 +33,6 @@ int mainConvertFluxToVcd(int argc, const char* argv[]) const auto& location = *(locations.begin()); std::cerr << "Reading source flux...\n"; - setHardwareFluxSourceDensity(highDensityFlag); std::shared_ptr fluxsource = FluxSource::create(spec); const auto& fluxmap = fluxsource->readFlux(location.track, location.side); From 7c4f8e14437be3a04b3f8e12d02524d5047d2796 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 7 May 2021 20:40:22 +0200 Subject: [PATCH 4/5] Added documentation on 40-track disks and drives. --- doc/disk-brother.md | 4 +++ doc/using.md | 67 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/doc/disk-brother.md b/doc/disk-brother.md index a5ccf42f..17e59881 100644 --- a/doc/disk-brother.md +++ b/doc/disk-brother.md @@ -46,6 +46,10 @@ You should end up with a `brother.img` which is 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: ``` diff --git a/doc/using.md b/doc/using.md index 895c82c1..720824a0 100644 --- a/doc/using.md +++ b/doc/using.md @@ -49,6 +49,34 @@ 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 + +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_. + +_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 @@ -78,11 +106,11 @@ fluxengine read ibm -s fakedisk.flux:t=0-79:s=0 `some/files/:t=0-10`. There must be a files for a single disk only in the directory. -Source and destination specifiers work entirely in *physical units*. -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. +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. If you _don't_ specify a modifier, you'll get the default, which should be sensible for the command you're using. @@ -104,7 +132,7 @@ exact format varies according to the extension: geometry will be autodetected if left unspecified. For input files you normally have to specify it. - If one image track does not map directly onto on physical track, you can + 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. @@ -157,7 +185,7 @@ 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 `--hd` flag. +density disk or not with the `-H` flag. **If you don't do this, your disks may not read correctly and will _certainly_ fail to write correctly.** @@ -169,6 +197,31 @@ 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 From 720fe9f95fc409c901cb4173b72015040033c900 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 7 May 2021 20:45:46 +0200 Subject: [PATCH 5/5] Make sure that places which use usbSeek() honour --40-track. --- lib/flaggroups/fluxsourcesink.cc | 2 +- src/fe-analysedriveresponse.cc | 13 +++++++++++-- src/fe-seek.cc | 11 ++++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/flaggroups/fluxsourcesink.cc b/lib/flaggroups/fluxsourcesink.cc index 832858a5..287cf4e0 100644 --- a/lib/flaggroups/fluxsourcesink.cc +++ b/lib/flaggroups/fluxsourcesink.cc @@ -5,7 +5,7 @@ FlagGroup fluxSourceSinkFlags; SettableFlag fluxSourceSinkFortyTrack( - { "--40-track" }, + { "--40-track", "-4" }, "indicates a 40 track drive"); SettableFlag fluxSourceSinkHighDensity( diff --git a/src/fe-analysedriveresponse.cc b/src/fe-analysedriveresponse.cc index aafd1c6c..19aaf634 100644 --- a/src/fe-analysedriveresponse.cc +++ b/src/fe-analysedriveresponse.cc @@ -7,11 +7,13 @@ #include "writer.h" #include "protocol.h" #include "fmt/format.h" +#include "flaggroups/fluxsourcesink.h" #include "dep/agg/include/agg2d.h" #include "dep/stb/stb_image_write.h" #include static FlagGroup flags = { + &fluxSourceSinkFlags, &usbFlags, }; @@ -186,8 +188,15 @@ int mainAnalyseDriveResponse(int argc, const char* argv[]) if (spec.locations.size() != 1) Error() << "the destination dataspec must contain exactly one track (two sides count as two tracks)"; - usbSetDrive(spec.drive, false, F_INDEX_REAL); - usbSeek(spec.locations[0].track); + usbSetDrive(spec.drive, fluxSourceSinkHighDensity, F_INDEX_REAL); + int track = spec.locations[0].track; + if (fluxSourceSinkFortyTrack) + { + if (track & 1) + Error() << "you can only seek to even tracks on a 40-track disk"; + track /= 2; + } + usbSeek(track); std::cout << "Measuring rotational speed...\n"; nanoseconds_t period = usbGetRotationalPeriod(0); diff --git a/src/fe-seek.cc b/src/fe-seek.cc index 0cb80eeb..d23559ec 100644 --- a/src/fe-seek.cc +++ b/src/fe-seek.cc @@ -1,9 +1,11 @@ #include "globals.h" #include "flags.h" #include "usb/usb.h" +#include "flaggroups/fluxsourcesink.h" #include "protocol.h" static FlagGroup flags = { + &fluxSourceSinkFlags, &usbFlags, }; @@ -22,6 +24,13 @@ int mainSeek(int argc, const char* argv[]) flags.parseFlags(argc, argv); usbSetDrive(drive, false, F_INDEX_REAL); - usbSeek(track); + if (fluxSourceSinkFortyTrack) + { + if (track & 1) + Error() << "you can only seek to even tracks on a 40-track drive"; + usbSeek(track / 2); + } + else + usbSeek(track); return 0; }