From 18af881fe533975b06ba6100e2d03eca32b93544 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 4 Jan 2022 23:49:39 +0100 Subject: [PATCH] Attach the underlying raw records to Sector structures; add a .raw exporter for getting the MFM/FM/GCR stream. --- doc/using.md | 22 +++++++--- lib/decoders/decoders.cc | 1 + lib/imagewriter/imagewriter.cc | 6 ++- lib/imagewriter/imagewriter.h | 16 +++---- lib/imagewriter/imagewriter.proto | 2 + lib/imagewriter/rawimagewriter.cc | 73 +++++++++++++++++++++++++++++++ lib/sector.h | 3 ++ mkninja.sh | 1 + 8 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 lib/imagewriter/rawimagewriter.cc diff --git a/doc/using.md b/doc/using.md index 5cecf464..6086c71e 100644 --- a/doc/using.md +++ b/doc/using.md @@ -282,14 +282,22 @@ FluxEngine also supports a number of file system image formats. When using the - `` - Write to a [LDBS generic image - file](https://www.seasip.info/Unix/LibDsk/ldbs.html). **Write only.** - - - `` + Write to a [LDBS generic image + file](https://www.seasip.info/Unix/LibDsk/ldbs.html). **Write only.** - Write to a [D64 image - file](http://unusedino.de/ec64/technical/formats/d64.html), commonly used - by Commodore 64 emulators. **Write only.** + - `` + + Write to a [D64 image + file](http://unusedino.de/ec64/technical/formats/d64.html), commonly used by + Commodore 64 emulators. **Write only.** + + - `` + + Write undecoded data to a raw binary file. **Write only.** This gives you the + underlying MFM, FM or GCR stream, without actually doing the decode into + user-visible bytes. However, the decode is still done in order to check for + correctness. Individual records are separated by three `\\0` bytes and tracks + are seperated by four `\\0` bytes; tracks are emitted in CHS order. ### High density disks diff --git a/lib/decoders/decoders.cc b/lib/decoders/decoders.cc index 0dee46e4..c206c1f9 100644 --- a/lib/decoders/decoders.cc +++ b/lib/decoders/decoders.cc @@ -132,6 +132,7 @@ void AbstractDecoder::pushRecord(const Fluxmap::Position& start, const Fluxmap:: auto record = std::make_shared(); _trackdata->records.push_back(record); + _sector->records.push_back(record); record->startTime = start.ns(); record->endTime = end.ns(); diff --git a/lib/imagewriter/imagewriter.cc b/lib/imagewriter/imagewriter.cc index e8535acf..1a23ba73 100644 --- a/lib/imagewriter/imagewriter.cc +++ b/lib/imagewriter/imagewriter.cc @@ -29,6 +29,9 @@ std::unique_ptr ImageWriter::create(const ImageWriterProto& config) case ImageWriterProto::kNsi: return ImageWriter::createNsiImageWriter(config); + case ImageWriterProto::kRaw: + return ImageWriter::createRawImageWriter(config); + default: Error() << "bad output image config"; return std::unique_ptr(); @@ -45,8 +48,9 @@ void ImageWriter::updateConfigForFilename(ImageWriterProto* proto, const std::st {".diskcopy", [&]() { proto->mutable_diskcopy(); }}, {".img", [&]() { proto->mutable_img(); }}, {".ldbs", [&]() { proto->mutable_ldbs(); }}, - {".st", [&]() { proto->mutable_img(); }}, {".nsi", [&]() { proto->mutable_nsi(); }}, + {".raw", [&]() { proto->mutable_raw(); }}, + {".st", [&]() { proto->mutable_img(); }}, {".xdf", [&]() { proto->mutable_img(); }}, }; diff --git a/lib/imagewriter/imagewriter.h b/lib/imagewriter/imagewriter.h index 321b9355..143c4af9 100644 --- a/lib/imagewriter/imagewriter.h +++ b/lib/imagewriter/imagewriter.h @@ -14,16 +14,12 @@ public: static std::unique_ptr create(const ImageWriterProto& config); static void updateConfigForFilename(ImageWriterProto* proto, const std::string& filename); - static std::unique_ptr createImgImageWriter( - const ImageWriterProto& config); - static std::unique_ptr createLDBSImageWriter( - const ImageWriterProto& config); - static std::unique_ptr createD64ImageWriter( - const ImageWriterProto& config); - static std::unique_ptr createDiskCopyImageWriter( - const ImageWriterProto& config); - static std::unique_ptr createNsiImageWriter( - const ImageWriterProto& config); + static std::unique_ptr createD64ImageWriter(const ImageWriterProto& config); + static std::unique_ptr createDiskCopyImageWriter(const ImageWriterProto& config); + static std::unique_ptr createImgImageWriter(const ImageWriterProto& config); + static std::unique_ptr createLDBSImageWriter(const ImageWriterProto& config); + static std::unique_ptr createNsiImageWriter(const ImageWriterProto& config); + static std::unique_ptr createRawImageWriter(const ImageWriterProto& config); public: void printMap(const Image& sectors); diff --git a/lib/imagewriter/imagewriter.proto b/lib/imagewriter/imagewriter.proto index 6585e026..22490fbf 100644 --- a/lib/imagewriter/imagewriter.proto +++ b/lib/imagewriter/imagewriter.proto @@ -29,6 +29,7 @@ message LDBSOutputProto { message DiskCopyOutputProto {} message NsiOutputProto {} +message RawOutputProto {} message ImageWriterProto { optional string filename = 1 [(help) = "filename of output sector image"]; @@ -38,6 +39,7 @@ message ImageWriterProto { LDBSOutputProto ldbs = 4; DiskCopyOutputProto diskcopy = 5; NsiOutputProto nsi = 6; + RawOutputProto raw = 7; } } diff --git a/lib/imagewriter/rawimagewriter.cc b/lib/imagewriter/rawimagewriter.cc new file mode 100644 index 00000000..b97512cd --- /dev/null +++ b/lib/imagewriter/rawimagewriter.cc @@ -0,0 +1,73 @@ +#include "globals.h" +#include "flags.h" +#include "sector.h" +#include "imagewriter/imagewriter.h" +#include "fmt/format.h" +#include "decoders/decoders.h" +#include "image.h" +#include "arch/northstar/northstar.h" +#include "lib/imagewriter/imagewriter.pb.h" +#include +#include +#include + +class RawImageWriter : public ImageWriter +{ +public: + RawImageWriter(const ImageWriterProto& config): + ImageWriter(config) + {} + + void writeImage(const Image& image) + { + const Geometry& geometry = image.getGeometry(); + + size_t trackSize = geometry.numSectors * geometry.sectorSize; + + if (geometry.numTracks * trackSize == 0) { + std::cout << "RAW: no sectors in output; skipping image file generation." << std::endl; + return; + } + + std::cout << fmt::format("RAW: writing {} cylinders, {} sides\n", + geometry.numTracks, geometry.numSides); + + std::ofstream outputFile(_config.filename(), std::ios::out | std::ios::binary); + if (!outputFile.is_open()) + Error() << "RAW: cannot open output file"; + + unsigned sectorFileOffset; + for (int track = 0; track < geometry.numTracks * geometry.numSides; track++) + { + int side = (track < geometry.numTracks) ? 0 : 1; + + std::vector> records; + for (int sectorId = 0; sectorId < geometry.numSectors; sectorId++) + { + const auto& sector = image.get(track % geometry.numTracks, side, sectorId); + if (sector) + records.insert(records.end(), sector->records.begin(), sector->records.end()); + } + + std::sort(records.begin(), records.end(), + [&](std::shared_ptr left, std::shared_ptr right) { + return left->startTime < right->startTime; + }); + + for (const auto& record : records) + { + record->rawData.writeTo(outputFile); + Bytes(3).writeTo(outputFile); + } + Bytes(1).writeTo(outputFile); + } + } +}; + + +std::unique_ptr ImageWriter::createRawImageWriter( + const ImageWriterProto& config) +{ + return std::unique_ptr(new RawImageWriter(config)); +} + diff --git a/lib/sector.h b/lib/sector.h index 6ad2862e..1c90cefc 100644 --- a/lib/sector.h +++ b/lib/sector.h @@ -4,6 +4,8 @@ #include "bytes.h" #include "fluxmap.h" +class Record; + /* * Note that sectors here used zero-based numbering throughout (to make the * maths easier); traditionally floppy disk use 0-based track numbering and @@ -38,6 +40,7 @@ public: int logicalSide = 0; int logicalSector = 0; Bytes data; + std::vector> records; std::tuple key() const { return std::make_tuple(logicalTrack, logicalSide, logicalSector, status); } diff --git a/mkninja.sh b/mkninja.sh index d80f02ec..d0915e33 100644 --- a/mkninja.sh +++ b/mkninja.sh @@ -470,6 +470,7 @@ buildlibrary libbackend.a \ lib/imagewriter/imgimagewriter.cc \ lib/imagewriter/ldbsimagewriter.cc \ lib/imagewriter/nsiimagewriter.cc \ + lib/imagewriter/rawimagewriter.cc \ lib/ldbs.cc \ lib/proto.cc \ lib/reader.cc \