diff --git a/arch/ibm/encoder.cc b/arch/ibm/encoder.cc index 73eb4897..b53c6f9e 100644 --- a/arch/ibm/encoder.cc +++ b/arch/ibm/encoder.cc @@ -315,3 +315,33 @@ std::unique_ptr createIbmEncoder(const EncoderProto& config) { return std::unique_ptr(new IbmEncoder(config)); } + +std::unique_ptr createIbmEncoderFromImage(EncoderProto& config, const Image& image) +{ + IbmEncoderProto* ibm; + Geometry geometry; + ibm = config.mutable_ibm(); + geometry = image.getGeometry(); + std::map>> tracks_heads; + for (const auto& sector : image) { + tracks_heads[sector->logicalTrack][sector->logicalSide].push_back(sector.get()); + } + for (const auto& track: tracks_heads) { + for (const auto& head : track.second) { + auto trackdata = ibm->mutable_trackdata()->Add(); + for (const auto& sector : head.second) { + trackdata->mutable_sectors()->mutable_sector()->Add(sector->logicalSector); + trackdata->set_sector_size(sector->data.size()); + // note: this currently only uses the last sector's parameters + trackdata->set_target_clock_period_us(sector->clock / 1000.0 * 2.0); + } + trackdata->set_track(track.first); + trackdata->set_head(head.first); + trackdata->set_gap0(0x1b); + trackdata->set_gap2(0x09); + trackdata->set_gap3(0x1b); + trackdata->set_target_rotational_period_ms(167); + } + } + return createIbmEncoder(config); +} diff --git a/arch/ibm/ibm.h b/arch/ibm/ibm.h index fe804354..7d0caf54 100644 --- a/arch/ibm/ibm.h +++ b/arch/ibm/ibm.h @@ -33,5 +33,6 @@ class EncoderProto; extern std::unique_ptr createIbmDecoder(const DecoderProto& config); extern std::unique_ptr createIbmEncoder(const EncoderProto& config); +extern std::unique_ptr createIbmEncoderFromImage(EncoderProto& config, const Image& image); #endif diff --git a/lib/config.proto b/lib/config.proto index 29309f34..39fd968a 100644 --- a/lib/config.proto +++ b/lib/config.proto @@ -11,7 +11,7 @@ import "lib/drive.proto"; import "lib/mapper.proto"; import "lib/common.proto"; -// NEXT_TAG: 17 +// NEXT_TAG: 19 message ConfigProto { optional string comment = 8; optional bool is_extension = 13; @@ -21,9 +21,11 @@ message ConfigProto { optional FluxSourceProto flux_source = 10; optional FluxSinkProto flux_sink = 11; + optional FluxSinkProto solved_flux = 17; optional DriveProto drive = 15; optional EncoderProto encoder = 3; + optional EncoderProto solved_encoder = 18; optional DecoderProto decoder = 4; optional UsbProto usb = 5; diff --git a/lib/encoders/encoders.cc b/lib/encoders/encoders.cc index 30faf3b7..e00bb25c 100644 --- a/lib/encoders/encoders.cc +++ b/lib/encoders/encoders.cc @@ -13,6 +13,8 @@ #include "arch/tids990/tids990.h" #include "arch/victor9k/victor9k.h" #include "lib/encoders/encoders.pb.h" +#include "lib/decoders/decoders.pb.h" +#include "lib/image.h" #include "protocol.h" std::unique_ptr AbstractEncoder::create( @@ -40,6 +42,22 @@ std::unique_ptr AbstractEncoder::create( return (encoder->second)(config); } +std::unique_ptr AbstractEncoder::createFromImage(EncoderProto& encoderConfig, + const DecoderProto& decoderConfig, const Image& image) +{ + static const std::map(EncoderProto&, const Image&)>> + encoders = { + {DecoderProto::kIbm, createIbmEncoderFromImage}, + }; + + auto encoder = encoders.find(decoderConfig.format_case()); + if (encoder == encoders.end()) + Error() << "solved fluxmaps not supported for this format"; + + return (encoder->second)(encoderConfig, image); +} + Fluxmap& Fluxmap::appendBits(const std::vector& bits, nanoseconds_t clock) { nanoseconds_t now = duration(); diff --git a/lib/encoders/encoders.h b/lib/encoders/encoders.h index c2859c34..e76fc8b9 100644 --- a/lib/encoders/encoders.h +++ b/lib/encoders/encoders.h @@ -2,6 +2,7 @@ #define ENCODERS_H class EncoderProto; +class DecoderProto; class Fluxmap; class Image; class Location; @@ -14,6 +15,8 @@ class AbstractEncoder virtual ~AbstractEncoder() {} static std::unique_ptr create(const EncoderProto& config); + static std::unique_ptr createFromImage(EncoderProto& encoderConfig, + const DecoderProto& decoderConfig, const Image& image); public: virtual std::vector> collectSectors( diff --git a/lib/readerwriter.cc b/lib/readerwriter.cc index c80539d9..3c9fbf63 100644 --- a/lib/readerwriter.cc +++ b/lib/readerwriter.cc @@ -470,7 +470,7 @@ std::shared_ptr readDiskCommand( } void readDiskCommand( - FluxSource& fluxsource, AbstractDecoder& decoder, ImageWriter& writer) + FluxSource& fluxsource, AbstractDecoder& decoder, ImageWriter& writer,FluxSink* solvedFlux) { auto diskflux = readDiskCommand(fluxsource, decoder); @@ -478,6 +478,11 @@ void readDiskCommand( if (config.decoder().has_write_csv_to()) writer.writeCsv(*diskflux->image, config.decoder().write_csv_to()); writer.writeImage(*diskflux->image); + if (config.has_solved_flux()) { + std::unique_ptr solvedEncoder = AbstractEncoder::createFromImage(*config.mutable_encoder(), + config.decoder(), *diskflux->image); + writeTracks(*solvedFlux, *solvedEncoder, *diskflux->image); + } } void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink) diff --git a/lib/readerwriter.h b/lib/readerwriter.h index 8bf1ace4..e9f3fe65 100644 --- a/lib/readerwriter.h +++ b/lib/readerwriter.h @@ -34,7 +34,7 @@ extern std::unique_ptr readAndDecodeTrack( FluxSource& source, AbstractDecoder& decoder, unsigned track, unsigned head); extern std::shared_ptr readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder); -extern void readDiskCommand(FluxSource& source, AbstractDecoder& decoder, ImageWriter& writer); +extern void readDiskCommand(FluxSource& source, AbstractDecoder& decoder, ImageWriter& writer, FluxSink* solvedFlux); extern void rawReadDiskCommand(FluxSource& source, FluxSink& sink); #endif diff --git a/src/fe-read.cc b/src/fe-read.cc index 0e3f0f61..59be9a1b 100644 --- a/src/fe-read.cc +++ b/src/fe-read.cc @@ -3,6 +3,7 @@ #include "readerwriter.h" #include "fluxmap.h" #include "decoders/decoders.h" +#include "encoders/encoders.h" #include "macintosh/macintosh.h" #include "sector.h" #include "proto.h" @@ -45,6 +46,15 @@ static StringFlag copyFluxTo( FluxSink::updateConfigForFilename(config.mutable_decoder()->mutable_copy_flux_to(), value); }); +static StringFlag solvedFlux( + { "-r", "--solved" }, + "after reading, write a reconstructed/solved fluxmap to this file", + "", + [](const auto& value) + { + FluxSink::updateConfigForFilename(config.mutable_solved_flux(), value); + }); + static StringFlag srcTracks( { "--cylinders", "-c" }, "tracks to read from", @@ -76,8 +86,12 @@ int mainRead(int argc, const char* argv[]) std::unique_ptr fluxSource(FluxSource::create(config.flux_source())); std::unique_ptr decoder(AbstractDecoder::create(config.decoder())); std::unique_ptr writer(ImageWriter::create(config.image_writer())); + std::unique_ptr solvedFlux; + std::unique_ptr solvedEncoder; + if (config.has_solved_flux()) { + solvedFlux = FluxSink::create(config.solved_flux()); } - readDiskCommand(*fluxSource, *decoder, *writer); + readDiskCommand(*fluxSource, *decoder, *writer, solvedFlux.get()); return 0; }