Massive overhaul of how the physical/logical layout mapping is done, to make it

more consistent and bidirectional everywhere and just generally better.
Hopefully this fixes that pesky 1581 problem.
This commit is contained in:
David Given
2022-09-15 20:23:33 +02:00
parent 4bf5fd49d6
commit 9a8fc80220
31 changed files with 856 additions and 762 deletions

View File

@@ -32,200 +32,204 @@
std::unique_ptr<Decoder> Decoder::create(const DecoderProto& config)
{
static const std::map<int,
std::function<std::unique_ptr<Decoder>(const DecoderProto&)>> decoders =
{
{ DecoderProto::kAgat, createAgatDecoder },
{ DecoderProto::kAeslanier, createAesLanierDecoder },
{ DecoderProto::kAmiga, createAmigaDecoder },
{ DecoderProto::kApple2, createApple2Decoder },
{ DecoderProto::kBrother, createBrotherDecoder },
{ DecoderProto::kC64, createCommodore64Decoder },
{ DecoderProto::kF85, createDurangoF85Decoder },
{ DecoderProto::kFb100, createFb100Decoder },
{ DecoderProto::kIbm, createIbmDecoder },
{ DecoderProto::kMacintosh, createMacintoshDecoder },
{ DecoderProto::kMicropolis, createMicropolisDecoder },
{ DecoderProto::kMx, createMxDecoder },
{ DecoderProto::kNorthstar, createNorthstarDecoder },
{ DecoderProto::kTids990, createTids990Decoder },
{ DecoderProto::kVictor9K, createVictor9kDecoder },
{ DecoderProto::kZilogmcz, createZilogMczDecoder },
};
static const std::map<int,
std::function<std::unique_ptr<Decoder>(const DecoderProto&)>>
decoders = {
{DecoderProto::kAgat, createAgatDecoder },
{DecoderProto::kAeslanier, createAesLanierDecoder },
{DecoderProto::kAmiga, createAmigaDecoder },
{DecoderProto::kApple2, createApple2Decoder },
{DecoderProto::kBrother, createBrotherDecoder },
{DecoderProto::kC64, createCommodore64Decoder},
{DecoderProto::kF85, createDurangoF85Decoder },
{DecoderProto::kFb100, createFb100Decoder },
{DecoderProto::kIbm, createIbmDecoder },
{DecoderProto::kMacintosh, createMacintoshDecoder },
{DecoderProto::kMicropolis, createMicropolisDecoder },
{DecoderProto::kMx, createMxDecoder },
{DecoderProto::kNorthstar, createNorthstarDecoder },
{DecoderProto::kTids990, createTids990Decoder },
{DecoderProto::kVictor9K, createVictor9kDecoder },
{DecoderProto::kZilogmcz, createZilogMczDecoder },
};
auto decoder = decoders.find(config.format_case());
if (decoder == decoders.end())
Error() << "no decoder specified";
auto decoder = decoders.find(config.format_case());
if (decoder == decoders.end())
Error() << "no decoder specified";
return (decoder->second)(config);
return (decoder->second)(config);
}
std::shared_ptr<const TrackDataFlux> Decoder::decodeToSectors(
std::shared_ptr<const Fluxmap> fluxmap, const Location& location)
std::shared_ptr<const Fluxmap> fluxmap, const Location& location)
{
_trackdata = std::make_shared<TrackDataFlux>();
_trackdata->fluxmap = fluxmap;
_trackdata->location = location;
_trackdata = std::make_shared<TrackDataFlux>();
_trackdata->fluxmap = fluxmap;
_trackdata->location = location;
FluxmapReader fmr(*fluxmap);
_fmr = &fmr;
auto newSector = [&] {
_sector = std::make_shared<Sector>();
_sector->status = Sector::MISSING;
_sector->logicalTrack = location.logicalTrack;
_sector->logicalSide = location.head;
_sector->physicalTrack = location.physicalTrack;
_sector->physicalHead = location.head;
};
auto newSector = [&]
{
_sector = std::make_shared<Sector>(location);
_sector->status = Sector::MISSING;
};
newSector();
newSector();
beginTrack();
for (;;)
{
newSector();
newSector();
Fluxmap::Position recordStart = fmr.tell();
_sector->clock = advanceToNextRecord();
if (fmr.eof() || !_sector->clock)
if (fmr.eof() || !_sector->clock)
return _trackdata;
/* Read the sector record. */
Fluxmap::Position before = fmr.tell();
Fluxmap::Position before = fmr.tell();
decodeSectorRecord();
Fluxmap::Position after = fmr.tell();
pushRecord(before, after);
Fluxmap::Position after = fmr.tell();
pushRecord(before, after);
if (_sector->status != Sector::DATA_MISSING)
{
_sector->position = before.bytes;
_sector->dataStartTime = before.ns();
_sector->dataEndTime = after.ns();
}
else
{
_sector->position = before.bytes;
_sector->dataStartTime = before.ns();
_sector->dataEndTime = after.ns();
}
else
{
/* The data is in a separate record. */
for (;;)
{
_sector->headerStartTime = before.ns();
_sector->headerEndTime = after.ns();
for (;;)
{
_sector->headerStartTime = before.ns();
_sector->headerEndTime = after.ns();
_sector->clock = advanceToNextRecord();
if (fmr.eof() || !_sector->clock)
break;
_sector->clock = advanceToNextRecord();
if (fmr.eof() || !_sector->clock)
break;
before = fmr.tell();
decodeDataRecord();
after = fmr.tell();
before = fmr.tell();
decodeDataRecord();
after = fmr.tell();
if (_sector->status != Sector::DATA_MISSING)
{
_sector->position = before.bytes;
_sector->dataStartTime = before.ns();
_sector->dataEndTime = after.ns();
pushRecord(before, after);
break;
}
if (_sector->status != Sector::DATA_MISSING)
{
_sector->position = before.bytes;
_sector->dataStartTime = before.ns();
_sector->dataEndTime = after.ns();
pushRecord(before, after);
break;
}
fmr.skipToEvent(F_BIT_PULSE);
resetFluxDecoder();
}
fmr.skipToEvent(F_BIT_PULSE);
resetFluxDecoder();
}
}
if (_sector->status != Sector::MISSING)
{
auto& trackLayout = Layout::getLayoutOfTrack(_sector->logicalTrack, _sector->logicalSide);
_trackdata->sectors.push_back(_sector);
auto& trackLayout = Layout::getLayoutOfTrack(
_sector->logicalTrack, _sector->logicalSide);
_trackdata->sectors.push_back(_sector);
}
}
}
void Decoder::pushRecord(const Fluxmap::Position& start, const Fluxmap::Position& end)
void Decoder::pushRecord(
const Fluxmap::Position& start, const Fluxmap::Position& end)
{
Fluxmap::Position here = _fmr->tell();
auto record = std::make_shared<Record>();
_trackdata->records.push_back(record);
_sector->records.push_back(record);
record->startTime = start.ns();
record->endTime = end.ns();
auto record = std::make_shared<Record>();
_trackdata->records.push_back(record);
_sector->records.push_back(record);
record->startTime = start.ns();
record->endTime = end.ns();
record->clock = _sector->clock;
record->rawData = toBytes(_recordBits);
_recordBits.clear();
record->rawData = toBytes(_recordBits);
_recordBits.clear();
}
void Decoder::resetFluxDecoder()
{
_decoder.reset(new FluxDecoder(_fmr, _sector->clock, _config));
_decoder.reset(new FluxDecoder(_fmr, _sector->clock, _config));
}
nanoseconds_t Decoder::seekToPattern(const FluxMatcher& pattern)
{
nanoseconds_t clock = _fmr->seekToPattern(pattern);
_decoder.reset(new FluxDecoder(_fmr, clock, _config));
return clock;
nanoseconds_t clock = _fmr->seekToPattern(pattern);
_decoder.reset(new FluxDecoder(_fmr, clock, _config));
return clock;
}
void Decoder::seekToIndexMark()
{
_fmr->skipToEvent(F_BIT_PULSE);
_fmr->seekToIndexMark();
_fmr->skipToEvent(F_BIT_PULSE);
_fmr->seekToIndexMark();
}
std::vector<bool> Decoder::readRawBits(unsigned count)
{
auto bits = _decoder->readBits(count);
_recordBits.insert(_recordBits.end(), bits.begin(), bits.end());
return bits;
auto bits = _decoder->readBits(count);
_recordBits.insert(_recordBits.end(), bits.begin(), bits.end());
return bits;
}
uint8_t Decoder::readRaw8()
{
return toBytes(readRawBits(8)).reader().read_8();
return toBytes(readRawBits(8)).reader().read_8();
}
uint16_t Decoder::readRaw16()
{
return toBytes(readRawBits(16)).reader().read_be16();
return toBytes(readRawBits(16)).reader().read_be16();
}
uint32_t Decoder::readRaw20()
{
std::vector<bool> bits(4);
for (bool b : readRawBits(20))
bits.push_back(b);
std::vector<bool> bits(4);
for (bool b : readRawBits(20))
bits.push_back(b);
return toBytes(bits).reader().read_be24();
return toBytes(bits).reader().read_be24();
}
uint32_t Decoder::readRaw24()
{
return toBytes(readRawBits(24)).reader().read_be24();
return toBytes(readRawBits(24)).reader().read_be24();
}
uint32_t Decoder::readRaw32()
{
return toBytes(readRawBits(32)).reader().read_be32();
return toBytes(readRawBits(32)).reader().read_be32();
}
uint64_t Decoder::readRaw48()
{
return toBytes(readRawBits(48)).reader().read_be48();
return toBytes(readRawBits(48)).reader().read_be48();
}
uint64_t Decoder::readRaw64()
{
return toBytes(readRawBits(64)).reader().read_be64();
return toBytes(readRawBits(64)).reader().read_be64();
}
std::set<unsigned> Decoder::requiredSectors(const Location& location) const
std::set<LogicalLocation> Decoder::requiredSectors(
const Location& location) const
{
const auto& trackLayout = Layout::getLayoutOfTrack(location.logicalTrack, location.head);
return std::set(trackLayout.logicalSectorOrder.begin(), trackLayout.logicalSectorOrder.end());
}
const auto& trackLayout =
Layout::getLayoutOfTrackPhysical(location.physicalTrack, location.physicalSide);
std::set<LogicalLocation> results;
for (unsigned sectorId : trackLayout.logicalSectorOrder)
results.insert(LogicalLocation{
trackLayout.logicalTrack, trackLayout.logicalSide, sectorId});
return results;
}

View File

@@ -89,7 +89,7 @@ public:
return _fmr->getDuration();
}
virtual std::set<unsigned> requiredSectors(const Location& location) const;
virtual std::set<LogicalLocation> requiredSectors(const Location& location) const;
protected:
virtual void beginTrack(){};

View File

@@ -59,7 +59,7 @@ nanoseconds_t Encoder::calculatePhysicalClockPeriod(
std::shared_ptr<const Sector> Encoder::getSector(
const Location& location, const Image& image, unsigned sectorId)
{
return image.get(location.logicalTrack, location.head, sectorId);
return image.get(location.logicalTrack, location.logicalSide, sectorId);
}
std::vector<std::shared_ptr<const Sector>> Encoder::collectSectors(
@@ -68,14 +68,14 @@ std::vector<std::shared_ptr<const Sector>> Encoder::collectSectors(
std::vector<std::shared_ptr<const Sector>> sectors;
const auto& trackLayout =
Layout::getLayoutOfTrack(location.logicalTrack, location.head);
Layout::getLayoutOfTrack(location.logicalTrack, location.logicalSide);
for (unsigned sectorId : trackLayout.diskSectorOrder)
{
const auto& sector = getSector(location, image, sectorId);
if (!sector)
Error() << fmt::format("sector {}.{}.{} is missing from the image",
location.logicalTrack,
location.head,
location.logicalSide,
sectorId);
sectors.push_back(sector);
}

View File

@@ -18,24 +18,25 @@ struct Record
struct Location
{
unsigned physicalTrack;
unsigned physicalSide;
unsigned logicalTrack;
unsigned head;
unsigned logicalSide;
unsigned groupSize;
bool operator==(const Location& other) const
{
if (physicalTrack == other.physicalTrack)
return true;
return head == other.head;
return key() == other.key();
}
bool operator<(const Location& other) const
{
if (physicalTrack < other.physicalTrack)
return true;
if (physicalTrack == other.physicalTrack)
return head < other.head;
return false;
return key() < other.key();
}
private:
std::tuple<unsigned, unsigned> key() const
{
return std::make_tuple(physicalTrack, physicalSide);
}
};

View File

@@ -51,11 +51,11 @@ public:
}
public:
std::unique_ptr<FluxSourceIterator> readFlux(int track, int head) override
std::unique_ptr<FluxSourceIterator> readFlux(int physicalTrack, int physicalSide) override
{
for (const auto& trackFlux : _flux.tracks)
{
if ((trackFlux->location.physicalTrack == track) && (trackFlux->location.head == head))
if ((trackFlux->location.physicalTrack == physicalTrack) && (trackFlux->location.physicalSide == physicalSide))
return std::make_unique<MemoryFluxSourceIterator>(*trackFlux);
}

View File

@@ -69,7 +69,7 @@ std::shared_ptr<Sector> Image::put(
sector->logicalSide = side;
sector->logicalSector = sectorid;
sector->physicalTrack = Layout::remapTrackLogicalToPhysical(track);
sector->physicalHead = side;
sector->physicalSide = side;
_sectors[key] = sector;
return sector;
}

View File

@@ -384,14 +384,14 @@ public:
if (blnOptionalHeadMap) //there was een optional head map. write it to the sector
//The Sector Head Map has one entry for each sector, and contains the logical Head ID for the corresponding sector in the Sector Numbering Map.
{
sector->physicalHead = header.Head;
sector->physicalSide = header.Head;
sector->logicalSide = optionalhead_map[s];
blnOptionalHeadMap = false;
}
else
{
sector->logicalSide = header.Head;
sector->physicalHead = header.Head;
sector->physicalSide = header.Head;
}
}

View File

@@ -112,7 +112,7 @@ public:
break;
uint8_t physicalTrack = br.read_8();
uint8_t physicalHead = br.read_8() & 1;
uint8_t physicalSide = br.read_8() & 1;
br.skip(1); /* crc */
for (int i = 0; i < sectorCount; i++)
@@ -186,7 +186,7 @@ public:
image->put(logicalTrack, logicalSide, sectorId);
sector->status = Sector::OK;
sector->physicalTrack = physicalTrack;
sector->physicalHead = physicalHead;
sector->physicalSide = physicalSide;
sector->data = data.slice(0, sectorSize);
totalSize += sectorSize;
}

View File

@@ -109,7 +109,7 @@ void ImageWriter::writeCsv(const Image& image, const std::string& filename)
{
f << fmt::format("{},{},{},{},{},{},{},{},{},{},{},{},{}\n",
sector->physicalTrack,
sector->physicalHead,
sector->physicalSide,
sector->logicalSector,
sector->logicalTrack,
sector->logicalSide,

View File

@@ -266,7 +266,7 @@ public:
{
blnOptionalCylinderMap = true;
}
if (sector->logicalSide != sector->physicalHead) //different physicalside fromn logicalside
if (sector->logicalSide != sector->physicalSide) //different physicalside fromn logicalside
{
blnOptionalHeadMap = true;
}

View File

@@ -7,11 +7,6 @@
static Local<std::map<std::pair<int, int>, std::unique_ptr<Layout>>>
layoutCache;
unsigned Layout::remapTrackPhysicalToLogical(unsigned ptrack)
{
return (ptrack - config.drive().head_bias()) / config.drive().head_width();
}
static unsigned getTrackStep()
{
unsigned track_step =
@@ -23,15 +18,28 @@ static unsigned getTrackStep()
return track_step;
}
unsigned Layout::remapTrackPhysicalToLogical(unsigned ptrack)
{
return (ptrack - config.drive().head_bias()) / getTrackStep();
}
unsigned Layout::remapTrackLogicalToPhysical(unsigned ltrack)
{
return config.drive().head_bias() + ltrack * getTrackStep();
}
unsigned Layout::remapSidePhysicalToLogical(unsigned pside)
{
return pside ^ config.layout().swap_sides();
}
unsigned Layout::remapSideLogicalToPhysical(unsigned lside)
{
return lside ^ config.layout().swap_sides();
}
std::set<Location> Layout::computeLocations()
{
std::set<Location> locations;
std::set<unsigned> tracks;
if (config.has_tracks())
tracks = iterate(config.tracks());
@@ -44,32 +52,29 @@ std::set<Location> Layout::computeLocations()
else
heads = iterate(0, config.layout().sides());
std::set<Location> locations;
for (unsigned logicalTrack : tracks)
{
for (unsigned head : heads)
locations.insert(computeLocationFor(logicalTrack, head));
for (unsigned logicalHead : heads)
locations.insert(computeLocationFor(logicalTrack, logicalHead));
}
return locations;
}
Location Layout::computeLocationFor(unsigned logicalTrack, unsigned logicalHead)
Location Layout::computeLocationFor(unsigned logicalTrack, unsigned logicalSide)
{
if ((logicalTrack < config.layout().tracks()) &&
(logicalHead < config.layout().sides()))
(logicalSide < config.layout().sides()))
{
unsigned track_step = getTrackStep();
unsigned physicalTrack =
config.drive().head_bias() + logicalTrack * track_step;
return {.physicalTrack = physicalTrack,
return Location {.physicalTrack = remapTrackLogicalToPhysical(logicalTrack),
.physicalSide = remapSideLogicalToPhysical(logicalSide),
.logicalTrack = logicalTrack,
.head = logicalHead,
.groupSize = track_step};
.logicalSide = logicalSide,
.groupSize = getTrackStep()};
}
Error() << fmt::format(
"track {}.{} is not part of the image", logicalTrack, logicalHead);
"track {}.{} is not part of the image", logicalTrack, logicalSide);
}
std::vector<std::pair<int, int>> Layout::getTrackOrdering(
@@ -131,14 +136,15 @@ std::vector<unsigned> Layout::expandSectorList(
sectors.push_back(sectorId);
}
else
Error() << "LAYOUT: no sectors in track!";
Error() << "LAYOUT: no sectors in sector definition!";
return sectors;
}
const Layout& Layout::getLayoutOfTrack(unsigned track, unsigned side)
const Layout& Layout::getLayoutOfTrack(
unsigned logicalTrack, unsigned logicalSide)
{
auto& layout = (*layoutCache)[std::make_pair(track, side)];
auto& layout = (*layoutCache)[std::make_pair(logicalTrack, logicalSide)];
if (!layout)
{
layout.reset(new Layout());
@@ -147,11 +153,13 @@ const Layout& Layout::getLayoutOfTrack(unsigned track, unsigned side)
for (const auto& f : config.layout().layoutdata())
{
if (f.has_track() && f.has_up_to_track() &&
((track < f.track()) || (track > f.up_to_track())))
((logicalTrack < f.track()) ||
(logicalTrack > f.up_to_track())))
continue;
if (f.has_track() && !f.has_up_to_track() && (track != f.track()))
if (f.has_track() && !f.has_up_to_track() &&
(logicalTrack != f.track()))
continue;
if (f.has_side() && (f.side() != side))
if (f.has_side() && (f.side() != logicalSide))
continue;
layoutdata.MergeFrom(f);
@@ -160,6 +168,11 @@ const Layout& Layout::getLayoutOfTrack(unsigned track, unsigned side)
layout->numTracks = config.layout().tracks();
layout->numSides = config.layout().sides();
layout->sectorSize = layoutdata.sector_size();
layout->logicalTrack = logicalTrack;
layout->logicalSide = logicalSide;
layout->physicalTrack = remapTrackLogicalToPhysical(logicalTrack);
layout->physicalSide = logicalSide ^ config.layout().swap_sides();
layout->groupSize = getTrackStep();
layout->diskSectorOrder = expandSectorList(layoutdata.physical());
layout->logicalSectorOrder = layout->diskSectorOrder;
std::sort(
@@ -192,3 +205,10 @@ const Layout& Layout::getLayoutOfTrack(unsigned track, unsigned side)
return *layout;
}
const Layout& Layout::getLayoutOfTrackPhysical(
unsigned physicalTrack, unsigned physicalSide)
{
return getLayoutOfTrack(remapTrackPhysicalToLogical(physicalTrack),
remapSidePhysicalToLogical(physicalSide));
}

View File

@@ -16,13 +16,19 @@ private:
Layout& operator=(const Layout&);
public:
/* Translates logical track numbering (filesystem numbering) to
* the track numbering on the actual drive, taking into account tpi
* settings.
/* Translates logical track numbering (the numbers actually written in the
* sector headers) to the track numbering on the actual drive, taking into
* account tpi settings.
*/
static unsigned remapTrackPhysicalToLogical(unsigned physicalTrack);
static unsigned remapTrackLogicalToPhysical(unsigned logicalTrack);
/* Translates logical side numbering (the numbers actually written in the
* sector headers) to the sides used on the actual drive.
*/
static unsigned remapSidePhysicalToLogical(unsigned physicalSide);
static unsigned remapSideLogicalToPhysical(unsigned logicalSide);
/* Computes a Location for a given logical track and side, which
* contains the physical drive location and group size. */
static Location computeLocationFor(
@@ -42,6 +48,10 @@ public:
static const Layout& getLayoutOfTrack(
unsigned logicalTrack, unsigned logicalHead);
/* Returns the layout of a given track via physical location. */
static const Layout& getLayoutOfTrackPhysical(
unsigned physicalTrack, unsigned physicalSide);
/* Expand a SectorList into the actual sector IDs. */
static std::vector<unsigned> expandSectorList(
const SectorListProto& sectorsProto);
@@ -49,7 +59,27 @@ public:
public:
unsigned numTracks;
unsigned numSides;
/* The number of sectors in this track. */
unsigned numSectors;
/* Physical location of this track. */
unsigned physicalTrack;
/* Physical side of this track. */
unsigned physicalSide;
/* Logical location of this track. */
unsigned logicalTrack;
/* Logical side of this track. */
unsigned logicalSide;
/* The number of physical tracks which need to be written for one logical
* track. */
unsigned groupSize;
/* Number of bytes in a sector. */
unsigned sectorSize;
/* Sector IDs in disk order. */

View File

@@ -28,11 +28,11 @@ message LayoutProto
message LayoutdataProto
{
optional int32 track = 1
[ (help) = "if present, this format only applies to this track" ];
[ (help) = "if present, this format only applies to this logical track" ];
optional int32 up_to_track = 5
[ (help) = "if present, forms a range with track" ];
optional int32 side = 2
[ (help) = "if present, this format only applies to this side" ];
[ (help) = "if present, this format only applies to this logical side" ];
optional int32 sector_size = 3
[ default = 512, (help) = "number of bytes per sector" ];
@@ -51,4 +51,6 @@ message LayoutProto
[ default = 0, (help) = "number of sides in image" ];
optional Order order = 4
[ default = CHS, (help) = "the order of sectors in the filesystem" ];
optional bool swap_sides = 5
[ default = false, (help) = "the sides are inverted on this disk" ];
}

View File

@@ -163,10 +163,9 @@ BadSectorsState combineRecordAndSectors(
track_sectors.insert(
trackdataflux->sectors.begin(), trackdataflux->sectors.end());
for (unsigned logical_sector : decoder.requiredSectors(trackFlux.location))
for (auto& logicalLocation : decoder.requiredSectors(trackFlux.location))
{
auto sector = std::make_shared<Sector>(location);
sector->logicalSector = logical_sector;
auto sector = std::make_shared<Sector>(logicalLocation);
sector->status = Sector::MISSING;
track_sectors.insert(sector);
}
@@ -192,12 +191,12 @@ ReadResult readGroup(FluxSourceIteratorHolder& fluxSourceIteratorHolder,
offset += config.drive().head_width())
{
auto& fluxSourceIterator = fluxSourceIteratorHolder.getIterator(
location.physicalTrack + offset, location.head);
location.physicalTrack + offset, location.physicalSide);
if (!fluxSourceIterator.hasNext())
continue;
Logger() << BeginReadOperationLogMessage{
location.physicalTrack + offset, location.head};
location.physicalTrack + offset, location.physicalSide};
std::shared_ptr<const Fluxmap> fluxmap = fluxSourceIterator.next();
// ->rescale(
// 1.0 / config.flux_source().rescale());
@@ -248,7 +247,7 @@ void writeTracks(FluxSink& fluxSink,
unsigned physicalTrack = location.physicalTrack + offset;
Logger() << BeginWriteOperationLogMessage{
physicalTrack, location.head};
physicalTrack, location.physicalSide};
if (offset == config.drive().group_offset())
{
@@ -256,7 +255,8 @@ void writeTracks(FluxSink& fluxSink,
if (!fluxmap)
goto erase;
fluxSink.writeFlux(physicalTrack, location.head, *fluxmap);
fluxSink.writeFlux(
physicalTrack, location.physicalSide, *fluxmap);
Logger() << fmt::format("writing {0} ms in {1} bytes",
int(fluxmap->duration() / 1e6),
fluxmap->bytes());
@@ -267,7 +267,8 @@ void writeTracks(FluxSink& fluxSink,
/* Erase this track rather than writing. */
Fluxmap blank;
fluxSink.writeFlux(physicalTrack, location.head, blank);
fluxSink.writeFlux(
physicalTrack, location.physicalSide, blank);
Logger() << "erased";
}
@@ -301,7 +302,10 @@ void writeTracks(FluxSink& fluxSink,
auto sectors = encoder.collectSectors(location, image);
return encoder.encode(location, sectors, image);
},
[](const auto&) { return true; },
[](const auto&)
{
return true;
},
locations);
}
@@ -401,10 +405,14 @@ void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink)
fluxSink,
[&](const Location& location)
{
return fluxSource.readFlux(location.physicalTrack, location.head)
return fluxSource
.readFlux(location.physicalTrack, location.physicalSide)
->next();
},
[](const auto&){return true;},
[](const auto&)
{
return true;
},
Layout::computeLocations());
}
@@ -468,8 +476,9 @@ std::shared_ptr<const DiskFlux> readDiskCommand(
if (outputFluxSink)
{
for (const auto& data : trackFlux->trackDatas)
outputFluxSink->writeFlux(
location.physicalTrack, location.head, *data->fluxmap);
outputFluxSink->writeFlux(location.physicalTrack,
location.physicalSide,
*data->fluxmap);
}
if (config.decoder().dump_records())

View File

@@ -1,13 +1,19 @@
#include "globals.h"
#include "flux.h"
#include "sector.h"
#include "layout.h"
#include "fmt/format.h"
Sector::Sector(const LogicalLocation& location):
LogicalLocation(location),
physicalTrack(Layout::remapTrackLogicalToPhysical(location.logicalTrack)),
physicalSide(Layout::remapSideLogicalToPhysical(location.logicalSide))
{}
Sector::Sector(const Location& location):
LogicalLocation({ location.logicalTrack, location.logicalSide, 0 }),
physicalTrack(location.physicalTrack),
physicalHead(location.head),
logicalTrack(location.logicalTrack),
logicalSide(location.head)
physicalSide(location.physicalSide)
{}
std::string Sector::statusToString(Status status)

View File

@@ -7,14 +7,36 @@
class Record;
class Location;
/*
* Note that sectors here used zero-based numbering throughout (to make the
* maths easier); traditionally floppy disk use 0-based track numbering and
* 1-based sector numbering, which makes no sense.
*/
class Sector
struct LogicalLocation
{
unsigned logicalTrack;
unsigned logicalSide;
unsigned logicalSector;
std::tuple<int, int, int> key() const
{
return std::make_tuple(
logicalTrack, logicalSide, logicalSector);
}
bool operator==(const LogicalLocation& rhs) const
{
return key() == rhs.key();
}
bool operator!=(const LogicalLocation& rhs) const
{
return key() != rhs.key();
}
bool operator<(const LogicalLocation& rhs) const
{
return key() < rhs.key();
}
};
struct Sector : public LogicalLocation
{
public:
enum Status
{
OK,
@@ -30,22 +52,21 @@ public:
static Status stringToStatus(const std::string& value);
Status status = Status::INTERNAL_ERROR;
uint32_t position;
uint32_t position = 0;
nanoseconds_t clock = 0;
nanoseconds_t headerStartTime = 0;
nanoseconds_t headerEndTime = 0;
nanoseconds_t dataStartTime = 0;
nanoseconds_t dataEndTime = 0;
unsigned physicalTrack = 0;
unsigned physicalHead = 0;
unsigned logicalTrack = 0;
unsigned logicalSide = 0;
unsigned logicalSector = 0;
unsigned physicalSide = 0;
Bytes data;
std::vector<std::shared_ptr<Record>> records;
Sector() {}
Sector(const LogicalLocation& location);
Sector(const Location& location);
std::tuple<int, int, int, Status> key() const