From 9a8fc8022047327aee5d3303c652d9eaf822f376 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 15 Sep 2022 20:23:33 +0200 Subject: [PATCH] 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. --- arch/ibm/decoder.cc | 5 +- arch/ibm/encoder.cc | 23 +- arch/ibm/ibm.proto | 1 - arch/micropolis/decoder.cc | 2 +- arch/mx/decoder.cc | 2 +- arch/northstar/decoder.cc | 2 +- arch/victor9k/encoder.cc | 2 +- lib/decoders/decoders.cc | 214 ++++----- lib/decoders/decoders.h | 2 +- lib/encoders/encoders.cc | 6 +- lib/flux.h | 19 +- lib/fluxsource/memoryfluxsource.cc | 4 +- lib/image.cc | 2 +- lib/imagereader/imdimagereader.cc | 4 +- lib/imagereader/td0imagereader.cc | 4 +- lib/imagewriter/imagewriter.cc | 2 +- lib/imagewriter/imdimagewriter.cc | 2 +- lib/layout.cc | 72 +-- lib/layout.h | 36 +- lib/layout.proto | 6 +- lib/readerwriter.cc | 35 +- lib/sector.cc | 12 +- lib/sector.h | 45 +- src/fe-analyselayout.cc | 274 ++++++----- src/formats/_commodore1541.textpb | 7 +- src/formats/commodore1581.textpb | 4 +- src/gui/customstatusbar.cc | 4 +- src/gui/fluxviewercontrol.cc | 699 +++++++++++++++-------------- src/gui/fluxviewerwindow.cc | 19 +- src/gui/main.cc | 100 ++--- src/gui/visualisationcontrol.cc | 9 +- 31 files changed, 856 insertions(+), 762 deletions(-) diff --git a/arch/ibm/decoder.cc b/arch/ibm/decoder.cc index ed1f4097..4fbaa2d5 100644 --- a/arch/ibm/decoder.cc +++ b/arch/ibm/decoder.cc @@ -141,7 +141,7 @@ public: IbmDecoderProto::TrackdataProto trackdata; getTrackFormat( - trackdata, _sector->physicalTrack, _sector->physicalHead); + trackdata, _sector->physicalTrack, _sector->physicalSide); _sector->logicalTrack = br.read_8(); _sector->logicalSide = br.read_8(); @@ -154,7 +154,8 @@ public: Sector::DATA_MISSING; /* correct but unintuitive */ if (trackdata.ignore_side_byte()) - _sector->logicalSide = _sector->physicalHead; + _sector->logicalSide = + Layout::remapSidePhysicalToLogical(_sector->physicalSide); _sector->logicalSide ^= trackdata.invert_side_byte(); if (trackdata.ignore_track_byte()) _sector->logicalTrack = _sector->physicalTrack; diff --git a/arch/ibm/encoder.cc b/arch/ibm/encoder.cc index 5db45bf1..2d9130a7 100644 --- a/arch/ibm/encoder.cc +++ b/arch/ibm/encoder.cc @@ -107,34 +107,15 @@ private: } public: - std::shared_ptr getSector( - const Location& location, const Image& image, unsigned sectorId) - { - IbmEncoderProto::TrackdataProto trackdata; - getEncoderTrackData(trackdata, location.logicalTrack, location.head); - - if (trackdata.swap_sides()) - { - Location newLocation = location; - newLocation.head ^= 1; - auto sector = std::make_shared( - *Encoder::getSector(newLocation, image, sectorId)); - sector->logicalSide ^= 1; - return sector; - } - else - return image.get(location.logicalTrack, location.head, sectorId); - } - std::unique_ptr encode(const Location& location, const std::vector>& sectors, const Image& image) override { IbmEncoderProto::TrackdataProto trackdata; - getEncoderTrackData(trackdata, location.logicalTrack, location.head); + getEncoderTrackData(trackdata, location.logicalTrack, location.logicalSide); auto& trackLayout = - Layout::getLayoutOfTrack(location.logicalTrack, location.head); + Layout::getLayoutOfTrack(location.logicalTrack, location.logicalSide); auto writeBytes = [&](const Bytes& bytes) { diff --git a/arch/ibm/ibm.proto b/arch/ibm/ibm.proto index 7d4b82c0..d750646c 100644 --- a/arch/ibm/ibm.proto +++ b/arch/ibm/ibm.proto @@ -33,7 +33,6 @@ message IbmEncoderProto { optional int32 gap1 = 10 [default=50, (help) = "size of gap 2 (the post-ID gap)"]; optional int32 gap2 = 11 [default=22, (help) = "size of gap 3 (the pre-data gap)"]; optional int32 gap3 = 12 [default=80, (help) = "size of gap 4 (the post-data or format gap)"]; - optional bool swap_sides = 14 [default=false, (help) = "swap the sides of the disk"]; optional bool invert_side_byte = 19 [default=false, (help) = "invert the side byte before writing"]; optional int32 gap_fill_byte = 18 [default=0x9254, (help) = "16-bit raw bit pattern of gap fill byte"]; optional double target_rotational_period_ms = 1 [default=200, (help) = "rotational period of target disk"]; diff --git a/arch/micropolis/decoder.cc b/arch/micropolis/decoder.cc index b581b7e6..9c151391 100644 --- a/arch/micropolis/decoder.cc +++ b/arch/micropolis/decoder.cc @@ -127,7 +127,7 @@ public: return; _sector->logicalTrack = br.read_8(); - _sector->logicalSide = _sector->physicalHead; + _sector->logicalSide = _sector->physicalSide; _sector->logicalSector = br.read_8(); if (_sector->logicalSector > 15) return; diff --git a/arch/mx/decoder.cc b/arch/mx/decoder.cc index bd758a26..57d9c912 100644 --- a/arch/mx/decoder.cc +++ b/arch/mx/decoder.cc @@ -66,7 +66,7 @@ public: uint16_t wantChecksum = br.read_be16(); _sector->logicalTrack = _sector->physicalTrack; - _sector->logicalSide = _sector->physicalHead; + _sector->logicalSide = _sector->physicalSide; _sector->logicalSector = _currentSector; _sector->data = bytes.slice(0, SECTOR_SIZE).swab(); _sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM; diff --git a/arch/northstar/decoder.cc b/arch/northstar/decoder.cc index 2f196633..f683600f 100644 --- a/arch/northstar/decoder.cc +++ b/arch/northstar/decoder.cc @@ -150,7 +150,7 @@ public: auto bytes = decodeFmMfm(rawbits).slice(0, recordSize); ByteReader br(bytes); - _sector->logicalSide = _sector->physicalHead; + _sector->logicalSide = _sector->physicalSide; _sector->logicalSector = _hardSectorId; _sector->logicalTrack = _sector->physicalTrack; diff --git a/arch/victor9k/encoder.cc b/arch/victor9k/encoder.cc index 2838275d..1578aca6 100644 --- a/arch/victor9k/encoder.cc +++ b/arch/victor9k/encoder.cc @@ -168,7 +168,7 @@ public: const Image& image) override { Victor9kEncoderProto::TrackdataProto trackdata; - getTrackFormat(trackdata, location.logicalTrack, location.head); + getTrackFormat(trackdata, location.logicalTrack, location.logicalSide); unsigned bitsPerRevolution = (trackdata.rotational_period_ms() * 1e3) / trackdata.clock_period_us(); diff --git a/lib/decoders/decoders.cc b/lib/decoders/decoders.cc index 290b14c5..d700ff6d 100644 --- a/lib/decoders/decoders.cc +++ b/lib/decoders/decoders.cc @@ -32,200 +32,204 @@ std::unique_ptr Decoder::create(const DecoderProto& config) { - static const std::map(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(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 Decoder::decodeToSectors( - std::shared_ptr fluxmap, const Location& location) + std::shared_ptr fluxmap, const Location& location) { - _trackdata = std::make_shared(); - _trackdata->fluxmap = fluxmap; - _trackdata->location = location; - + _trackdata = std::make_shared(); + _trackdata->fluxmap = fluxmap; + _trackdata->location = location; + FluxmapReader fmr(*fluxmap); _fmr = &fmr; - auto newSector = [&] { - _sector = std::make_shared(); - _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(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(); - _trackdata->records.push_back(record); - _sector->records.push_back(record); - - record->startTime = start.ns(); - record->endTime = end.ns(); + auto record = std::make_shared(); + _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 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 bits(4); - for (bool b : readRawBits(20)) - bits.push_back(b); + std::vector 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 Decoder::requiredSectors(const Location& location) const +std::set 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 results; + for (unsigned sectorId : trackLayout.logicalSectorOrder) + results.insert(LogicalLocation{ + trackLayout.logicalTrack, trackLayout.logicalSide, sectorId}); + return results; +} diff --git a/lib/decoders/decoders.h b/lib/decoders/decoders.h index 5845dc33..4af2391a 100644 --- a/lib/decoders/decoders.h +++ b/lib/decoders/decoders.h @@ -89,7 +89,7 @@ public: return _fmr->getDuration(); } - virtual std::set requiredSectors(const Location& location) const; + virtual std::set requiredSectors(const Location& location) const; protected: virtual void beginTrack(){}; diff --git a/lib/encoders/encoders.cc b/lib/encoders/encoders.cc index fd75915e..87b8d761 100644 --- a/lib/encoders/encoders.cc +++ b/lib/encoders/encoders.cc @@ -59,7 +59,7 @@ nanoseconds_t Encoder::calculatePhysicalClockPeriod( std::shared_ptr 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> Encoder::collectSectors( @@ -68,14 +68,14 @@ std::vector> Encoder::collectSectors( std::vector> 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); } diff --git a/lib/flux.h b/lib/flux.h index 17b247f6..709f07e4 100644 --- a/lib/flux.h +++ b/lib/flux.h @@ -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 key() const + { + return std::make_tuple(physicalTrack, physicalSide); } }; diff --git a/lib/fluxsource/memoryfluxsource.cc b/lib/fluxsource/memoryfluxsource.cc index c4ee1bdb..c288e7bd 100644 --- a/lib/fluxsource/memoryfluxsource.cc +++ b/lib/fluxsource/memoryfluxsource.cc @@ -51,11 +51,11 @@ public: } public: - std::unique_ptr readFlux(int track, int head) override + std::unique_ptr 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(*trackFlux); } diff --git a/lib/image.cc b/lib/image.cc index 5811cf16..b2a58919 100644 --- a/lib/image.cc +++ b/lib/image.cc @@ -69,7 +69,7 @@ std::shared_ptr Image::put( sector->logicalSide = side; sector->logicalSector = sectorid; sector->physicalTrack = Layout::remapTrackLogicalToPhysical(track); - sector->physicalHead = side; + sector->physicalSide = side; _sectors[key] = sector; return sector; } diff --git a/lib/imagereader/imdimagereader.cc b/lib/imagereader/imdimagereader.cc index ae8e79dc..05a157f7 100644 --- a/lib/imagereader/imdimagereader.cc +++ b/lib/imagereader/imdimagereader.cc @@ -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; } } diff --git a/lib/imagereader/td0imagereader.cc b/lib/imagereader/td0imagereader.cc index dcb81bdc..8f20d7a1 100644 --- a/lib/imagereader/td0imagereader.cc +++ b/lib/imagereader/td0imagereader.cc @@ -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; } diff --git a/lib/imagewriter/imagewriter.cc b/lib/imagewriter/imagewriter.cc index 32bf9ca1..f969ea0d 100644 --- a/lib/imagewriter/imagewriter.cc +++ b/lib/imagewriter/imagewriter.cc @@ -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, diff --git a/lib/imagewriter/imdimagewriter.cc b/lib/imagewriter/imdimagewriter.cc index 5f7676c0..ca56a960 100644 --- a/lib/imagewriter/imdimagewriter.cc +++ b/lib/imagewriter/imdimagewriter.cc @@ -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; } diff --git a/lib/layout.cc b/lib/layout.cc index ff06a41a..5b329697 100644 --- a/lib/layout.cc +++ b/lib/layout.cc @@ -7,11 +7,6 @@ static Local, std::unique_ptr>> 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 Layout::computeLocations() { - std::set locations; - std::set tracks; if (config.has_tracks()) tracks = iterate(config.tracks()); @@ -44,32 +52,29 @@ std::set Layout::computeLocations() else heads = iterate(0, config.layout().sides()); + std::set 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> Layout::getTrackOrdering( @@ -131,14 +136,15 @@ std::vector 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)); +} diff --git a/lib/layout.h b/lib/layout.h index 08c69e8b..55dd9cf4 100644 --- a/lib/layout.h +++ b/lib/layout.h @@ -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 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. */ diff --git a/lib/layout.proto b/lib/layout.proto index d97c121f..ba75902d 100644 --- a/lib/layout.proto +++ b/lib/layout.proto @@ -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" ]; } diff --git a/lib/readerwriter.cc b/lib/readerwriter.cc index 58f117eb..e546b802 100644 --- a/lib/readerwriter.cc +++ b/lib/readerwriter.cc @@ -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(location); - sector->logicalSector = logical_sector; + auto sector = std::make_shared(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 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 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()) diff --git a/lib/sector.cc b/lib/sector.cc index 4a27a441..96aad02b 100644 --- a/lib/sector.cc +++ b/lib/sector.cc @@ -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) diff --git a/lib/sector.h b/lib/sector.h index 1a5911bc..46a48e94 100644 --- a/lib/sector.h +++ b/lib/sector.h @@ -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 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> records; Sector() {} + Sector(const LogicalLocation& location); + Sector(const Location& location); std::tuple key() const diff --git a/src/fe-analyselayout.cc b/src/fe-analyselayout.cc index c6e6c434..958da468 100644 --- a/src/fe-analyselayout.cc +++ b/src/fe-analyselayout.cc @@ -15,40 +15,23 @@ static FlagGroup flags = {}; -static StringFlag source( - { "--csv", "-s" }, - "CSV file produced by reader", - ""); +static StringFlag source({"--csv", "-s"}, "CSV file produced by reader", ""); static StringFlag writeImg( - { "--img", "-o" }, - "Draw a graph of the disk layout", - "disklayout.png"); + {"--img", "-o"}, "Draw a graph of the disk layout", "disklayout.png"); -static IntFlag imgWidth( - { "--width" }, - "Width of output graph", - 800); +static IntFlag imgWidth({"--width"}, "Width of output graph", 800); -static IntFlag imgHeight( - { "--height" }, - "Height of output graph", - 600); +static IntFlag imgHeight({"--height"}, "Height of output graph", 600); -static IntFlag period( - { "--visualiser-period" }, +static IntFlag period({"--visualiser-period"}, "rotational period for use by the visualiser (milliseconds)", 200); -static IntFlag sideToDraw( - { "--side" }, - "side to draw; -1 for both", - -1); +static IntFlag sideToDraw({"--side"}, "side to draw; -1 for both", -1); static IntFlag alignWithSector( - { "--align" }, - "sector to align to; -1 to align to index mark", - -1); + {"--align"}, "sector to align to; -1 to align to index mark", -1); static std::ifstream inputFile; @@ -57,110 +40,115 @@ static const int TRACKS = 83; void visualiseSectorsToFile(const Image& image, const std::string& filename) { - Bitmap bitmap(writeImg, imgWidth, imgHeight); - if (bitmap.filename.empty()) - Error() << "you must specify an image filename to write to"; + Bitmap bitmap(writeImg, imgWidth, imgHeight); + if (bitmap.filename.empty()) + Error() << "you must specify an image filename to write to"; - Agg2D& painter = bitmap.painter(); - painter.clearAll(0xff, 0xff, 0xff); + Agg2D& painter = bitmap.painter(); + painter.clearAll(0xff, 0xff, 0xff); - const double radians_per_ns = 2.0*M_PI / (period*1e6); - const double available_width = bitmap.width - 2*BORDER; - const double available_height = bitmap.height - 2*BORDER; - const double panel_centre = (sideToDraw == -1) - ? (available_width / 4) - : (available_width / 2); - const double panel_size = (sideToDraw == -1) - ? std::min(available_width / 2, available_height) - : std::min(available_width, available_height); - const double disk_radius = (panel_size-BORDER) / 2; + const double radians_per_ns = 2.0 * M_PI / (period * 1e6); + const double available_width = bitmap.width - 2 * BORDER; + const double available_height = bitmap.height - 2 * BORDER; + const double panel_centre = + (sideToDraw == -1) ? (available_width / 4) : (available_width / 2); + const double panel_size = + (sideToDraw == -1) ? std::min(available_width / 2, available_height) + : std::min(available_width, available_height); + const double disk_radius = (panel_size - BORDER) / 2; auto drawSide = [&](int side) { - int xpos = BORDER + - ((sideToDraw == -1) - ? (panel_centre + side*panel_size) - : panel_centre); + int xpos = + BORDER + ((sideToDraw == -1) ? (panel_centre + side * panel_size) + : panel_centre); for (int physicalTrack = 0; physicalTrack < TRACKS; physicalTrack++) { - double visibleDistance = (TRACKS * 0.5) + (TRACKS - physicalTrack); - double radius = (disk_radius*visibleDistance)/(TRACKS * 1.5); - painter.noFill(); - painter.lineColor(0x88, 0x88, 0x88); - painter.lineWidth(disk_radius/(TRACKS*2)); - painter.ellipse(xpos, available_height/2, radius, radius); + double visibleDistance = (TRACKS * 0.5) + (TRACKS - physicalTrack); + double radius = (disk_radius * visibleDistance) / (TRACKS * 1.5); + painter.noFill(); + painter.lineColor(0x88, 0x88, 0x88); + painter.lineWidth(disk_radius / (TRACKS * 2)); + painter.ellipse(xpos, available_height / 2, radius, radius); - nanoseconds_t offset = 0; - if (alignWithSector != -1) - { - for (const auto& sector : image) - { - if ((sector->physicalHead == side) && (sector->physicalTrack == physicalTrack) - && (sector->logicalSector == alignWithSector)) - { - offset = sector->headerStartTime; - if (!offset) - offset = sector->dataStartTime; - break; - } - } - } + nanoseconds_t offset = 0; + if (alignWithSector != -1) + { + for (const auto& sector : image) + { + if ((sector->physicalSide == side) && + (sector->physicalTrack == physicalTrack) && + (sector->logicalSector == alignWithSector)) + { + offset = sector->headerStartTime; + if (!offset) + offset = sector->dataStartTime; + break; + } + } + } auto drawArc = [&](nanoseconds_t start, nanoseconds_t end) { - start = fmod(start, period*1000000.0); - end = fmod(end, period*1000000.0); + start = fmod(start, period * 1000000.0); + end = fmod(end, period * 1000000.0); if (end < start) - end += period*1000000; - + end += period * 1000000; + double theta1 = (start - offset) * radians_per_ns; double theta2 = (end - offset) * radians_per_ns; int large = (theta2 - theta1) >= M_PI; - painter.arc(xpos, available_height/2, radius, radius, theta1, theta2-theta1); + painter.arc(xpos, + available_height / 2, + radius, + radius, + theta1, + theta2 - theta1); }; /* Sadly, Images aren't indexable by physical track. */ for (const auto& sector : image) { - if ((sector->physicalHead == side) && (sector->physicalTrack == physicalTrack)) + if ((sector->physicalSide == side) && + (sector->physicalTrack == physicalTrack)) { - painter.lineColor(0xff, 0x00, 0x00); + painter.lineColor(0xff, 0x00, 0x00); if (sector->status == Sector::OK) - painter.lineColor(0x00, 0x00, 0xff); + painter.lineColor(0x00, 0x00, 0xff); if (sector->dataStartTime && sector->dataEndTime) drawArc(sector->dataStartTime, sector->dataEndTime); if (sector->headerStartTime && sector->headerEndTime) - { - painter.lineColor(0x00, 0xff, 0xff); + { + painter.lineColor(0x00, 0xff, 0xff); drawArc(sector->headerStartTime, sector->headerEndTime); - } + } } } - painter.lineColor(0xff, 0xff, 0x00); - drawArc(0, 2000); + painter.lineColor(0xff, 0xff, 0x00); + drawArc(0, 2000); } }; - switch (sideToDraw) - { - case -1: - drawSide(0); - drawSide(1); - break; + switch (sideToDraw) + { + case -1: + drawSide(0); + drawSide(1); + break; - case 0: - drawSide(0); - break; + case 0: + drawSide(0); + break; - case 1: - drawSide(1); - break; - } + case 1: + drawSide(1); + break; + } - bitmap.save(); + bitmap.save(); } static void check_for_error() @@ -171,79 +159,79 @@ static void check_for_error() static void bad_csv() { - Error() << "bad CSV file format"; + Error() << "bad CSV file format"; } static void readRow(const std::vector& row, Image& image) { - if (row.size() != 13) - bad_csv(); + if (row.size() != 13) + bad_csv(); - try - { - Sector::Status status = Sector::stringToStatus(row[12]); - if (status == Sector::Status::INTERNAL_ERROR) - bad_csv(); - if (status == Sector::Status::MISSING) - return; + try + { + Sector::Status status = Sector::stringToStatus(row[12]); + if (status == Sector::Status::INTERNAL_ERROR) + bad_csv(); + if (status == Sector::Status::MISSING) + return; - int logicalTrack = std::stoi(row[3]); - int logicalSide = std::stoi(row[4]); - int logicalSector = std::stoi(row[2]); + int logicalTrack = std::stoi(row[3]); + int logicalSide = std::stoi(row[4]); + int logicalSector = std::stoi(row[2]); - const auto& sector = image.put(logicalTrack, logicalSide, logicalSector); - sector->physicalTrack = std::stoi(row[0]); - sector->physicalHead = std::stoi(row[1]); - sector->logicalTrack = logicalTrack; - sector->logicalSide = logicalSide; - sector->logicalSector = logicalSector; - sector->clock = std::stod(row[5]); - sector->headerStartTime = std::stod(row[6]); - sector->headerEndTime = std::stod(row[7]); - sector->dataStartTime = std::stod(row[8]); - sector->dataEndTime = std::stod(row[9]); - sector->status = status; - } - catch (const std::invalid_argument& e) - { - bad_csv(); - } + const auto& sector = + image.put(logicalTrack, logicalSide, logicalSector); + sector->physicalTrack = std::stoi(row[0]); + sector->physicalSide = std::stoi(row[1]); + sector->logicalTrack = logicalTrack; + sector->logicalSide = logicalSide; + sector->logicalSector = logicalSector; + sector->clock = std::stod(row[5]); + sector->headerStartTime = std::stod(row[6]); + sector->headerEndTime = std::stod(row[7]); + sector->dataStartTime = std::stod(row[8]); + sector->dataEndTime = std::stod(row[9]); + sector->status = status; + } + catch (const std::invalid_argument& e) + { + bad_csv(); + } } static Image readCsv(const std::string& filename) { - if (filename == "") - Error() << "you must specify an input CSV file"; + if (filename == "") + Error() << "you must specify an input CSV file"; - inputFile.open(filename); - check_for_error(); + inputFile.open(filename); + check_for_error(); - CsvReader csvReader(inputFile); - std::vector row = csvReader.readLine(); - if (row.size() != 13) - bad_csv(); + CsvReader csvReader(inputFile); + std::vector row = csvReader.readLine(); + if (row.size() != 13) + bad_csv(); - Image image; - for (;;) - { - row = csvReader.readLine(); - if (row.size() == 0) - break; + Image image; + for (;;) + { + row = csvReader.readLine(); + if (row.size() == 0) + break; - readRow(row, image); - } + readRow(row, image); + } - image.calculateSize(); - return image; + image.calculateSize(); + return image; } int mainAnalyseLayout(int argc, const char* argv[]) { flags.parseFlags(argc, argv); - Image image = readCsv(source.get()); - visualiseSectorsToFile(image, "out.svg"); + Image image = readCsv(source.get()); + visualiseSectorsToFile(image, "out.svg"); - return 0; + return 0; } - diff --git a/src/formats/_commodore1541.textpb b/src/formats/_commodore1541.textpb index 4ee03831..44466d04 100644 --- a/src/formats/_commodore1541.textpb +++ b/src/formats/_commodore1541.textpb @@ -15,14 +15,12 @@ layout { sides: 1 layoutdata { sector_size: 256 - physical { - start_sector: 0 - } } layoutdata { track: 0 up_to_track: 16 physical { + start_sector: 0 count: 21 } } @@ -30,6 +28,7 @@ layout { track: 17 up_to_track: 23 physical { + start_sector: 0 count: 19 } } @@ -37,6 +36,7 @@ layout { track: 24 up_to_track: 29 physical { + start_sector: 0 count: 18 } } @@ -44,6 +44,7 @@ layout { track: 30 up_to_track: 39 physical { + start_sector: 0 count: 17 } } diff --git a/src/formats/commodore1581.textpb b/src/formats/commodore1581.textpb index 02b4aea8..11186e6d 100644 --- a/src/formats/commodore1581.textpb +++ b/src/formats/commodore1581.textpb @@ -13,6 +13,7 @@ image_writer { layout { tracks: 80 sides: 2 + swap_sides: true layoutdata { sector_size: 512 physical { @@ -25,8 +26,6 @@ layout { encoder { ibm { trackdata { - swap_sides: true - invert_side_byte: true target_rotational_period_ms: 200 target_clock_period_us: 4 emit_iam: false @@ -41,7 +40,6 @@ decoder { ibm { trackdata { ignore_side_byte: true - invert_side_byte: true } } } diff --git a/src/gui/customstatusbar.cc b/src/gui/customstatusbar.cc index bb200f76..3b229efa 100644 --- a/src/gui/customstatusbar.cc +++ b/src/gui/customstatusbar.cc @@ -20,7 +20,7 @@ CustomStatusBar::CustomStatusBar(wxWindow* parent, wxWindowID id): static const int widths[] = {-1, 200, 100, 20}; SetStatusWidths(4, widths); - static const int styles[] = { wxSB_FLAT, wxSB_FLAT, wxSB_FLAT, wxSB_FLAT }; + static const int styles[] = {wxSB_FLAT, wxSB_FLAT, wxSB_FLAT, wxSB_FLAT}; SetStatusStyles(4, styles); _progressBar.reset(new wxGauge(this, @@ -99,7 +99,7 @@ void CustomStatusBar::SetProgress(int amount) void CustomStatusBar::SetLeftLabel(const std::string& text) { - SetStatusText(text, 0); + SetStatusText(text, 0); } void CustomStatusBar::SetRightLabel(const std::string& text) diff --git a/src/gui/fluxviewercontrol.cc b/src/gui/fluxviewercontrol.cc index 7374e993..fccfa8e4 100644 --- a/src/gui/fluxviewercontrol.cc +++ b/src/gui/fluxviewercontrol.cc @@ -25,456 +25,489 @@ FluxViewerControl::FluxViewerControl(wxWindow* parent, const wxPoint& pos, const wxSize& size, long style): - wxWindow(parent, id, pos, size, - style | wxFULL_REPAINT_ON_RESIZE, - "FluxViewerControl") + wxWindow(parent, + id, + pos, + size, + style | wxFULL_REPAINT_ON_RESIZE, + "FluxViewerControl") { - SetDoubleBuffered(true); + SetDoubleBuffered(true); } -wxBEGIN_EVENT_TABLE(FluxViewerControl, wxPanel) - EVT_PAINT(FluxViewerControl::OnPaint) - EVT_MOUSEWHEEL(FluxViewerControl::OnMouseWheel) - EVT_LEFT_DOWN(FluxViewerControl::OnMouseMotion) - EVT_LEFT_UP(FluxViewerControl::OnMouseMotion) - EVT_MOTION(FluxViewerControl::OnMouseMotion) - EVT_CONTEXT_MENU(FluxViewerControl::OnContextMenu) -wxEND_EVENT_TABLE() +wxBEGIN_EVENT_TABLE(FluxViewerControl, wxPanel) EVT_PAINT( + FluxViewerControl::OnPaint) EVT_MOUSEWHEEL(FluxViewerControl::OnMouseWheel) + EVT_LEFT_DOWN(FluxViewerControl::OnMouseMotion) + EVT_LEFT_UP(FluxViewerControl::OnMouseMotion) + EVT_MOTION(FluxViewerControl::OnMouseMotion) EVT_CONTEXT_MENU( + FluxViewerControl::OnContextMenu) wxEND_EVENT_TABLE() -void FluxViewerControl::SetScrollbar(wxScrollBar* scrollbar) + void FluxViewerControl::SetScrollbar(wxScrollBar* scrollbar) { - _scrollbar = scrollbar; - _scrollbar->Bind(wxEVT_SCROLL_THUMBTRACK, &FluxViewerControl::OnScrollbarChanged, this); - _scrollbar->Bind(wxEVT_SCROLL_CHANGED, &FluxViewerControl::OnScrollbarChanged, this); + _scrollbar = scrollbar; + _scrollbar->Bind( + wxEVT_SCROLL_THUMBTRACK, &FluxViewerControl::OnScrollbarChanged, this); + _scrollbar->Bind( + wxEVT_SCROLL_CHANGED, &FluxViewerControl::OnScrollbarChanged, this); } - + void FluxViewerControl::SetFlux(std::shared_ptr flux) { - _flux = flux; + _flux = flux; - _scrollPosition = 0; - _totalDuration = 0; - for (const auto& trackdata : _flux->trackDatas) - _totalDuration += trackdata->fluxmap->duration(); + _scrollPosition = 0; + _totalDuration = 0; + for (const auto& trackdata : _flux->trackDatas) + _totalDuration += trackdata->fluxmap->duration(); - auto size = GetSize(); - _nanosecondsPerPixel = (double)_totalDuration / (double)size.GetWidth(); + auto size = GetSize(); + _nanosecondsPerPixel = (double)_totalDuration / (double)size.GetWidth(); - UpdateScale(); - Refresh(); + UpdateScale(); + Refresh(); } void FluxViewerControl::UpdateScale() { - auto size = GetSize(); - nanoseconds_t thumbSize = size.GetWidth() * _nanosecondsPerPixel; - _scrollbar->SetScrollbar(_scrollPosition/1000, thumbSize/1000, _totalDuration/1000, thumbSize/2000); + auto size = GetSize(); + nanoseconds_t thumbSize = size.GetWidth() * _nanosecondsPerPixel; + _scrollbar->SetScrollbar(_scrollPosition / 1000, + thumbSize / 1000, + _totalDuration / 1000, + thumbSize / 2000); - int totalPixels = (_totalDuration / _nanosecondsPerPixel) + 1; - if ((totalPixels != _densityMap.size()) && (_nanosecondsPerPixel > RENDER_LIMIT)) - { - _densityMap.resize(totalPixels); - std::fill(_densityMap.begin(), _densityMap.end(), 0.0); + int totalPixels = (_totalDuration / _nanosecondsPerPixel) + 1; + if ((totalPixels != _densityMap.size()) && + (_nanosecondsPerPixel > RENDER_LIMIT)) + { + _densityMap.resize(totalPixels); + std::fill(_densityMap.begin(), _densityMap.end(), 0.0); - int i = 0; - for (const auto& trackdata : _flux->trackDatas) - { - FluxmapReader fmr(*trackdata->fluxmap); - while (!fmr.eof()) - { - unsigned ticks; - if (!fmr.findEvent(F_BIT_PULSE, ticks)) - break; + int i = 0; + for (const auto& trackdata : _flux->trackDatas) + { + FluxmapReader fmr(*trackdata->fluxmap); + while (!fmr.eof()) + { + unsigned ticks; + if (!fmr.findEvent(F_BIT_PULSE, ticks)) + break; - int fx = fmr.tell().ns() / _nanosecondsPerPixel; - _densityMap.at(i + fx)++; - } - i += trackdata->fluxmap->duration() / _nanosecondsPerPixel; - } + int fx = fmr.tell().ns() / _nanosecondsPerPixel; + _densityMap.at(i + fx)++; + } + i += trackdata->fluxmap->duration() / _nanosecondsPerPixel; + } - double max = *std::max_element(_densityMap.begin(), _densityMap.end()); - for (auto& d : _densityMap) - d /= max; - } + double max = *std::max_element(_densityMap.begin(), _densityMap.end()); + for (auto& d : _densityMap) + d /= max; + } } static int interpolate(int lo, int hi, float factor) { - float range = hi - lo; - return lo + range*factor; + float range = hi - lo; + return lo + range * factor; } void FluxViewerControl::OnPaint(wxPaintEvent&) { wxPaintDC dc(this); - dc.SetBackground(BACKGROUND_BRUSH); - dc.Clear(); + dc.SetBackground(BACKGROUND_BRUSH); + dc.Clear(); - auto size = GetSize(); - int w = size.GetWidth(); - int h = size.GetHeight(); - int th = h / 4; - int ch = th * 2 / 3; - int ch2 = ch / 2; - int t1y = th/2; - int t2y = th + th/2; - int t3y = th*2 + th/2; - int t4y = th*3 + th/2; + auto size = GetSize(); + int w = size.GetWidth(); + int h = size.GetHeight(); + int th = h / 4; + int ch = th * 2 / 3; + int ch2 = ch / 2; + int t1y = th / 2; + int t2y = th + th / 2; + int t3y = th * 2 + th / 2; + int t4y = th * 3 + th / 2; - int x = -_scrollPosition / _nanosecondsPerPixel; - nanoseconds_t fluxStartTime = 0; - for (const auto& trackdata : _flux->trackDatas) - { - nanoseconds_t duration = trackdata->fluxmap->duration(); - int fw = duration / _nanosecondsPerPixel; + int x = -_scrollPosition / _nanosecondsPerPixel; + nanoseconds_t fluxStartTime = 0; + for (const auto& trackdata : _flux->trackDatas) + { + nanoseconds_t duration = trackdata->fluxmap->duration(); + int fw = duration / _nanosecondsPerPixel; - if (((x+fw) > 0) && (x < w)) - { - if (fluxStartTime != 0) - { - dc.SetPen(READ_SEPARATOR_PEN); - dc.DrawLine({x, 0}, {x, h}); - } + if (((x + fw) > 0) && (x < w)) + { + if (fluxStartTime != 0) + { + dc.SetPen(READ_SEPARATOR_PEN); + dc.DrawLine({x, 0}, {x, h}); + } - dc.SetPen(FOREGROUND_PEN); - dc.DrawLine({x, t1y}, {x+fw, t1y}); - dc.DrawLine({x, t2y}, {x+fw, t2y}); - dc.DrawLine({x, t3y}, {x+fw, t3y}); + dc.SetPen(FOREGROUND_PEN); + dc.DrawLine({x, t1y}, {x + fw, t1y}); + dc.DrawLine({x, t2y}, {x + fw, t2y}); + dc.DrawLine({x, t3y}, {x + fw, t3y}); - /* Index lines. */ + /* Index lines. */ - { - dc.SetPen(INDEX_SEPARATOR_PEN); - FluxmapReader fmr(*trackdata->fluxmap); - for (;;) - { - unsigned ticks; - if (!fmr.findEvent(F_BIT_INDEX, ticks)) - break; + { + dc.SetPen(INDEX_SEPARATOR_PEN); + FluxmapReader fmr(*trackdata->fluxmap); + for (;;) + { + unsigned ticks; + if (!fmr.findEvent(F_BIT_INDEX, ticks)) + break; - int fx = fmr.tell().ns() / _nanosecondsPerPixel; - if (((x+fx) > 0) && ((x+fx) < w)) - dc.DrawLine({x+fx, 0}, {x+fx, h}); + int fx = fmr.tell().ns() / _nanosecondsPerPixel; + if (((x + fx) > 0) && ((x + fx) < w)) + dc.DrawLine({x + fx, 0}, {x + fx, h}); - if ((x+fx) >= w) - break; - } - } + if ((x + fx) >= w) + break; + } + } - /* Draw the horizontal scale. */ + /* Draw the horizontal scale. */ - uint64_t tickStep = 1000; - while ((tickStep / _nanosecondsPerPixel) < MINIMUM_TICK_DISTANCE) - tickStep *= 10; + uint64_t tickStep = 1000; + while ((tickStep / _nanosecondsPerPixel) < MINIMUM_TICK_DISTANCE) + tickStep *= 10; - static wxFont font(6, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); - dc.SetFont(font); - dc.SetBackgroundMode(wxTRANSPARENT); - dc.SetTextForeground(*wxBLACK); - dc.SetPen(FOREGROUND_PEN); + static wxFont font( + 6, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); + dc.SetFont(font); + dc.SetBackgroundMode(wxTRANSPARENT); + dc.SetTextForeground(*wxBLACK); + dc.SetPen(FOREGROUND_PEN); - uint64_t tick = 0; - if (x < 0) - tick = floor(-x * _nanosecondsPerPixel / tickStep) * tickStep; - while (tick < duration) - { - int xx = tick / _nanosecondsPerPixel; - if ((x+xx) > w) - break; - int ts = ch2/3; - if ((tick % (10*tickStep)) == 0) - ts = ch2/2; - if ((tick % (100*tickStep)) == 0) - ts = ch2; - dc.DrawLine({x+xx, t3y - ts}, {x+xx, t3y + ts}); - if ((tick % (10*tickStep)) == 0) - { - dc.DrawText( - fmt::format("{:.3f}ms", tick / 1e6), - { x+xx, t3y - ch2 } - ); - } + uint64_t tick = 0; + if (x < 0) + tick = floor(-x * _nanosecondsPerPixel / tickStep) * tickStep; + while (tick < duration) + { + int xx = tick / _nanosecondsPerPixel; + if ((x + xx) > w) + break; + int ts = ch2 / 3; + if ((tick % (10 * tickStep)) == 0) + ts = ch2 / 2; + if ((tick % (100 * tickStep)) == 0) + ts = ch2; + dc.DrawLine({x + xx, t3y - ts}, {x + xx, t3y + ts}); + if ((tick % (10 * tickStep)) == 0) + { + dc.DrawText(fmt::format("{:.3f}ms", tick / 1e6), + {x + xx, t3y - ch2}); + } - tick += tickStep; - } + tick += tickStep; + } - double relativeScrollPosition = _scrollPosition - fluxStartTime; - if (x <= 0) - dc.DrawText( - fmt::format("{:.3f}ms", relativeScrollPosition / 1e6), - { BORDER, t3y + ch2/2 } - ); + double relativeScrollPosition = _scrollPosition - fluxStartTime; + if (x <= 0) + dc.DrawText( + fmt::format("{:.3f}ms", relativeScrollPosition / 1e6), + {BORDER, t3y + ch2 / 2}); - if ((x+fw) >= w) - { - wxString text = fmt::format( - "{:.3f}ms", (relativeScrollPosition + (w * _nanosecondsPerPixel)) / 1e6); - auto size = dc.GetTextExtent(text); - dc.DrawText(text, { w - size.GetWidth() - BORDER, t3y + ch2/2 }); - } + if ((x + fw) >= w) + { + wxString text = fmt::format("{:.3f}ms", + (relativeScrollPosition + (w * _nanosecondsPerPixel)) / + 1e6); + auto size = dc.GetTextExtent(text); + dc.DrawText( + text, {w - size.GetWidth() - BORDER, t3y + ch2 / 2}); + } - /* Sector blocks. */ + /* Sector blocks. */ - dc.SetBackgroundMode(wxTRANSPARENT); - dc.SetTextForeground(*wxBLACK); - for (const auto& sector : trackdata->sectors) - { - nanoseconds_t sr = sector->dataEndTime; - if (!sr) - sr = sector->headerEndTime; + dc.SetBackgroundMode(wxTRANSPARENT); + dc.SetTextForeground(*wxBLACK); + for (const auto& sector : trackdata->sectors) + { + nanoseconds_t sr = sector->dataEndTime; + if (!sr) + sr = sector->headerEndTime; - int sp = sector->headerStartTime / _nanosecondsPerPixel; - int sw = (sr - sector->headerStartTime) / _nanosecondsPerPixel; + int sp = sector->headerStartTime / _nanosecondsPerPixel; + int sw = (sr - sector->headerStartTime) / _nanosecondsPerPixel; - wxRect rect = {x+sp, t1y - ch2, sw, ch}; - bool hovered = rect.Contains(_mouseX, _mouseY); - wxPen pen(FOREGROUND_COLOUR, hovered ? 2 : 1); - dc.SetPen(pen); + wxRect rect = {x + sp, t1y - ch2, sw, ch}; + bool hovered = rect.Contains(_mouseX, _mouseY); + wxPen pen(FOREGROUND_COLOUR, hovered ? 2 : 1); + dc.SetPen(pen); - dc.SetBrush((sector->status == Sector::OK) ? SECTOR_BRUSH : BAD_SECTOR_BRUSH); + dc.SetBrush((sector->status == Sector::OK) ? SECTOR_BRUSH + : BAD_SECTOR_BRUSH); - dc.DrawRectangle(rect); - wxDCClipper clipper(dc, rect); + dc.DrawRectangle(rect); + wxDCClipper clipper(dc, rect); - auto text = fmt::format("c{}.h{}.s{} {}", - sector->logicalTrack, sector->logicalSide, sector->logicalSector, - Sector::statusToString(sector->status)); - auto size = dc.GetTextExtent(text); - dc.DrawText(text, { x+sp+BORDER, t1y - size.GetHeight()/2 }); + auto text = fmt::format("c{}.h{}.s{} {}", + sector->logicalTrack, + sector->logicalSide, + sector->logicalSector, + Sector::statusToString(sector->status)); + auto size = dc.GetTextExtent(text); + dc.DrawText( + text, {x + sp + BORDER, t1y - size.GetHeight() / 2}); - if (_rightClicked && hovered) - ShowSectorMenu(sector); - } + if (_rightClicked && hovered) + ShowSectorMenu(sector); + } - /* Record blocks. */ + /* Record blocks. */ - dc.SetPen(FOREGROUND_PEN); - dc.SetBrush(RECORD_BRUSH); - for (const auto& record : trackdata->records) - { - int rp = record->startTime / _nanosecondsPerPixel; - int rw = (record->endTime - record->startTime) / _nanosecondsPerPixel; + dc.SetPen(FOREGROUND_PEN); + dc.SetBrush(RECORD_BRUSH); + for (const auto& record : trackdata->records) + { + int rp = record->startTime / _nanosecondsPerPixel; + int rw = (record->endTime - record->startTime) / + _nanosecondsPerPixel; - wxRect rect = {x+rp, t2y - ch2, rw, ch}; - bool hovered = rect.Contains(_mouseX, _mouseY); - wxPen pen(FOREGROUND_COLOUR, hovered ? 2 : 1); - dc.SetPen(pen); + wxRect rect = {x + rp, t2y - ch2, rw, ch}; + bool hovered = rect.Contains(_mouseX, _mouseY); + wxPen pen(FOREGROUND_COLOUR, hovered ? 2 : 1); + dc.SetPen(pen); - dc.DrawRectangle(rect); - wxDCClipper clipper(dc, rect); + dc.DrawRectangle(rect); + wxDCClipper clipper(dc, rect); - auto text = fmt::format("+{:.3f}ms", record->startTime / 1e6); - auto size = dc.GetTextExtent(text); - dc.DrawText(text, { x+rp+BORDER, t2y - size.GetHeight()/2 }); + auto text = fmt::format("+{:.3f}ms", record->startTime / 1e6); + auto size = dc.GetTextExtent(text); + dc.DrawText( + text, {x + rp + BORDER, t2y - size.GetHeight() / 2}); - if (_rightClicked && hovered) - ShowRecordMenu(trackdata->location, record); - } + if (_rightClicked && hovered) + ShowRecordMenu(trackdata->location, record); + } - /* Flux chart. */ + /* Flux chart. */ - dc.SetPen(FLUX_PEN); - if (_nanosecondsPerPixel > RENDER_LIMIT) - { - /* Draw using density map. */ + dc.SetPen(FLUX_PEN); + if (_nanosecondsPerPixel > RENDER_LIMIT) + { + /* Draw using density map. */ - dc.SetPen(*wxTRANSPARENT_PEN); - for (int fx = 0; fx < fw; fx++) - { - if (((x+fx) > 0) && ((x+fx) < w)) - { - float density = _densityMap[(fluxStartTime/_nanosecondsPerPixel) + fx]; - wxColour colour( - interpolate(BACKGROUND_COLOUR.Red(), FLUX_COLOUR.Red(), density), - interpolate(BACKGROUND_COLOUR.Green(), FLUX_COLOUR.Green(), density), - interpolate(BACKGROUND_COLOUR.Blue(), FLUX_COLOUR.Blue(), density)); - wxBrush brush(colour); - dc.SetBrush(brush); - dc.DrawRectangle({x+fx, t4y - ch2}, {1, ch}); - } - } - } - else - { - /* Draw discrete pulses. */ + dc.SetPen(*wxTRANSPARENT_PEN); + for (int fx = 0; fx < fw; fx++) + { + if (((x + fx) > 0) && ((x + fx) < w)) + { + float density = + _densityMap[(fluxStartTime / _nanosecondsPerPixel) + + fx]; + wxColour colour(interpolate(BACKGROUND_COLOUR.Red(), + FLUX_COLOUR.Red(), + density), + interpolate(BACKGROUND_COLOUR.Green(), + FLUX_COLOUR.Green(), + density), + interpolate(BACKGROUND_COLOUR.Blue(), + FLUX_COLOUR.Blue(), + density)); + wxBrush brush(colour); + dc.SetBrush(brush); + dc.DrawRectangle({x + fx, t4y - ch2}, {1, ch}); + } + } + } + else + { + /* Draw discrete pulses. */ - FluxmapReader fmr(*trackdata->fluxmap); - while (!fmr.eof()) - { - unsigned ticks; - if (!fmr.findEvent(F_BIT_PULSE, ticks)) - break; + FluxmapReader fmr(*trackdata->fluxmap); + while (!fmr.eof()) + { + unsigned ticks; + if (!fmr.findEvent(F_BIT_PULSE, ticks)) + break; - int fx = fmr.tell().ns() / _nanosecondsPerPixel; - if (((x+fx) > 0) && ((x+fx) < w)) - dc.DrawLine({x+fx, t4y - ch2}, {x+fx, t4y + ch2}); - if ((x+fx) >= w) - break; - } - } + int fx = fmr.tell().ns() / _nanosecondsPerPixel; + if (((x + fx) > 0) && ((x + fx) < w)) + dc.DrawLine({x + fx, t4y - ch2}, {x + fx, t4y + ch2}); + if ((x + fx) >= w) + break; + } + } - dc.SetPen(FLUX_PEN); - dc.DrawLine({x, t4y}, {x+fw, t4y}); - } + dc.SetPen(FLUX_PEN); + dc.DrawLine({x, t4y}, {x + fw, t4y}); + } - x += fw; - fluxStartTime += duration; - } + x += fw; + fluxStartTime += duration; + } - _rightClicked = false; + _rightClicked = false; } void FluxViewerControl::OnMouseWheel(wxMouseEvent& event) { - int x = event.GetX(); - - _scrollPosition += x * _nanosecondsPerPixel; - if (event.GetWheelRotation() > 0) - _nanosecondsPerPixel /= 1.2; - else - _nanosecondsPerPixel *= 1.2; - _nanosecondsPerPixel = std::max(30.0, _nanosecondsPerPixel); - _scrollPosition -= x * _nanosecondsPerPixel; + int x = event.GetX(); - UpdateScale(); - Refresh(); + _scrollPosition += x * _nanosecondsPerPixel; + if (event.GetWheelRotation() > 0) + _nanosecondsPerPixel /= 1.2; + else + _nanosecondsPerPixel *= 1.2; + _nanosecondsPerPixel = std::max(30.0, _nanosecondsPerPixel); + _scrollPosition -= x * _nanosecondsPerPixel; + + UpdateScale(); + Refresh(); } void FluxViewerControl::OnScrollbarChanged(wxScrollEvent& event) { - _scrollPosition = event.GetPosition() * 1000LL; - Refresh(); + _scrollPosition = event.GetPosition() * 1000LL; + Refresh(); } void FluxViewerControl::OnMouseMotion(wxMouseEvent& event) { - event.Skip(); + event.Skip(); - if (event.Leaving()) - _mouseX = _mouseY = -1; - else - { - _mouseX = event.GetX(); - _mouseY = event.GetY(); - } + if (event.Leaving()) + _mouseX = _mouseY = -1; + else + { + _mouseX = event.GetX(); + _mouseY = event.GetY(); + } - if (event.ButtonDown(wxMOUSE_BTN_LEFT)) - { - _dragStartX = event.GetX(); - _dragStartPosition = _scrollPosition; - } - else if (event.ButtonUp(wxMOUSE_BTN_LEFT)) - { - _dragStartX = -1; - _dragStartPosition = -1; - } - else if (event.Dragging() && event.LeftIsDown() && (_dragStartX != -1)) - { - int dx = _dragStartX - event.GetX(); - nanoseconds_t dt = dx * _nanosecondsPerPixel; - _scrollPosition = _dragStartPosition + dt; - UpdateScale(); - } + if (event.ButtonDown(wxMOUSE_BTN_LEFT)) + { + _dragStartX = event.GetX(); + _dragStartPosition = _scrollPosition; + } + else if (event.ButtonUp(wxMOUSE_BTN_LEFT)) + { + _dragStartX = -1; + _dragStartPosition = -1; + } + else if (event.Dragging() && event.LeftIsDown() && (_dragStartX != -1)) + { + int dx = _dragStartX - event.GetX(); + nanoseconds_t dt = dx * _nanosecondsPerPixel; + _scrollPosition = _dragStartPosition + dt; + UpdateScale(); + } - Refresh(); + Refresh(); } void FluxViewerControl::OnContextMenu(wxContextMenuEvent& event) { - _rightClicked = true; - Refresh(); + _rightClicked = true; + Refresh(); } void FluxViewerControl::ShowSectorMenu(std::shared_ptr sector) { - wxMenu menu; + wxMenu menu; - menu.Bind(wxEVT_MENU, - [&] (wxCommandEvent&) { - DisplayDecodedData(sector); - }, - menu.Append(wxID_ANY, "Show decoded data")->GetId() - ); + menu.Bind( + wxEVT_MENU, + [&](wxCommandEvent&) + { + DisplayDecodedData(sector); + }, + menu.Append(wxID_ANY, "Show decoded data")->GetId()); - menu.Bind(wxEVT_MENU, - [&] (wxCommandEvent&) { - DisplayRawData(sector); - }, - menu.Append(wxID_ANY, "Show raw data")->GetId() - ); + menu.Bind( + wxEVT_MENU, + [&](wxCommandEvent&) + { + DisplayRawData(sector); + }, + menu.Append(wxID_ANY, "Show raw data")->GetId()); - _rightClicked = false; - PopupMenu(&menu, _mouseX, _mouseY); + _rightClicked = false; + PopupMenu(&menu, _mouseX, _mouseY); } -void FluxViewerControl::ShowRecordMenu(const Location& location, std::shared_ptr record) +void FluxViewerControl::ShowRecordMenu( + const Location& location, std::shared_ptr record) { - wxMenu menu; + wxMenu menu; - menu.Bind(wxEVT_COMMAND_MENU_SELECTED, - [&] (wxCommandEvent&) { - DisplayRawData(location, record); - }, - menu.Append(wxID_ANY, "Show record data")->GetId() - ); + menu.Bind( + wxEVT_COMMAND_MENU_SELECTED, + [&](wxCommandEvent&) + { + DisplayRawData(location, record); + }, + menu.Append(wxID_ANY, "Show record data")->GetId()); - _rightClicked = false; - PopupMenu(&menu, _mouseX, _mouseY); + _rightClicked = false; + PopupMenu(&menu, _mouseX, _mouseY); } -static void dumpSectorMetadata(std::ostream& s, std::shared_ptr sector) +static void dumpSectorMetadata( + std::ostream& s, std::shared_ptr sector) { - s << fmt::format("Sector status: {}\n", - Sector::statusToString(sector->status)) - << fmt::format("Physical location: c{}.h{}\n", - sector->physicalTrack, sector->physicalHead) - << fmt::format("Clock: {:.2f}us / {:.0f}kHz\n", - sector->clock / 1000.0, - 1000000.0 / sector->clock); + s << fmt::format( + "Sector status: {}\n", Sector::statusToString(sector->status)) + << fmt::format("Physical location: c{}.h{}\n", + sector->physicalTrack, + sector->physicalSide) + << fmt::format("Clock: {:.2f}us / {:.0f}kHz\n", + sector->clock / 1000.0, + 1000000.0 / sector->clock); } void FluxViewerControl::DisplayDecodedData(std::shared_ptr sector) { - std::stringstream s; + std::stringstream s; - auto title = fmt::format("User data for c{}.h{}.s{}", - sector->logicalTrack, sector->logicalSide, sector->logicalSector); - s << title << '\n'; - dumpSectorMetadata(s, sector); - s << '\n'; + auto title = fmt::format("User data for c{}.h{}.s{}", + sector->logicalTrack, + sector->logicalSide, + sector->logicalSector); + s << title << '\n'; + dumpSectorMetadata(s, sector); + s << '\n'; - hexdump(s, sector->data); + hexdump(s, sector->data); - TextViewerWindow::Create(this, title, s.str())->Show(); + TextViewerWindow::Create(this, title, s.str())->Show(); } void FluxViewerControl::DisplayRawData(std::shared_ptr sector) { - std::stringstream s; + std::stringstream s; - auto title = fmt::format("Raw data for c{}.h{}.s{}", - sector->logicalTrack, sector->logicalSide, sector->logicalSector); - s << title << '\n'; - dumpSectorMetadata(s, sector); - s << fmt::format("Number of records: {}\n", sector->records.size()); + auto title = fmt::format("Raw data for c{}.h{}.s{}", + sector->logicalTrack, + sector->logicalSide, + sector->logicalSector); + s << title << '\n'; + dumpSectorMetadata(s, sector); + s << fmt::format("Number of records: {}\n", sector->records.size()); - for (auto& record : sector->records) - { - s << '\n'; - hexdump(s, record->rawData); - } + for (auto& record : sector->records) + { + s << '\n'; + hexdump(s, record->rawData); + } - TextViewerWindow::Create(this, title, s.str())->Show(); + TextViewerWindow::Create(this, title, s.str())->Show(); } -void FluxViewerControl::DisplayRawData(const Location& location, std::shared_ptr record) +void FluxViewerControl::DisplayRawData( + const Location& location, std::shared_ptr record) { - std::stringstream s; + std::stringstream s; - auto title = fmt::format("Raw data for record c{}.h{} + {:.3f}ms", - location.physicalTrack, location.head, record->startTime / 1e6); - s << title << "\n\n"; - hexdump(s, record->rawData); + auto title = fmt::format("Raw data for record c{}.h{} + {:.3f}ms", + location.physicalTrack, + location.physicalSide, + record->startTime / 1e6); + s << title << "\n\n"; + hexdump(s, record->rawData); - TextViewerWindow::Create(this, title, s.str())->Show(); + TextViewerWindow::Create(this, title, s.str())->Show(); } diff --git a/src/gui/fluxviewerwindow.cc b/src/gui/fluxviewerwindow.cc index f9e9ce6b..82bb3dc4 100644 --- a/src/gui/fluxviewerwindow.cc +++ b/src/gui/fluxviewerwindow.cc @@ -6,20 +6,19 @@ #include "lib/flux.h" #include "fmt/format.h" -FluxViewerWindow::FluxViewerWindow(wxWindow* parent, std::shared_ptr flux): - FluxViewerWindowGen(parent), - _flux(flux) +FluxViewerWindow::FluxViewerWindow( + wxWindow* parent, std::shared_ptr flux): + FluxViewerWindowGen(parent), + _flux(flux) { - fluxviewer->SetScrollbar(scrollbar); - fluxviewer->SetFlux(flux); - SetTitle( - fmt::format("Flux for c{} h{}", - flux->location.physicalTrack, flux->location.head)); + fluxviewer->SetScrollbar(scrollbar); + fluxviewer->SetFlux(flux); + SetTitle(fmt::format("Flux for c{} h{}", + flux->location.physicalTrack, + flux->location.physicalSide)); } void FluxViewerWindow::OnExit(wxCommandEvent& event) { Close(true); } - - diff --git a/src/gui/main.cc b/src/gui/main.cc index 38ff5279..3a66dead 100644 --- a/src/gui/main.cc +++ b/src/gui/main.cc @@ -30,15 +30,15 @@ public: return new ExecEvent(*this); } - void SetCallback(const std::function callback) - { - _callback = callback; - } + void SetCallback(const std::function callback) + { + _callback = callback; + } - void RunCallback() const - { - _callback(); - } + void RunCallback() const + { + _callback(); + } private: std::function _callback; @@ -46,8 +46,8 @@ private: bool FluxEngineApp::OnInit() { - wxImage::AddHandler(new wxPNGHandler()); - Bind(EXEC_EVENT_TYPE, &FluxEngineApp::OnExec, this); + wxImage::AddHandler(new wxPNGHandler()); + Bind(EXEC_EVENT_TYPE, &FluxEngineApp::OnExec, this); _mainWindow = CreateMainWindow(); _mainWindow->Show(true); return true; @@ -55,74 +55,74 @@ bool FluxEngineApp::OnInit() wxThread::ExitCode FluxEngineApp::Entry() { - try - { - if (_callback) - _callback(); - } - catch (const ErrorException& e) - { - Logger() << ErrorLogMessage { e.message+'\n' }; - } - catch (const EmergencyStopException& e) - { - Logger() << EmergencyStopMessage(); - } + try + { + if (_callback) + _callback(); + } + catch (const ErrorException& e) + { + Logger() << ErrorLogMessage{e.message + '\n'}; + } + catch (const EmergencyStopException& e) + { + Logger() << EmergencyStopMessage(); + } - runOnUiThread( - [&] { - _callback = nullptr; - SendUpdateEvent(); - } - ); - return 0; + runOnUiThread( + [&] + { + _callback = nullptr; + SendUpdateEvent(); + }); + return 0; } void FluxEngineApp::RunOnWorkerThread(std::function callback) { - if (_callback) - std::cerr << "Cannot start new worker task as one is already running\n"; - _callback = callback; + if (_callback) + std::cerr << "Cannot start new worker task as one is already running\n"; + _callback = callback; - if (GetThread()) - GetThread()->Wait(); + if (GetThread()) + GetThread()->Wait(); - emergencyStop = false; - CreateThread(wxTHREAD_JOINABLE); - GetThread()->Run(); + emergencyStop = false; + CreateThread(wxTHREAD_JOINABLE); + GetThread()->Run(); - SendUpdateEvent(); + SendUpdateEvent(); } void FluxEngineApp::SendUpdateEvent() { - auto* event = new wxCommandEvent(UPDATE_STATE_EVENT, 0); - event->SetEventObject(_mainWindow); - QueueEvent(event); + auto* event = new wxCommandEvent(UPDATE_STATE_EVENT, 0); + event->SetEventObject(_mainWindow); + QueueEvent(event); } void runOnWorkerThread(std::function callback) { - wxGetApp().RunOnWorkerThread(callback); + wxGetApp().RunOnWorkerThread(callback); } bool FluxEngineApp::IsWorkerThreadRunning() const { - return !!_callback; + return !!_callback; } void FluxEngineApp::OnExec(const ExecEvent& event) { - event.RunCallback(); - execSemaphore.Post(); + event.RunCallback(); + execSemaphore.Post(); } void runOnUiThread(std::function callback) { - ExecEvent* event = new ExecEvent(); - event->SetCallback(callback); - wxGetApp().QueueEvent(event); - execSemaphore.Wait(); + ExecEvent* event = new ExecEvent(); + event->SetCallback(callback); + wxGetApp().QueueEvent(event); + execSemaphore.Wait(); } wxIMPLEMENT_APP(FluxEngineApp); diff --git a/src/gui/visualisationcontrol.cc b/src/gui/visualisationcontrol.cc index 32ce2825..156fbd16 100644 --- a/src/gui/visualisationcontrol.cc +++ b/src/gui/visualisationcontrol.cc @@ -195,7 +195,7 @@ void VisualisationControl::OnPaint(wxPaintEvent&) if (it != _tracks.end()) logicalText = fmt::format("logical: {}.{}", it->second->location.logicalTrack, - it->second->location.head); + it->second->location.logicalSide); centreText(logicalText, h - 35); } @@ -271,7 +271,7 @@ void VisualisationControl::Clear() void VisualisationControl::SetTrackData(std::shared_ptr track) { - key_t key = {track->location.physicalTrack, track->location.head}; + key_t key = {track->location.physicalTrack, track->location.physicalSide}; _tracks[key] = track; _sectors.erase(key); for (auto& sector : track->sectors) @@ -285,13 +285,14 @@ void VisualisationControl::SetDiskData(std::shared_ptr disk) _sectors.clear(); for (const auto& track : disk->tracks) { - key_t key = {track->location.physicalTrack, track->location.head}; + key_t key = { + track->location.physicalTrack, track->location.physicalSide}; _tracks[key] = track; } for (const auto& sector : *(disk->image)) { - key_t key = {sector->physicalTrack, sector->physicalHead}; + key_t key = {sector->physicalTrack, sector->physicalSide}; _sectors.insert({key, sector}); }