From f24e4029b4369f1378d75c55111c9503a0018ede Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 17 Aug 2025 00:38:25 +0200 Subject: [PATCH] Flux sources now add the locations of their data to _extraConfig --- which is now honoured. Fix a bunch of bugs in some of the flux sources and sinks. The converter now actually works, maybe. --- lib/config/drive.proto | 18 ++++----- lib/core/globals.h | 1 + lib/data/locations.cc | 20 +++++++++- lib/data/locations.h | 3 ++ lib/fluxsink/a2rfluxsink.cc | 16 ++++++-- lib/fluxsink/fl2fluxsink.cc | 3 ++ lib/fluxsink/fluxsink.h | 5 +++ lib/fluxsink/scpfluxsink.cc | 3 +- lib/fluxsource/a2rfluxsource.cc | 33 ++++++++++++---- lib/fluxsource/cwffluxsource.cc | 39 ++++++++++++------- lib/fluxsource/dmkfluxsource.cc | 15 +++++++ lib/fluxsource/erasefluxsource.cc | 6 ++- lib/fluxsource/fl2fluxsource.cc | 10 +++++ lib/fluxsource/fluxsource.cc | 4 +- lib/fluxsource/fluxsource.h | 20 ++++++---- lib/fluxsource/flxfluxsource.cc | 18 +++++++++ lib/fluxsource/kryofluxfluxsource.cc | 15 +++++++ lib/fluxsource/memoryfluxsource.cc | 11 +++++- lib/fluxsource/scpfluxsource.cc | 10 +++++ lib/fluxsource/testpatternfluxsource.cc | 1 + lib/imagewriter/ldbsimagewriter.cc | 12 +++--- src/fe-convert.cc | 52 ++++++++----------------- src/formats/40track_drive.textpb | 2 +- src/formats/apple2_drive.textpb | 3 +- src/gui/drivetypes/apple2.textpb | 3 +- 25 files changed, 225 insertions(+), 98 deletions(-) diff --git a/lib/config/drive.proto b/lib/config/drive.proto index aef3033f..e9ab5a62 100644 --- a/lib/config/drive.proto +++ b/lib/config/drive.proto @@ -3,7 +3,7 @@ syntax = "proto2"; import "lib/config/common.proto"; import "lib/external/fl2.proto"; -// Next: 15 +// Next: 14 message DriveProto { optional int32 drive = 1 @@ -22,20 +22,18 @@ message DriveProto optional double revolutions = 7 [ default = 1.2, (help) = "number of revolutions to read" ]; - optional int32 tracks = 8 - [ default = 81, (help) = "Number of tracks supported by drive" ]; - optional int32 heads = 9 - [ default = 2, (help) = "Number of heads supported by drive" ]; - optional int32 head_bias = 10 [ + optional string tracks = 8 + [ default = "c0-80h0-1", (help) = "Tracks supported by drive" ]; + optional int32 head_bias = 9 [ default = 0, (help) = "Bias to apply to the head position (in tracks)" ]; - optional int32 group_offset = 11 [ + optional int32 group_offset = 10 [ default = 0, (help) = "When writing groups, erase all tracks except this one in each group" ]; - optional DriveType drive_type = 12 [ default = DRIVETYPE_UNKNOWN, (help) = "Type of drive" ]; - optional double rotational_period_ms = 13 + optional DriveType drive_type = 11 [ default = DRIVETYPE_UNKNOWN, (help) = "Type of drive" ]; + optional double rotational_period_ms = 12 [ default = 0, (help) = "Rotational period of the drive in milliseconds (0 to autodetect)"]; enum ErrorBehaviour { @@ -44,7 +42,7 @@ message DriveProto RECALIBRATE = 2; } - optional ErrorBehaviour error_behaviour = 14 + optional ErrorBehaviour error_behaviour = 13 [ default = JIGGLE, (help) = "what to do when an error occurs during reads" ]; } diff --git a/lib/core/globals.h b/lib/core/globals.h index 4ca57eb2..5a9c7dce 100644 --- a/lib/core/globals.h +++ b/lib/core/globals.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "fmt/format.h" #if defined(_WIN32) || defined(__WIN32__) diff --git a/lib/data/locations.cc b/lib/data/locations.cc index c05e625e..6360bbd8 100644 --- a/lib/data/locations.cc +++ b/lib/data/locations.cc @@ -9,6 +9,7 @@ #include #include #include "fmt/ranges.h" +#include namespace { @@ -142,5 +143,20 @@ std::vector parseCylinderHeadsString(const std::string& s) error(fmt::format("track descriptor parse error: {}", fmt::join(result.errors(), "; "))); } - return result.value(); -} \ No newline at end of file + + std::vector results = result.value(); + std::sort(results.begin(), results.end()); + return results; +} + +std::string convertCylinderHeadsToString(const std::vector& chs) +{ + return fmt::format("{}", + fmt::join(chs | std::views::transform( + [](const auto& ch) + { + return fmt::format( + "c{}h{}", ch.cylinder, ch.head); + }), + " ")); +} diff --git a/lib/data/locations.h b/lib/data/locations.h index 3bd4f8ee..8610472c 100644 --- a/lib/data/locations.h +++ b/lib/data/locations.h @@ -3,8 +3,11 @@ struct CylinderHead { bool operator==(const CylinderHead&) const = default; + std::strong_ordering operator<=>(const CylinderHead&) const = default; unsigned cylinder, head; }; extern std::vector parseCylinderHeadsString(const std::string& s); +extern std::string convertCylinderHeadsToString( + const std::vector& chs); diff --git a/lib/fluxsink/a2rfluxsink.cc b/lib/fluxsink/a2rfluxsink.cc index bd3a5e72..924def12 100644 --- a/lib/fluxsink/a2rfluxsink.cc +++ b/lib/fluxsink/a2rfluxsink.cc @@ -1,5 +1,6 @@ #include "lib/core/globals.h" #include "lib/config/flags.h" +#include "lib/config/config.h" #include "lib/data/fluxmap.h" #include "lib/core/bytes.h" #include "protocol.h" @@ -31,8 +32,6 @@ namespace _bytes{}, _writer{_bytes.writer()} { - log("A2R: collecting data"); - time_t now{std::time(nullptr)}; auto t = gmtime(&now); _metadata["image_date"] = fmt::format("{:%FT%TZ}", *t); @@ -88,7 +87,12 @@ namespace auto version_str_padded = fmt::format("{: <32}", "FluxEngine"); assert(version_str_padded.size() == 32); writer.append(version_str_padded); - writer.write_8(A2R_DISK_35); + + writer.write_8( + (globalConfig()->drive().drive_type() == DRIVETYPE_APPLE2) + ? A2R_DISK_525 + : A2R_DISK_35); + writer.write_8(1); // write protected writer.write_8(1); // synchronized writeChunkAndData(A2R_CHUNK_INFO, info); @@ -203,7 +207,11 @@ namespace uint32_t chunk_size = 10 + trackBytes.size(); - _strmWriter.write_8((cylinder << 1) | head); + if (globalConfig()->drive().drive_type() == DRIVETYPE_APPLE2) + _strmWriter.write_8(cylinder); + else + _strmWriter.write_8((cylinder << 1) | head); + _strmWriter.write_8(A2R_TIMING); _strmWriter.write_le32(trackBytes.size()); _strmWriter.write_le32(ticks_to_a2r(loopPoint)); diff --git a/lib/fluxsink/fl2fluxsink.cc b/lib/fluxsink/fl2fluxsink.cc index 43da9a9c..c8ffdf3a 100644 --- a/lib/fluxsink/fl2fluxsink.cc +++ b/lib/fluxsink/fl2fluxsink.cc @@ -10,6 +10,7 @@ #include "lib/config/proto.h" #include "lib/external/fl2.pb.h" #include "lib/external/fl2.h" +#include "lib/core/logger.h" #include #include #include @@ -34,6 +35,8 @@ public: ~Fl2FluxSink() { + log("FL2: writing {}", _filename); + FluxFileProto proto; for (const auto& e : _data) { diff --git a/lib/fluxsink/fluxsink.h b/lib/fluxsink/fluxsink.h index ab12d9dd..d835c538 100644 --- a/lib/fluxsink/fluxsink.h +++ b/lib/fluxsink/fluxsink.h @@ -2,6 +2,7 @@ #define FLUXSINK_H #include "lib/config/flags.h" +#include "lib/data/locations.h" #include class Fluxmap; @@ -42,6 +43,10 @@ public: /* Writes a fluxmap to a track and side. */ virtual void writeFlux(int track, int side, const Fluxmap& fluxmap) = 0; + void writeFlux(const CylinderHead& location, const Fluxmap& fluxmap) + { + writeFlux(location.cylinder, location.head, fluxmap); + } /* Returns whether this is writing to real hardware or not. */ diff --git a/lib/fluxsink/scpfluxsink.cc b/lib/fluxsink/scpfluxsink.cc index 610b9cb4..56b9af8d 100644 --- a/lib/fluxsink/scpfluxsink.cc +++ b/lib/fluxsink/scpfluxsink.cc @@ -173,8 +173,7 @@ public: _fileheader.revolutions = revolution; write_le32( _fileheader.track[strack], trackdataWriter.pos + sizeof(ScpHeader)); - trackdataWriter += - Bytes((uint8_t*)&trackHeader, sizeof(trackHeader)); + trackdataWriter += Bytes((uint8_t*)&trackHeader, sizeof(trackHeader)); trackdataWriter += fluxdata; } diff --git a/lib/fluxsource/a2rfluxsource.cc b/lib/fluxsource/a2rfluxsource.cc index 9e8bf8b0..74463f0c 100644 --- a/lib/fluxsource/a2rfluxsource.cc +++ b/lib/fluxsource/a2rfluxsource.cc @@ -1,9 +1,13 @@ #include "lib/core/globals.h" #include "lib/data/fluxmap.h" +#include "lib/data/layout.h" #include "lib/fluxsource/fluxsource.pb.h" #include "lib/fluxsource/fluxsource.h" #include "lib/config/proto.h" +#include "lib/data/locations.h" +#include "lib/core/logger.h" #include +#include struct A2Rv2Flux { @@ -78,8 +82,6 @@ public: if (disktype == 1) { /* 5.25" with quarter stepping. */ - _extraConfig.mutable_drive()->set_tracks(160); - _extraConfig.mutable_drive()->set_heads(1); _extraConfig.mutable_drive()->set_drive_type( DRIVETYPE_APPLE2); } @@ -94,12 +96,12 @@ public: ByteReader bsr(stream); for (;;) { - int location = bsr.read_8(); + unsigned location = bsr.read_8(); if (location == 0xff) break; - auto key = (disktype == 1) ? std::make_pair(location, 0) - : std::make_pair(location >> 1, - location & 1); + auto key = (disktype == 1) + ? CylinderHead{location, 0} + : CylinderHead{location >> 1, location & 1}; bsr.skip(1); uint32_t len = bsr.read_le32(); @@ -115,6 +117,20 @@ public: it->second->flux.push_back(bsr.read(len)); } + auto keys = std::views::keys(_v2data); + std::vector chs{keys.begin(), keys.end()}; + auto [minCylinder, maxCylinder, minHead, maxHead] = + Layout::getBounds(chs); + log("A2R: reading A2R {} file with {} cylinders and {} head{}", + (disktype == 1) ? "Apple II" + : (disktype == 2) ? "normal" + : "unknown", + maxCylinder - minCylinder + 1, + maxHead - minHead + 1, + (maxHead == minHead) ? "" : "s"); + + _extraConfig.mutable_drive()->set_tracks( + convertCylinderHeadsToString(chs)); break; } @@ -130,7 +146,8 @@ public: { case 2: { - auto i = _v2data.find(std::make_pair(track, head)); + auto i = + _v2data.find(CylinderHead{(unsigned)track, (unsigned)head}); if (i != _v2data.end()) return std::make_unique( *i->second); @@ -170,7 +187,7 @@ private: Bytes _data; std::ifstream _if; int _version; - std::map, std::unique_ptr> _v2data; + std::map> _v2data; }; std::unique_ptr FluxSource::createA2rFluxSource( diff --git a/lib/fluxsource/cwffluxsource.cc b/lib/fluxsource/cwffluxsource.cc index b23f9678..83696631 100644 --- a/lib/fluxsource/cwffluxsource.cc +++ b/lib/fluxsource/cwffluxsource.cc @@ -1,10 +1,12 @@ #include "lib/core/globals.h" #include "lib/data/fluxmap.h" +#include "lib/data/locations.h" #include "lib/fluxsource/fluxsource.pb.h" #include "lib/fluxsource/fluxsource.h" #include "lib/external/catweasel.h" #include "lib/config/proto.h" #include +#include struct CwfHeader { @@ -14,8 +16,8 @@ struct CwfHeader uint8_t version; // version of this file uint8_t clock_rate; // clock rate used: 0, 1, 2 (2 = 28MHz) uint8_t drive_type; // type of drive - uint8_t tracks; // number of tracks - uint8_t sides; // number of sides + uint8_t cylinders; // number of cylinders + uint8_t heads; // number of heads uint8_t index_mark; // nonzero if index marks are included uint8_t step; // track stepping interval uint8_t filler[15]; // reserved for expansion @@ -24,8 +26,8 @@ struct CwfHeader struct CwfTrack { - uint8_t track; // sequential - uint8_t side; + uint8_t cylinder; // sequential + uint8_t head; uint8_t unused[2]; uint8_t length[4]; // little-endian }; @@ -60,16 +62,16 @@ public: error("unsupported clock rate"); } - std::cout << fmt::format("CWF {}x{} = {} tracks, {} sides\n", - _header.tracks, - _header.step, - _header.tracks * _header.step, - _header.sides); + std::cout << fmt::format("CWF {}x{} = {} cylinders, {} heads\n", + _header.cylinders, + _header.heads, + _header.cylinders * _header.step, + _header.heads); std::cout << fmt::format( "CWF sample clock rate: {} MHz\n", 1e3 / _clockPeriod); - int tracks = _header.tracks * _header.sides; - for (int i = 0; i < tracks; i++) + int cylinders = _header.cylinders * _header.heads; + for (int i = 0; i < cylinders; i++) { CwfTrack trackHeader; _if.read((char*)&trackHeader, sizeof(trackHeader)); @@ -78,19 +80,26 @@ public: uint32_t length = Bytes(trackHeader.length, 4).reader().read_le32() - sizeof(CwfTrack); - unsigned track_number = trackHeader.track * _header.step; + unsigned track_number = trackHeader.cylinder * _header.step; off_t pos = _if.tellg(); - _trackOffsets[std::make_pair(track_number, trackHeader.side)] = + _trackOffsets[CylinderHead{track_number, trackHeader.head}] = std::make_pair(pos, length); _if.seekg(pos + length); } + + std::vector chs; + for (auto& [key, value] : _trackOffsets) + chs.push_back(key); + _extraConfig.mutable_drive()->set_tracks( + convertCylinderHeadsToString(chs)); } public: std::unique_ptr readSingleFlux(int track, int side) override { - const auto& p = _trackOffsets.find(std::make_pair(track, side)); + const auto& p = + _trackOffsets.find(CylinderHead{(unsigned)track, (unsigned)side}); if (p == _trackOffsets.end()) return std::make_unique(); @@ -117,7 +126,7 @@ private: std::ifstream _if; CwfHeader _header; nanoseconds_t _clockPeriod; - std::map, std::pair> _trackOffsets; + std::map> _trackOffsets; }; std::unique_ptr FluxSource::createCwfFluxSource( diff --git a/lib/fluxsource/dmkfluxsource.cc b/lib/fluxsource/dmkfluxsource.cc index 22b16216..4ccf577e 100644 --- a/lib/fluxsource/dmkfluxsource.cc +++ b/lib/fluxsource/dmkfluxsource.cc @@ -1,5 +1,6 @@ #include "lib/core/globals.h" #include "lib/data/fluxmap.h" +#include "lib/data/locations.h" #include "lib/fluxsource/fluxsource.pb.h" #include "lib/fluxsource/fluxsource.h" #include "lib/external/catweasel.h" @@ -56,6 +57,20 @@ class DmkFluxSource : public FluxSource public: DmkFluxSource(const DmkFluxSourceProto& config): _path(config.directory()) { + std::vector chs; + for (const auto& di : std::filesystem::directory_iterator(_path)) + { + static const std::regex FILENAME_REGEX( + "C_S([0-9]+)T([0-9]+)\\.[0-9]+"); + + std::string filename = di.path().filename(); + std::smatch dmatch; + if (std::regex_match(filename, dmatch, FILENAME_REGEX)) + chs.push_back(CylinderHead{(unsigned)std::stoi(dmatch[2]), + (unsigned)std::stoi(dmatch[1])}); + } + _extraConfig.mutable_drive()->set_tracks( + convertCylinderHeadsToString(chs)); } public: diff --git a/lib/fluxsource/erasefluxsource.cc b/lib/fluxsource/erasefluxsource.cc index 2fcc8515..3146758a 100644 --- a/lib/fluxsource/erasefluxsource.cc +++ b/lib/fluxsource/erasefluxsource.cc @@ -6,7 +6,11 @@ class EraseFluxSource : public TrivialFluxSource { public: - EraseFluxSource(const EraseFluxSourceProto& config) {} + EraseFluxSource(const EraseFluxSourceProto& config) + { + _extraConfig.mutable_drive()->set_tracks("c0-255h0-1"); + } + ~EraseFluxSource() {} public: diff --git a/lib/fluxsource/fl2fluxsource.cc b/lib/fluxsource/fl2fluxsource.cc index 1fb8227e..5f2c37d1 100644 --- a/lib/fluxsource/fl2fluxsource.cc +++ b/lib/fluxsource/fl2fluxsource.cc @@ -1,11 +1,13 @@ #include "lib/core/globals.h" #include "lib/data/fluxmap.h" +#include "lib/data/locations.h" #include "lib/fluxsource/fluxsource.pb.h" #include "lib/external/fl2.pb.h" #include "lib/fluxsource/fluxsource.h" #include "lib/config/proto.h" #include "lib/external/fl2.h" #include "lib/data/fluxmap.h" +#include "lib/core/logger.h" #include class Fl2FluxSourceIterator : public FluxSourceIterator @@ -35,12 +37,20 @@ class Fl2FluxSource : public FluxSource public: Fl2FluxSource(const Fl2FluxSourceProto& config): _config(config) { + log("FL2: reading {}", _config.filename()); _proto = loadFl2File(_config.filename()); _extraConfig.mutable_drive()->set_rotational_period_ms( _proto.rotational_period_ms()); if (_proto.has_drive_type()) _extraConfig.mutable_drive()->set_drive_type(_proto.drive_type()); + + std::vector chs; + for (const auto& trackFlux : _proto.track()) + chs.push_back(CylinderHead{ + (unsigned)trackFlux.track(), (unsigned)trackFlux.head()}); + _extraConfig.mutable_drive()->set_tracks( + convertCylinderHeadsToString(chs)); } public: diff --git a/lib/fluxsource/fluxsource.cc b/lib/fluxsource/fluxsource.cc index 67a253c4..d1e46733 100644 --- a/lib/fluxsource/fluxsource.cc +++ b/lib/fluxsource/fluxsource.cc @@ -11,7 +11,9 @@ std::unique_ptr FluxSource::create(Config& config) { if (!config.hasFluxSource()) error("no flux source configured"); - return create(config->flux_source()); + auto fluxSource = create(config->flux_source()); + globalConfig().base()->MergeFrom(fluxSource->getExtraConfig()); + return fluxSource; } std::unique_ptr FluxSource::create(const FluxSourceProto& config) diff --git a/lib/fluxsource/fluxsource.h b/lib/fluxsource/fluxsource.h index 20f8515f..12e1f1cd 100644 --- a/lib/fluxsource/fluxsource.h +++ b/lib/fluxsource/fluxsource.h @@ -2,6 +2,7 @@ #define FLUXSOURCE_H #include "lib/config/flags.h" +#include "lib/data/locations.h" #include "lib/config/config.pb.h" class A2rFluxSourceProto; @@ -71,19 +72,23 @@ public: return _extraConfig; } - /* Read flux from a given track and side. */ + /* Read flux from a given cylinder and head. */ virtual std::unique_ptr readFlux( - int track, int side) = 0; + int cylinder, int head) = 0; + std::unique_ptr readFlux(const CylinderHead& location) + { + return readFlux(location.cylinder, location.head); + } - /* Recalibrates; seeks to track 0 and ensures the head is in the right + /* Recalibrates; seeks to cylinder 0 and ensures the head is in the right * place. */ virtual void recalibrate() {} - /* Seeks to a given track (without recalibrating). */ + /* Seeks to a given cylinder (without recalibrating). */ - virtual void seek(int track) {} + virtual void seek(int cylinder) {} /* Is this real hardware? If so, then flux can be read indefinitely (among * other things). */ @@ -113,9 +118,10 @@ class EmptyFluxSourceIterator : public FluxSourceIterator class TrivialFluxSource : public FluxSource { public: - std::unique_ptr readFlux(int track, int side) override; + std::unique_ptr readFlux( + int cylinder, int head) override; virtual std::unique_ptr readSingleFlux( - int track, int side) = 0; + int cylinder, int head) = 0; }; #endif diff --git a/lib/fluxsource/flxfluxsource.cc b/lib/fluxsource/flxfluxsource.cc index 1d37fc48..04bb0008 100644 --- a/lib/fluxsource/flxfluxsource.cc +++ b/lib/fluxsource/flxfluxsource.cc @@ -1,14 +1,31 @@ #include "lib/core/globals.h" #include "lib/data/fluxmap.h" +#include "lib/data/locations.h" #include "lib/fluxsource/fluxsource.pb.h" #include "lib/fluxsource/fluxsource.h" #include "lib/external/flx.h" +#include "lib/core/logger.h" +#include class FlxFluxSource : public TrivialFluxSource { public: FlxFluxSource(const FlxFluxSourceProto& config): _path(config.directory()) { + std::vector chs; + for (const auto& di : std::filesystem::directory_iterator(_path)) + { + static const std::regex FILENAME_REGEX( + "@TR([0-9]+)S([0-9]+)@\\.FLX"); + + std::string filename = di.path().filename(); + std::smatch dmatch; + if (std::regex_match(filename, dmatch, FILENAME_REGEX)) + chs.push_back(CylinderHead{(unsigned)std::stoi(dmatch[1]), + (unsigned)std::stoi(dmatch[2]) - 1}); + } + _extraConfig.mutable_drive()->set_tracks( + convertCylinderHeadsToString(chs)); } public: @@ -16,6 +33,7 @@ public: { std::string path = fmt::format("{}/@TR{:02}S{}@.FLX", _path, track, side + 1); + log("FLX: reading {}", path); return readFlxBytes(Bytes::readFromFile(path)); } diff --git a/lib/fluxsource/kryofluxfluxsource.cc b/lib/fluxsource/kryofluxfluxsource.cc index e48e2c45..15a241a8 100644 --- a/lib/fluxsource/kryofluxfluxsource.cc +++ b/lib/fluxsource/kryofluxfluxsource.cc @@ -1,8 +1,10 @@ #include "lib/core/globals.h" #include "lib/data/fluxmap.h" +#include "lib/data/locations.h" #include "lib/external/kryoflux.h" #include "lib/fluxsource/fluxsource.pb.h" #include "lib/fluxsource/fluxsource.h" +#include class KryofluxFluxSource : public TrivialFluxSource { @@ -10,6 +12,19 @@ public: KryofluxFluxSource(const KryofluxFluxSourceProto& config): _path(config.directory()) { + std::vector chs; + for (const auto& di : std::filesystem::directory_iterator(_path)) + { + static const std::regex FILENAME_REGEX("([0-9]+)\\.([0-9]+)\\.raw"); + + std::string filename = di.path().filename(); + std::smatch dmatch; + if (std::regex_match(filename, dmatch, FILENAME_REGEX)) + chs.push_back(CylinderHead{(unsigned)std::stoi(dmatch[1]), + (unsigned)std::stoi(dmatch[2])}); + } + _extraConfig.mutable_drive()->set_tracks( + convertCylinderHeadsToString(chs)); } public: diff --git a/lib/fluxsource/memoryfluxsource.cc b/lib/fluxsource/memoryfluxsource.cc index 58aac684..87051842 100644 --- a/lib/fluxsource/memoryfluxsource.cc +++ b/lib/fluxsource/memoryfluxsource.cc @@ -31,7 +31,16 @@ private: class MemoryFluxSource : public FluxSource { public: - MemoryFluxSource(const DiskFlux& flux): _flux(flux) {} + MemoryFluxSource(const DiskFlux& flux): _flux(flux) + { + std::vector chs; + for (const auto& trackFlux : flux.tracks) + chs.push_back( + CylinderHead{(unsigned)trackFlux->trackInfo->physicalTrack, + (unsigned)trackFlux->trackInfo->logicalTrack}); + _extraConfig.mutable_drive()->set_tracks( + convertCylinderHeadsToString(chs)); + } public: std::unique_ptr readFlux( diff --git a/lib/fluxsource/scpfluxsource.cc b/lib/fluxsource/scpfluxsource.cc index 43f47c77..61c42fba 100644 --- a/lib/fluxsource/scpfluxsource.cc +++ b/lib/fluxsource/scpfluxsource.cc @@ -1,5 +1,6 @@ #include "lib/core/globals.h" #include "lib/data/fluxmap.h" +#include "lib/data/locations.h" #include "lib/external/kryoflux.h" #include "lib/fluxsource/fluxsource.pb.h" #include "lib/core/utils.h" @@ -53,6 +54,15 @@ public: if ((_header.cell_width != 0) && (_header.cell_width != 16)) error("currently only 16-bit cells in SCP files are supported"); + std::vector chs; + for (unsigned cylinder = trackno(_header.start_track); + cylinder <= trackno(_header.end_track); + cylinder++) + for (unsigned head = startSide; head <= endSide; head++) + chs.push_back(CylinderHead{cylinder, head}); + _extraConfig.mutable_drive()->set_tracks( + convertCylinderHeadsToString(chs)); + log("SCP tracks {}-{}, heads {}-{}", trackno(_header.start_track), trackno(_header.end_track), diff --git a/lib/fluxsource/testpatternfluxsource.cc b/lib/fluxsource/testpatternfluxsource.cc index 7b16376a..8e332153 100644 --- a/lib/fluxsource/testpatternfluxsource.cc +++ b/lib/fluxsource/testpatternfluxsource.cc @@ -9,6 +9,7 @@ public: TestPatternFluxSource(const TestPatternFluxSourceProto& config): _config(config) { + _extraConfig.mutable_drive()->set_tracks("c0-255h0-1"); } ~TestPatternFluxSource() {} diff --git a/lib/imagewriter/ldbsimagewriter.cc b/lib/imagewriter/ldbsimagewriter.cc index d971200c..f1a4c778 100644 --- a/lib/imagewriter/ldbsimagewriter.cc +++ b/lib/imagewriter/ldbsimagewriter.cc @@ -76,10 +76,9 @@ public: trackHeaderWriter.write_le16(actualSectors); trackHeaderWriter.write_8(dataRate); trackHeaderWriter.write_8(recordingMode); - trackHeaderWriter.write_8(0); /* format gap length */ - trackHeaderWriter.write_8(0); /* filler byte */ - trackHeaderWriter.write_le16( - 0); /* approximate track length */ + trackHeaderWriter.write_8(0); /* format gap length */ + trackHeaderWriter.write_8(0); /* filler byte */ + trackHeaderWriter.write_le16(0); /* approximate track length */ for (int sectorId = 0; sectorId < geometry.numSectors; sectorId++) @@ -100,7 +99,7 @@ public: trackHeaderWriter.write_8( (sector->status == Sector::OK) ? 0x00 - : 0x20); /* 8272 status 1 */ + : 0x20); /* 8272 status 1 */ trackHeaderWriter.write_8(0); /* 8272 status 2 */ trackHeaderWriter.write_8(1); /* number of copies */ trackHeaderWriter.write_8(0); /* filler byte */ @@ -114,8 +113,7 @@ public: uint32_t trackLabel = (('T') << 24) | ((track & 0xff) << 16) | ((track >> 8) << 8) | side; - uint32_t trackHeaderAddress = - ldbs.put(trackHeader, trackLabel); + uint32_t trackHeaderAddress = ldbs.put(trackHeader, trackLabel); trackDirectoryWriter.write_be32(trackLabel); trackDirectoryWriter.write_le32(trackHeaderAddress); trackDirectorySize++; diff --git a/src/fe-convert.cc b/src/fe-convert.cc index 7f7761a9..37ed91c4 100644 --- a/src/fe-convert.cc +++ b/src/fe-convert.cc @@ -28,44 +28,26 @@ int mainConvert(int argc, const char* argv[]) globalConfig().setFluxSink(filenames[1]); auto fluxSource = FluxSource::create(globalConfig()); + auto locations = globalConfig()->drive().tracks(); + globalConfig().overrides()->set_tracks(locations); -#if 0 - std::vector> locations; - std::map, - std::vector>> - data; - for (int track = 0; track < 255; track++) - for (int side = 0; side < 2; side++) - { - auto ti = std::make_shared(); - ti->physicalTrack = track; - ti->physicalSide = side; - - auto fsi = fluxSource->readFlux(track, side); - std::vector> fluxes; - - while (fsi->hasNext()) - fluxes.push_back(fsi->next()); - - if (!fluxes.empty()) - { - data[ti] = fluxes; - locations.push_back(ti); - } - } - - auto [minTrack, maxTrack, minSide, maxSide] = Layout::getBounds(locations); - log("CONVERT: seen tracks {}..{}, sides {}..{}", - minTrack, - maxTrack, - minSide, - maxSide); - - globalConfig().set("tracks", fmt::format("{}-{}", minTrack, maxTrack)); - globalConfig().set("heads", fmt::format("{}-{}", minSide, maxSide)); + auto physicalLocations = Layout::computePhysicalLocations(); + auto [minCylinder, maxCylinder, minHead, maxHead] = + Layout::getBounds(physicalLocations); + log("CONVERT: seen cylinders {}..{}, heads {}..{}", + minCylinder, + maxCylinder, + minHead, + maxHead); auto fluxSink = FluxSink::create(globalConfig()); -#endif + + for (const auto& physicalLocation : physicalLocations) + { + auto fi = fluxSource->readFlux(physicalLocation); + while (fi->hasNext()) + fluxSink->writeFlux(physicalLocation, *fi->next()); + } return 0; } diff --git a/src/formats/40track_drive.textpb b/src/formats/40track_drive.textpb index 736b709d..39b16f95 100644 --- a/src/formats/40track_drive.textpb +++ b/src/formats/40track_drive.textpb @@ -15,7 +15,7 @@ fluxengine read ibm --180 40track_drive >>> drive { - tracks: 40 + tracks: "c0-40h0-1" drive_type: DRIVETYPE_40TRACK } diff --git a/src/formats/apple2_drive.textpb b/src/formats/apple2_drive.textpb index 0527daf4..64532bcc 100644 --- a/src/formats/apple2_drive.textpb +++ b/src/formats/apple2_drive.textpb @@ -22,8 +22,7 @@ usb { } drive { - tracks: 160 - heads: 1 + tracks: "c0-159h0" drive_type: DRIVETYPE_APPLE2 } diff --git a/src/gui/drivetypes/apple2.textpb b/src/gui/drivetypes/apple2.textpb index e8d933ce..95378945 100644 --- a/src/gui/drivetypes/apple2.textpb +++ b/src/gui/drivetypes/apple2.textpb @@ -7,8 +7,7 @@ usb { } drive { - tracks: 160 - heads: 1 + tracks: "c0-159h0" drive_type: DRIVETYPE_APPLE2 }