This commit is contained in:
David Given
2022-02-21 22:22:10 +01:00
13 changed files with 396 additions and 186 deletions

View File

@@ -57,10 +57,10 @@ std::unique_ptr<AbstractDecoder> AbstractDecoder::create(const DecoderProto& con
return (decoder->second)(config);
}
std::unique_ptr<TrackDataFlux> AbstractDecoder::decodeToSectors(
std::shared_ptr<TrackDataFlux> AbstractDecoder::decodeToSectors(
std::shared_ptr<const Fluxmap> fluxmap, unsigned physicalCylinder, unsigned physicalHead)
{
_trackdata = std::make_unique<TrackDataFlux>();
_trackdata = std::make_shared<TrackDataFlux>();
_trackdata->fluxmap = fluxmap;
_trackdata->physicalCylinder = physicalCylinder;
_trackdata->physicalHead = physicalHead;

View File

@@ -45,7 +45,7 @@ public:
};
public:
std::unique_ptr<TrackDataFlux> decodeToSectors(std::shared_ptr<const Fluxmap> fluxmap, unsigned cylinder, unsigned head);
std::shared_ptr<TrackDataFlux> decodeToSectors(std::shared_ptr<const Fluxmap> fluxmap, unsigned cylinder, unsigned head);
void pushRecord(const Fluxmap::Position& start, const Fluxmap::Position& end);
void resetFluxDecoder();
@@ -82,7 +82,7 @@ protected:
virtual void decodeDataRecord() {};
const DecoderProto& _config;
std::unique_ptr<TrackDataFlux> _trackdata;
std::shared_ptr<TrackDataFlux> _trackdata;
std::shared_ptr<Sector> _sector;
std::unique_ptr<FluxDecoder> _decoder;
std::vector<bool> _recordBits;

View File

@@ -25,13 +25,13 @@ struct TrackFlux
{
unsigned physicalCylinder;
unsigned physicalHead;
std::vector<std::unique_ptr<TrackDataFlux>> trackDatas;
std::vector<std::shared_ptr<TrackDataFlux>> trackDatas;
std::set<std::shared_ptr<Sector>> sectors;
};
struct DiskFlux
{
std::vector<std::unique_ptr<TrackFlux>> tracks;
std::vector<std::shared_ptr<TrackFlux>> tracks;
std::unique_ptr<Image> image;
};

View File

@@ -1,6 +1,7 @@
#include "globals.h"
#include "flags.h"
#include "fluxmap.h"
#include "logger.h"
#include "usb/usb.h"
#include "fluxsink/fluxsink.h"
#include "lib/fluxsink/fluxsink.pb.h"
@@ -14,22 +15,22 @@ public:
{
if (config.has_hard_sector_count())
{
int rotationalSpeedMs;
nanoseconds_t oneRevolution;
int retries = 5;
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
std::cout << "Measuring rotational speed... " << std::flush;
Logger() << BeginSpeedOperationLogMessage();
do {
nanoseconds_t oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
_hardSectorThreshold = oneRevolution * 3 / (4 * _config.hard_sector_count());
rotationalSpeedMs = oneRevolution / 1e6;
retries--;
} while ((rotationalSpeedMs == 0) && (retries > 0));
} while ((oneRevolution == 0) && (retries > 0));
if (rotationalSpeedMs == 0) {
if (oneRevolution == 0) {
Error() << "Failed\nIs a disk in the drive?";
}
std::cout << fmt::format("{}ms\n", rotationalSpeedMs);
Logger() << EndSpeedOperationLogMessage(oneRevolution);
}
else
_hardSectorThreshold = 0;

View File

@@ -1,6 +1,7 @@
#include "globals.h"
#include "flags.h"
#include "fluxmap.h"
#include "logger.h"
#include "usb/usb.h"
#include "fluxsource/fluxsource.h"
#include "lib/fluxsource/fluxsource.pb.h"
@@ -12,10 +13,9 @@ public:
HardwareFluxSource(const HardwareFluxSourceProto& config):
_config(config)
{
int rotationalSpeedMs;
int retries = 5;
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
std::cout << "Measuring rotational speed... " << std::flush;
Logger() << BeginSpeedOperationLogMessage();
do {
_oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
@@ -24,15 +24,14 @@ public:
else
_hardSectorThreshold = 0;
rotationalSpeedMs = _oneRevolution / 1e6;
retries--;
} while ((rotationalSpeedMs == 0) && (retries > 0));
} while ((_oneRevolution == 0) && (retries > 0));
if (rotationalSpeedMs == 0) {
if (_oneRevolution == 0) {
Error() << "Failed\nIs a disk in the drive?";
}
std::cout << fmt::format("{}ms\n", rotationalSpeedMs);
Logger() << EndSpeedOperationLogMessage(_oneRevolution);
}
~HardwareFluxSource()

View File

@@ -12,6 +12,7 @@
#include <set>
#include <cassert>
#include <climits>
#include <variant>
#if defined(_WIN32) || defined(__WIN32__)
#include <direct.h>

129
lib/logger.cc Normal file
View File

@@ -0,0 +1,129 @@
#include "globals.h"
#include "bytes.h"
#include "fluxmap.h"
#include "sector.h"
#include "flux.h"
#include "fmt/format.h"
#include "logger.h"
template <class... Ts>
struct overloaded : Ts...
{
using Ts::operator()...;
};
template <class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
static bool indented = false;
static void indent()
{
if (!indented)
std::cout << " ";
indented = false;
}
Logger& Logger::operator<<(std::shared_ptr<AnyLogMessage> message)
{
std::visit(
overloaded{
/* Fallback --- do nothing */
[](const auto& m)
{
},
/* Start measuring the rotational speed */
[](const BeginSpeedOperationLogMessage& m)
{
std::cout << "Measuring rotational speed... " << std::flush;
},
/* Finish measuring the rotational speed */
[](const EndSpeedOperationLogMessage& m)
{
std::cout << fmt::format("{:.1f}ms ({:.1f}rpm)\n",
m.rotationalPeriod / 1e6,
60e9 / m.rotationalPeriod);
},
/* Indicates that we're working on a given cylinder and head */
[](const DiskContextLogMessage& m)
{
std::cout << fmt::format("{:2}.{}: ", m.cylinder, m.head)
<< std::flush;
indented = true;
},
/* A single read has happened */
[](const SingleReadLogMessage& m)
{
const auto& trackdataflux = m.trackDataFlux;
indent();
std::cout << fmt::format("{} records, {} sectors",
trackdataflux->records.size(),
trackdataflux->sectors.size());
if (trackdataflux->sectors.size() > 0)
{
nanoseconds_t clock =
(*trackdataflux->sectors.begin())->clock;
std::cout << fmt::format("; {:.2f}us clock ({:.0f}kHz)",
clock / 1000.0,
1000000.0 / clock);
}
std::cout << '\n';
indent();
std::cout << "sectors:";
std::vector<std::shared_ptr<Sector>> sectors(m.sectors.begin(), m.sectors.end());
std::sort(sectors.begin(), sectors.end(),
[](const std::shared_ptr<Sector>& s1, const std::shared_ptr<Sector>&s2)
{
return s1->logicalSector < s2->logicalSector;
}
);
for (const auto& sector : sectors)
std::cout << fmt::format(" {}{}", sector->logicalSector, Sector::statusToChar(sector->status));
std::cout << '\n';
},
/* We've finished reading a track */
[](const TrackReadLogMessage& m)
{
int size = 0;
std::set<std::pair<int, int>> track_ids;
for (const auto& sector : m.track->sectors)
{
track_ids.insert(std::make_pair(sector->logicalTrack, sector->logicalSide));
size += sector->data.size();
}
if (!track_ids.empty())
{
std::vector<std::string> ids;
for (const auto& i : track_ids)
ids.push_back(fmt::format("{}.{}", i.first, i.second));
indent();
std::cout << fmt::format("logical track {}\n", fmt::join(ids, "; "));
}
indent();
std::cout << fmt::format("{} bytes decoded\n", size);
},
/* Generic text message */
[](const std::string& s)
{
indent();
std::cout << s << '\n';
},
},
*message);
return *this;
}

64
lib/logger.h Normal file
View File

@@ -0,0 +1,64 @@
#ifndef LOGGER_H
#define LOGGER_H
#include "fmt/format.h"
class TrackDataFlux;
class TrackFlux;
class Sector;
struct BeginSpeedOperationLogMessage {};
struct EndSpeedOperationLogMessage
{
nanoseconds_t rotationalPeriod;
};
struct DiskContextLogMessage
{
unsigned cylinder;
unsigned head;
};
struct SingleReadLogMessage
{
std::shared_ptr<TrackDataFlux> trackDataFlux;
std::set<std::shared_ptr<Sector>> sectors;
};
struct TrackReadLogMessage
{
std::shared_ptr<TrackFlux> track;
};
struct BeginReadOperationLogMessage { };
struct EndReadOperationLogMessage { };
struct BeginWriteOperationLogMessage { };
struct EndWriteOperationLogMessage { };
class TrackFlux;
typedef std::variant<std::string,
SingleReadLogMessage,
TrackReadLogMessage,
DiskContextLogMessage,
BeginSpeedOperationLogMessage,
EndSpeedOperationLogMessage,
BeginReadOperationLogMessage,
EndReadOperationLogMessage,
BeginWriteOperationLogMessage,
EndWriteOperationLogMessage>
AnyLogMessage;
class Logger
{
public:
Logger& operator<<(std::shared_ptr<AnyLogMessage> message);
template <class T>
Logger& operator<<(const T& message)
{
return *this << std::make_shared<AnyLogMessage>(message);
}
};
#endif

View File

@@ -12,6 +12,7 @@
#include "flux.h"
#include "image.h"
#include "imagewriter/imagewriter.h"
#include "logger.h"
#include "fmt/format.h"
#include "proto.h"
#include "lib/decoders/decoders.pb.h"
@@ -22,13 +23,12 @@ static std::unique_ptr<FluxSink> outputFluxSink;
static std::shared_ptr<Fluxmap> readFluxmap(FluxSource& fluxsource, unsigned cylinder, unsigned head)
{
std::cout << fmt::format("{0:>3}.{1}: ", cylinder, head) << std::flush;
Logger() << DiskContextLogMessage { cylinder, head }
<< BeginReadOperationLogMessage();
std::shared_ptr<Fluxmap> fluxmap = fluxsource.readFlux(cylinder, head);
fluxmap->rescale(1.0/config.flux_source().rescale());
std::cout << fmt::format(
"{0:.0} ms in {1} bytes\n",
fluxmap->duration()/1e6,
fluxmap->bytes());
Logger() << EndReadOperationLogMessage()
<< fmt::format("{0:.0} ms in {1} bytes", fluxmap->duration()/1e6, fluxmap->bytes());
return fluxmap;
}
@@ -50,8 +50,7 @@ static std::set<std::shared_ptr<Sector>> collect_sectors(std::set<std::shared_pt
{
if (replacement->data != replacing->data)
{
std::cout << fmt::format(
"\n multiple conflicting copies of sector {} seen; ",
Logger() << fmt::format("multiple conflicting copies of sector {} seen",
std::get<2>(sectorid));
replacing->status = replacement->status = Sector::CONFLICT;
}
@@ -77,7 +76,7 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
{
for (int head : iterate(config.heads()))
{
auto track = std::make_unique<TrackFlux>();
auto track = std::make_shared<TrackFlux>();
std::set<std::shared_ptr<Sector>> track_sectors;
std::set<std::shared_ptr<Record>> track_records;
Fluxmap totalFlux;
@@ -87,65 +86,49 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
auto fluxmap = readFluxmap(fluxsource, cylinder, head);
totalFlux.appendDesync().appendBytes(fluxmap->rawBytes());
{
auto trackdata = decoder.decodeToSectors(fluxmap, cylinder, head);
auto trackdataflux = decoder.decodeToSectors(fluxmap, cylinder, head);
track->trackDatas.push_back(trackdataflux);
std::cout << " ";
std::cout << fmt::format("{} records, {} sectors; ",
trackdata->records.size(),
trackdata->sectors.size());
if (trackdata->sectors.size() > 0)
{
nanoseconds_t clock = (*trackdata->sectors.begin())->clock;
std::cout << fmt::format("{:.2f}us clock ({:.0f}kHz); ",
clock / 1000.0, 1000000.0 / clock);
}
track_sectors.insert(trackdata->sectors.begin(), trackdata->sectors.end());
track_records.insert(trackdata->records.begin(), trackdata->records.end());
track->trackDatas.push_back(std::move(trackdata));
}
track_sectors.insert(trackdataflux->sectors.begin(), trackdataflux->sectors.end());
track_records.insert(trackdataflux->records.begin(), trackdataflux->records.end());
auto collected_sectors = collect_sectors(track_sectors);
std::cout << fmt::format("{} distinct sectors; ", collected_sectors.size());
bool hasBadSectors = false;
std::set<unsigned> required_sectors = decoder.requiredSectors(cylinder, head);
std::set<std::shared_ptr<Sector>> result_sectors;
for (const auto& sector : collected_sectors)
{
result_sectors.insert(sector);
required_sectors.erase(sector->logicalSector);
if (sector->status != Sector::OK)
{
std::cout << std::endl
<< " Failed to read sector " << sector->logicalSector
<< " (" << Sector::statusToString(sector->status) << "); ";
hasBadSectors = true;
}
}
for (unsigned logical_sector : required_sectors)
{
std::cout << "\n"
<< " Required sector " << logical_sector << " missing; ";
auto sector = std::make_shared<Sector>();
sector->logicalSector = logical_sector;
sector->status = Sector::MISSING;
result_sectors.insert(sector);
hasBadSectors = true;
}
Logger() << SingleReadLogMessage { trackdataflux, result_sectors };
if (hasBadSectors)
failures = false;
std::cout << std::endl
<< " ";
if (!hasBadSectors)
break;
if (!fluxsource.retryable())
break;
if (retry == 0)
std::cout << "giving up" << std::endl
<< " ";
Logger() << fmt::format("giving up");
else
std::cout << retry << " retries remaining" << std::endl;
Logger() << fmt::format("retrying; {} retries remaining", retry);
}
if (outputFluxSink)
@@ -181,24 +164,9 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
}
}
int size = 0;
std::set<std::pair<int, int>> track_ids;
for (const auto& sector : track_sectors)
{
track_ids.insert(std::make_pair(sector->logicalTrack, sector->logicalSide));
size += sector->data.size();
}
if (!track_ids.empty())
{
std::cout << "logical track ";
for (const auto& i : track_ids)
std::cout << fmt::format("{}.{}; ", i.first, i.second);
}
std::cout << size << " bytes decoded." << std::endl;
track->sectors = collect_sectors(track_sectors);
diskflux->tracks.push_back(std::move(track));
Logger() << TrackReadLogMessage { track };
diskflux->tracks.push_back(track);
}
}

View File

@@ -2,7 +2,7 @@
#include "sector.h"
#include "fmt/format.h"
const std::string Sector::statusToString(Status status)
std::string Sector::statusToString(Status status)
{
switch (status)
{
@@ -15,6 +15,19 @@ const std::string Sector::statusToString(Status status)
}
}
std::string Sector::statusToChar(Status status)
{
switch (status)
{
case Status::OK: return "";
case Status::MISSING: return "?";
case Status::BAD_CHECKSUM: return "!";
case Status::DATA_MISSING: return "!";
case Status::CONFLICT: return "*";
default: return "?";
}
}
Sector::Status Sector::stringToStatus(const std::string& value)
{
if (value == "OK")

View File

@@ -24,7 +24,8 @@ public:
INTERNAL_ERROR
};
static const std::string statusToString(Status status);
static std::string statusToString(Status status);
static std::string statusToChar(Status status);
static Status stringToStatus(const std::string& value);
Status status = Status::INTERNAL_ERROR;

View File

@@ -12,144 +12,177 @@
#include "fmt/format.h"
#include "sector.h"
#include "image.h"
#include "logger.h"
#include "lib/config.pb.h"
#include "proto.h"
void writeTracks(
FluxSink& fluxSink,
const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
void writeTracks(FluxSink& fluxSink,
const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
{
std::cout << "Writing to: " << fluxSink << std::endl;
for (unsigned cylinder : iterate(config.cylinders()))
{
for (unsigned head : iterate(config.heads()))
{
Logger() << DiskContextLogMessage(cylinder, head)
<< fmt::format("{0:>3}.{1}: writing", cylinder, head)
<< BeginWriteOperationLogMessage();
for (unsigned cylinder : iterate(config.cylinders()))
{
for (unsigned head : iterate(config.heads()))
{
std::cout << fmt::format("{0:>3}.{1}: ", cylinder, head) << std::flush;
std::unique_ptr<Fluxmap> fluxmap = producer(cylinder, head);
if (!fluxmap)
{
/* Erase this track rather than writing. */
std::unique_ptr<Fluxmap> fluxmap = producer(cylinder, head);
if (!fluxmap)
{
/* Erase this track rather than writing. */
fluxmap.reset(new Fluxmap());
fluxSink.writeFlux(cylinder, head, *fluxmap);
std::cout << "erased\n";
}
else
{
fluxmap->rescale(config.flux_sink().rescale());
/* Precompensation actually seems to make things worse, so let's leave
* it disabled for now. */
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
fluxSink.writeFlux(cylinder, head, *fluxmap);
std::cout << fmt::format(
"{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl;
}
}
fluxmap.reset(new Fluxmap());
fluxSink.writeFlux(cylinder, head, *fluxmap);
Logger() << "erased";
}
else
{
fluxmap->rescale(config.flux_sink().rescale());
/* Precompensation actually seems to make things worse, so let's
* leave it disabled for now. */
// fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
fluxSink.writeFlux(cylinder, head, *fluxmap);
Logger() << fmt::format("{0} ms in {1} bytes",
int(fluxmap->duration() / 1e6),
fluxmap->bytes());
}
Logger() << EndWriteOperationLogMessage();
}
}
}
void writeTracksAndVerify(
FluxSink& fluxSink,
AbstractEncoder& encoder,
FluxSource& fluxSource,
AbstractDecoder& decoder,
const Image& image)
void writeTracksAndVerify(FluxSink& fluxSink,
AbstractEncoder& encoder,
FluxSource& fluxSource,
AbstractDecoder& decoder,
const Image& image)
{
std::cout << "Writing to: " << fluxSink << std::endl;
for (unsigned cylinder : iterate(config.cylinders()))
{
for (unsigned head : iterate(config.heads()))
{
std::cout << fmt::format("{0:>3}.{1}: Write: ", cylinder, head) << std::flush;
auto sectors = encoder.collectSectors(cylinder, head, image);
std::unique_ptr<Fluxmap> fluxmap = encoder.encode(cylinder, head, sectors, image);
if (!fluxmap)
{
/* Erase this track rather than writing. */
for (unsigned cylinder : iterate(config.cylinders()))
{
for (unsigned head : iterate(config.heads()))
{
Logger() << DiskContextLogMessage { cylinder, head }
<< fmt::format("{0:>3}.{1}", cylinder, head);
fluxmap.reset(new Fluxmap());
fluxSink.writeFlux(cylinder, head, *fluxmap);
std::cout << "erased\n";
}
else
{
fluxmap->rescale(config.flux_sink().rescale());
std::sort(sectors.begin(), sectors.end(), sectorPointerSortPredicate);
auto sectors = encoder.collectSectors(cylinder, head, image);
std::unique_ptr<Fluxmap> fluxmap =
encoder.encode(cylinder, head, sectors, image);
if (!fluxmap)
{
/* Erase this track rather than writing. */
for (int retry = 0;; retry++)
{
/* Precompensation actually seems to make things worse, so let's leave
* it disabled for now. */
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
fluxSink.writeFlux(cylinder, head, *fluxmap);
std::cout << fmt::format(
"{0} ms in {1} bytes\n", int(fluxmap->duration()/1e6), fluxmap->bytes());
Logger() << BeginWriteOperationLogMessage() << "erasing";
fluxmap.reset(new Fluxmap());
fluxSink.writeFlux(cylinder, head, *fluxmap);
Logger() << EndWriteOperationLogMessage();
}
else
{
fluxmap->rescale(config.flux_sink().rescale());
std::sort(
sectors.begin(), sectors.end(), sectorPointerSortPredicate);
std::cout << fmt::format(" Verify: ", cylinder, head) << std::flush;
std::shared_ptr<Fluxmap> writtenFluxmap = fluxSource.readFlux(cylinder, head);
std::cout << fmt::format(
"{0} ms in {1} bytes\n", int(writtenFluxmap->duration()/1e6), writtenFluxmap->bytes());
const auto trackdata = decoder.decodeToSectors(writtenFluxmap, cylinder, head);
for (int retry = 0;; retry++)
{
/* Precompensation actually seems to make things worse, so
* let's leave it disabled for now. */
// fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS,
// 2);
Logger() << BeginWriteOperationLogMessage() << "writing";
fluxSink.writeFlux(cylinder, head, *fluxmap);
Logger() << EndWriteOperationLogMessage()
<< fmt::format("{0} ms in {1} bytes",
int(fluxmap->duration() / 1e6),
fluxmap->bytes());
std::vector<std::shared_ptr<Sector>> gotSectors = trackdata->sectors;
gotSectors.erase(std::remove_if(gotSectors.begin(), gotSectors.end(),
[](const auto& s) { return s->status != Sector::OK; }), gotSectors.end());
std::sort(gotSectors.begin(), gotSectors.end(), sectorPointerSortPredicate);
gotSectors.erase(std::unique(gotSectors.begin(), gotSectors.end(),
sectorPointerEqualsPredicate), gotSectors.end());
Logger() << "verifying" << BeginReadOperationLogMessage();
std::shared_ptr<Fluxmap> writtenFluxmap =
fluxSource.readFlux(cylinder, head);
Logger() << EndReadOperationLogMessage()
<< fmt::format("{0} ms in {1} bytes",
int(writtenFluxmap->duration() / 1e6),
writtenFluxmap->bytes());
if (std::equal(gotSectors.begin(), gotSectors.end(), sectors.begin(), sectors.end(),
sectorPointerEqualsPredicate))
break;
const auto trackdata =
decoder.decodeToSectors(writtenFluxmap, cylinder, head);
if (retry == config.decoder().retries())
Error() << "Write failed; uncorrectable error during write.";
std::vector<std::shared_ptr<Sector>> gotSectors =
trackdata->sectors;
gotSectors.erase(std::remove_if(gotSectors.begin(),
gotSectors.end(),
[](const auto& s)
{
return s->status != Sector::OK;
}),
gotSectors.end());
std::sort(gotSectors.begin(),
gotSectors.end(),
sectorPointerSortPredicate);
gotSectors.erase(std::unique(gotSectors.begin(),
gotSectors.end(),
sectorPointerEqualsPredicate),
gotSectors.end());
std::cout << fmt::format(" Rewrite: ", cylinder, head) << std::flush;
}
}
}
if (std::equal(gotSectors.begin(),
gotSectors.end(),
sectors.begin(),
sectors.end(),
sectorPointerEqualsPredicate))
break;
if (retry == config.decoder().retries())
Error() << "Write failed; uncorrectable error during "
"write.";
Logger() << "retrying";
}
}
}
}
}
void fillBitmapTo(std::vector<bool>& bitmap,
unsigned& cursor, unsigned terminateAt,
const std::vector<bool>& pattern)
unsigned& cursor,
unsigned terminateAt,
const std::vector<bool>& pattern)
{
while (cursor < terminateAt)
{
for (bool b : pattern)
{
if (cursor < bitmap.size())
bitmap[cursor++] = b;
}
}
while (cursor < terminateAt)
{
for (bool b : pattern)
{
if (cursor < bitmap.size())
bitmap[cursor++] = b;
}
}
}
void writeDiskCommand(const Image& image, AbstractEncoder& encoder, FluxSink& fluxSink,
AbstractDecoder* decoder, FluxSource* fluxSource)
void writeDiskCommand(const Image& image,
AbstractEncoder& encoder,
FluxSink& fluxSink,
AbstractDecoder* decoder,
FluxSource* fluxSource)
{
if (fluxSource && decoder)
writeTracksAndVerify(fluxSink, encoder, *fluxSource, *decoder, image);
else
writeTracks(fluxSink,
[&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
{
const auto& sectors = encoder.collectSectors(physicalTrack, physicalSide, image);
return encoder.encode(physicalTrack, physicalSide, sectors, image);
}
);
if (fluxSource && decoder)
writeTracksAndVerify(fluxSink, encoder, *fluxSource, *decoder, image);
else
writeTracks(fluxSink,
[&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
{
const auto& sectors =
encoder.collectSectors(physicalTrack, physicalSide, image);
return encoder.encode(
physicalTrack, physicalSide, sectors, image);
});
}
void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink)
{
writeTracks(fluxSink,
[&](int track, int side) -> std::unique_ptr<Fluxmap>
{
return fluxSource.readFlux(track, side);
}
);
writeTracks(fluxSink,
[&](int track, int side) -> std::unique_ptr<Fluxmap>
{
return fluxSource.readFlux(track, side);
});
}

View File

@@ -472,6 +472,7 @@ buildlibrary libbackend.a \
lib/imagewriter/rawimagewriter.cc \
lib/imginputoutpututils.cc \
lib/ldbs.cc \
lib/logger.cc \
lib/proto.cc \
lib/reader.cc \
lib/sector.cc \