From bf8f6ae68739e9441a5f8402074252905bc9ea56 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 21 Apr 2021 00:41:36 +0200 Subject: [PATCH] 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); } }