Bash the imagewriter stuff into working with the new config system.

This commit is contained in:
David Given
2021-05-12 23:08:17 +02:00
parent df0a9bac96
commit 6ff84b3693
11 changed files with 224 additions and 275 deletions

View File

@@ -9,9 +9,6 @@ message ImgInputOutput {
optional int32 sector_size = 4;
}
optional int32 tracks = 1;
optional int32 heads = 2;
optional int32 sectors = 3;
repeated Format format = 4;
}

View File

@@ -6,6 +6,7 @@
#include "imagewriter/imagewriter.h"
#include "fmt/format.h"
#include "ldbs.h"
#include "lib/config.pb.h"
#include <algorithm>
#include <iostream>
#include <fstream>
@@ -24,15 +25,15 @@ static int sectors_per_track(int track)
class D64ImageWriter : public ImageWriter
{
public:
D64ImageWriter(const SectorSet& sectors, const ImageSpec& spec):
ImageWriter(sectors, spec)
D64ImageWriter(const Config_OutputFile& config):
ImageWriter(config)
{}
void writeImage()
void writeImage(const SectorSet& sectors)
{
std::cout << "writing D64 triangular image\n";
std::ofstream outputFile(spec.filename, std::ios::out | std::ios::binary);
std::ofstream outputFile(_config.filename(), std::ios::out | std::ios::binary);
if (!outputFile.is_open())
Error() << "cannot open output file";
@@ -55,9 +56,8 @@ public:
}
};
std::unique_ptr<ImageWriter> ImageWriter::createD64ImageWriter(
const SectorSet& sectors, const ImageSpec& spec)
std::unique_ptr<ImageWriter> ImageWriter::createD64ImageWriter(const Config_OutputFile& config)
{
return std::unique_ptr<ImageWriter>(new D64ImageWriter(sectors, spec));
return std::unique_ptr<ImageWriter>(new D64ImageWriter(config));
}

View File

@@ -6,6 +6,7 @@
#include "imagewriter/imagewriter.h"
#include "fmt/format.h"
#include "ldbs.h"
#include "lib/config.pb.h"
#include <algorithm>
#include <iostream>
#include <fstream>
@@ -27,35 +28,44 @@ static void write_and_update_checksum(ByteWriter& bw, uint32_t& checksum, const
class DiskCopyImageWriter : public ImageWriter
{
public:
DiskCopyImageWriter(const SectorSet& sectors, const ImageSpec& spec):
ImageWriter(sectors, spec)
DiskCopyImageWriter(const Config_OutputFile& config):
ImageWriter(config)
{}
void writeImage()
void writeImage(const SectorSet& sectors)
{
unsigned numCylinders;
unsigned numHeads;
unsigned numSectors;
unsigned numBytes;
sectors.calculateSize(numCylinders, numHeads, numSectors, numBytes);
bool mfm = false;
if (spec.bytes == 524)
switch (numBytes)
{
/* GCR disk */
case 524:
/* GCR disk */
break;
case 512:
/* MFM disk */
mfm = true;
break;
default:
Error() << "this image is not compatible with the DiskCopy 4.2 format";
}
else if (spec.bytes == 512)
{
/* MFM disk */
mfm = true;
}
else
Error() << "this image is not compatible with the DiskCopy 4.2 format";
std::cout << "writing DiskCopy 4.2 image\n"
<< fmt::format("{} tracks, {} heads, {} sectors, {} bytes per sector; {}\n",
spec.cylinders, spec.heads, spec.sectors, spec.bytes,
numCylinders, numHeads, numSectors, numBytes,
mfm ? "MFM" : "GCR");
auto sectors_per_track = [&](int track) -> int
{
if (mfm)
return spec.sectors;
return numSectors;
if (track < 16)
return 12;
@@ -77,9 +87,9 @@ public:
uint32_t tagChecksum = 0;
uint32_t offset = 0x54;
uint32_t sectorDataStart = offset;
for (int track = 0; track < spec.cylinders; track++)
for (int track = 0; track < numCylinders; track++)
{
for (int head = 0; head < spec.heads; head++)
for (int head = 0; head < numHeads; head++)
{
int sectorCount = sectors_per_track(track);
for (int sectorId = 0; sectorId < sectorCount; sectorId++)
@@ -97,9 +107,9 @@ public:
uint32_t sectorDataEnd = offset;
if (!mfm)
{
for (int track = 0; track < spec.cylinders; track++)
for (int track = 0; track < numCylinders; track++)
{
for (int head = 0; head < spec.heads; head++)
for (int head = 0; head < numHeads; head++)
{
int sectorCount = sectors_per_track(track);
for (int sectorId = 0; sectorId < sectorCount; sectorId++)
@@ -124,14 +134,14 @@ public:
if (mfm)
{
format = 0x22;
if (spec.sectors == 18)
if (numSectors == 18)
encoding = 3;
else
encoding = 2;
}
else
{
if (spec.heads == 2)
if (numHeads == 2)
{
encoding = 1;
format = 0x22;
@@ -155,14 +165,14 @@ public:
bw.write_8(format); /* format byte */
bw.write_be16(0x0100); /* magic number */
image.writeToFile(spec.filename);
image.writeToFile(_config.filename());
}
};
std::unique_ptr<ImageWriter> ImageWriter::createDiskCopyImageWriter(
const SectorSet& sectors, const ImageSpec& spec)
const Config_OutputFile& config)
{
return std::unique_ptr<ImageWriter>(new DiskCopyImageWriter(sectors, spec));
return std::unique_ptr<ImageWriter>(new DiskCopyImageWriter(config));
}

View File

@@ -5,10 +5,12 @@
#include "sectorset.h"
#include "imagewriter/imagewriter.h"
#include "utils.h"
#include "lib/config.pb.h"
#include "fmt/format.h"
#include <iostream>
#include <fstream>
#if 0
std::map<std::string, ImageWriter::Constructor> ImageWriter::formats =
{
{".adf", ImageWriter::createImgImageWriter},
@@ -19,48 +21,27 @@ std::map<std::string, ImageWriter::Constructor> ImageWriter::formats =
{".ldbs", ImageWriter::createLDBSImageWriter},
{".st", ImageWriter::createImgImageWriter},
};
#endif
ImageWriter::Constructor ImageWriter::findConstructor(const ImageSpec& spec)
std::unique_ptr<ImageWriter> ImageWriter::create(const Config_OutputFile& config)
{
const auto& filename = spec.filename;
for (const auto& e : formats)
{
if (endsWith(filename, e.first))
return e.second;
}
return NULL;
if (config.has_img())
return ImageWriter::createImgImageWriter(config);
else
Error() << "bad output image config";
}
std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const ImageSpec& spec)
{
verifyImageSpec(spec);
return findConstructor(spec)(sectors, spec);
}
//void ImageWriter::verifyImageSpec(const ImageSpec& spec)
//{
// if (!findConstructor(spec))
// Error() << "unrecognised output image filename extension";
//}
void ImageWriter::verifyImageSpec(const ImageSpec& spec)
{
if (!findConstructor(spec))
Error() << "unrecognised output image filename extension";
}
ImageWriter::ImageWriter(const SectorSet& sectors, const ImageSpec& spec):
sectors(sectors),
spec(spec)
ImageWriter::ImageWriter(const Config_OutputFile& config):
_config(config)
{}
void ImageWriter::adjustGeometry()
{
if (!spec.initialised)
{
sectors.calculateSize(spec.cylinders, spec.heads, spec.sectors, spec.bytes);
spec.initialised = true;
std::cout << "Autodetecting output geometry\n";
}
}
void ImageWriter::writeCsv(const std::string& filename)
void ImageWriter::writeCsv(const SectorSet& sectors, const std::string& filename)
{
std::ofstream f(filename, std::ios::out);
if (!f.is_open())
@@ -81,47 +62,45 @@ void ImageWriter::writeCsv(const std::string& filename)
"\"Status\""
"\n";
for (int track = 0; track < spec.cylinders; track++)
for (const auto& it : sectors.get())
{
for (int head = 0; head < spec.heads; head++)
{
for (int sectorId = 0; sectorId < spec.sectors; sectorId++)
{
f << fmt::format("{},{},", track, head);
const auto& sector = sectors.get(track, head, sectorId);
if (!sector)
f << fmt::format(",,{},,,,,,,,sector not found\n", sectorId);
else
f << fmt::format("{},{},{},{},{},{},{},{},{},{},{}\n",
sector->logicalTrack,
sector->logicalSide,
sector->logicalSector,
sector->clock,
sector->headerStartTime,
sector->headerEndTime,
sector->dataStartTime,
sector->dataEndTime,
sector->position.bytes,
sector->data.size(),
Sector::statusToString(sector->status)
);
}
}
const auto& sector = it.second;
f << fmt::format("{},{},{},{},{},{},{},{},{},{},{},{},{}\n",
sector->physicalTrack,
sector->physicalSide,
sector->logicalTrack,
sector->logicalSide,
sector->logicalSector,
sector->clock,
sector->headerStartTime,
sector->headerEndTime,
sector->dataStartTime,
sector->dataEndTime,
sector->position.bytes,
sector->data.size(),
Sector::statusToString(sector->status)
);
}
}
void ImageWriter::printMap()
void ImageWriter::printMap(const SectorSet& sectors)
{
unsigned numCylinders;
unsigned numHeads;
unsigned numSectors;
unsigned numBytes;
sectors.calculateSize(numCylinders, numHeads, numSectors, numBytes);
int badSectors = 0;
int missingSectors = 0;
int totalSectors = 0;
std::cout << "H.SS Tracks --->" << std::endl;
for (int head = 0; head < spec.heads; head++)
for (int head = 0; head < numHeads; head++)
{
for (int sectorId = 0; sectorId < spec.sectors; sectorId++)
for (int sectorId = 0; sectorId < numSectors; sectorId++)
{
std::cout << fmt::format("{}.{:2} ", head, sectorId);
for (int track = 0; track < spec.cylinders; track++)
for (int track = 0; track < numCylinders; track++)
{
const auto& sector = sectors.get(track, head, sectorId);
if (!sector)

View File

@@ -2,47 +2,33 @@
#define IMAGEWRITER_H
class SectorSet;
class ImageSpec;
class Config_OutputFile;
class ImageWriter
{
public:
ImageWriter(const SectorSet& sectors, const ImageSpec& spec);
ImageWriter(const Config_OutputFile& config);
virtual ~ImageWriter() {};
public:
static std::unique_ptr<ImageWriter> create(const SectorSet& sectors, const ImageSpec& spec);
static void verifyImageSpec(const ImageSpec& filename);
private:
typedef
std::function<
std::unique_ptr<ImageWriter>(const SectorSet& sectors, const ImageSpec& spec)
>
Constructor;
static std::map<std::string, Constructor> formats;
static std::unique_ptr<ImageWriter> create(const Config_OutputFile& config);
static std::unique_ptr<ImageWriter> createImgImageWriter(
const SectorSet& sectors, const ImageSpec& spec);
const Config_OutputFile& config);
static std::unique_ptr<ImageWriter> createLDBSImageWriter(
const SectorSet& sectors, const ImageSpec& spec);
const Config_OutputFile& config);
static std::unique_ptr<ImageWriter> createD64ImageWriter(
const SectorSet& sectors, const ImageSpec& spec);
const Config_OutputFile& config);
static std::unique_ptr<ImageWriter> createDiskCopyImageWriter(
const SectorSet& sectors, const ImageSpec& spec);
static Constructor findConstructor(const ImageSpec& spec);
const Config_OutputFile& config);
public:
virtual void adjustGeometry();
void printMap();
void writeCsv(const std::string& filename);
virtual void writeImage() = 0;
void printMap(const SectorSet& sectors);
void writeCsv(const SectorSet& sectors, const std::string& filename);
virtual void writeImage(const SectorSet& sectors) = 0;
protected:
const SectorSet& sectors;
ImageSpec spec;
const Config_OutputFile& _config;
};
#endif

View File

@@ -4,6 +4,7 @@
#include "sector.h"
#include "sectorset.h"
#include "imagewriter/imagewriter.h"
#include "lib/config.pb.h"
#include "fmt/format.h"
#include <algorithm>
#include <iostream>
@@ -12,16 +13,17 @@
class ImgImageWriter : public ImageWriter
{
public:
ImgImageWriter(const SectorSet& sectors, const ImageSpec& spec):
ImageWriter(sectors, spec)
ImgImageWriter(const Config_OutputFile& config):
ImageWriter(config)
{}
void writeImage()
void writeImage(const SectorSet& sectors)
{
unsigned numCylinders = spec.cylinders;
unsigned numHeads = spec.heads;
unsigned numSectors = spec.sectors;
unsigned numBytes = spec.bytes;
unsigned numCylinders;
unsigned numHeads;
unsigned numSectors;
unsigned numBytes;
sectors.calculateSize(numCylinders, numHeads, numSectors, numBytes);
size_t headSize = numSectors * numBytes;
size_t trackSize = headSize * numHeads;
@@ -32,7 +34,7 @@ public:
numCylinders * trackSize / 1024)
<< std::endl;
std::ofstream outputFile(spec.filename, std::ios::out | std::ios::binary);
std::ofstream outputFile(_config.filename(), std::ios::out | std::ios::binary);
if (!outputFile.is_open())
Error() << "cannot open output file";
@@ -55,7 +57,7 @@ public:
};
std::unique_ptr<ImageWriter> ImageWriter::createImgImageWriter(
const SectorSet& sectors, const ImageSpec& spec)
const Config_OutputFile& config)
{
return std::unique_ptr<ImageWriter>(new ImgImageWriter(sectors, spec));
return std::unique_ptr<ImageWriter>(new ImgImageWriter(config));
}

View File

@@ -6,6 +6,7 @@
#include "imagewriter/imagewriter.h"
#include "fmt/format.h"
#include "ldbs.h"
#include "lib/config.pb.h"
#include <algorithm>
#include <iostream>
#include <fstream>
@@ -13,18 +14,20 @@
class LDBSImageWriter : public ImageWriter
{
public:
LDBSImageWriter(const SectorSet& sectors, const ImageSpec& spec):
ImageWriter(sectors, spec)
LDBSImageWriter(const Config_OutputFile& config):
ImageWriter(config)
{}
void writeImage()
void writeImage(const SectorSet& sectors)
{
LDBS ldbs;
unsigned numCylinders = spec.cylinders;
unsigned numHeads = spec.heads;
unsigned numSectors = spec.sectors;
unsigned numBytes = spec.bytes;
unsigned numCylinders;
unsigned numHeads;
unsigned numSectors;
unsigned numBytes;
sectors.calculateSize(numCylinders, numHeads, numSectors, numBytes);
std::cout << fmt::format("writing {} tracks, {} heads, {} sectors, {} bytes per sector",
numCylinders, numHeads,
numSectors, numBytes)
@@ -95,12 +98,11 @@ public:
uint32_t trackDirectoryAddress = ldbs.put(trackDirectory, LDBS_TRACK_BLOCK);
Bytes data = ldbs.write(trackDirectoryAddress);
data.writeToFile(spec.filename);
data.writeToFile(_config.filename());
}
};
std::unique_ptr<ImageWriter> ImageWriter::createLDBSImageWriter(
const SectorSet& sectors, const ImageSpec& spec)
std::unique_ptr<ImageWriter> ImageWriter::createLDBSImageWriter(const Config_OutputFile& config)
{
return std::unique_ptr<ImageWriter>(new LDBSImageWriter(sectors, spec));
return std::unique_ptr<ImageWriter>(new LDBSImageWriter(config));
}

View File

@@ -27,16 +27,6 @@ FlagGroup readerFlags
&fluxmapReaderFlags,
};
//static DataSpecFlag source(
// { "--source", "-s" },
// "source for data",
// ":t=0-79:s=0-1:d=0");
//
//static DataSpecFlag output(
// { "--output", "-o" },
// "output image file to write to",
// "");
static StringFlag destination(
{ "--write-flux", "-f" },
"write the raw magnetic flux to this file",
@@ -66,16 +56,6 @@ static StringFlag csvFile(
static std::unique_ptr<FluxSink> outputFluxSink;
static void writeSectorsToFile(const SectorSet& sectors, const ImageSpec& spec)
{
std::unique_ptr<ImageWriter> writer(ImageWriter::create(sectors, spec));
writer->adjustGeometry();
writer->printMap();
if (!csvFile.get().empty())
writer->writeCsv(csvFile.get());
writer->writeImage();
}
void Track::readFluxmap()
{
std::cout << fmt::format("{0:>3}.{1}: ", physicalTrack, physicalSide) << std::flush;
@@ -158,131 +138,124 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
{
for (int side : iterate(config.sides()))
{
#if 0
auto track = std::make_unique<Track>(location
std::vector<std::unique_ptr<Track>> tracks;
for (const auto& location : spec.locations)
{
auto track = std::make_unique<Track>(location.track, location.side);
track->fluxsource = fluxSource;
tracks.push_back(std::move(track));
}
#endif
auto track = std::make_unique<Track>(cylinder, side);
track->fluxsource = &fluxsource;
auto track = std::make_unique<Track>(cylinder, side);
track->fluxsource = &fluxsource;
std::map<int, std::unique_ptr<Sector>> readSectors;
for (int retry = ::retries; retry >= 0; retry--)
{
track->readFluxmap();
decoder.decodeToSectors(*track);
std::map<int, std::unique_ptr<Sector>> readSectors;
for (int retry = ::retries; retry >= 0; retry--)
{
track->readFluxmap();
decoder.decodeToSectors(*track);
std::cout << " ";
std::cout << fmt::format("{} records, {} sectors; ",
track->rawrecords.size(),
track->sectors.size());
if (track->sectors.size() > 0)
std::cout << fmt::format("{:.2f}us clock ({:.0f}kHz); ",
track->sectors.begin()->clock / 1000.0,
1000000.0 / track->sectors.begin()->clock);
std::cout << " ";
std::cout << fmt::format("{} records, {} sectors; ",
track->rawrecords.size(),
track->sectors.size());
if (track->sectors.size() > 0)
std::cout << fmt::format("{:.2f}us clock ({:.0f}kHz); ",
track->sectors.begin()->clock / 1000.0,
1000000.0 / track->sectors.begin()->clock);
for (auto& sector : track->sectors)
{
auto& replacing = readSectors[sector.logicalSector];
replace_sector(replacing, sector);
}
bool hasBadSectors = false;
std::set<unsigned> requiredSectors = decoder.requiredSectors(*track);
for (const auto& i : readSectors)
{
const auto& sector = i.second;
requiredSectors.erase(sector->logicalSector);
if (sector->status != Sector::OK)
for (auto& sector : track->sectors)
{
std::cout << std::endl
<< " Failed to read sector " << sector->logicalSector
<< " (" << Sector::statusToString((Sector::Status)sector->status) << "); ";
auto& replacing = readSectors[sector.logicalSector];
replace_sector(replacing, sector);
}
bool hasBadSectors = false;
std::set<unsigned> requiredSectors = decoder.requiredSectors(*track);
for (const auto& i : readSectors)
{
const auto& sector = i.second;
requiredSectors.erase(sector->logicalSector);
if (sector->status != Sector::OK)
{
std::cout << std::endl
<< " Failed to read sector " << sector->logicalSector
<< " (" << Sector::statusToString((Sector::Status)sector->status) << "); ";
hasBadSectors = true;
}
}
for (unsigned logicalSector : requiredSectors)
{
std::cout << "\n"
<< " Required sector " << logicalSector << " missing; ";
hasBadSectors = true;
}
}
for (unsigned logicalSector : requiredSectors)
{
std::cout << "\n"
<< " Required sector " << logicalSector << " missing; ";
hasBadSectors = true;
}
if (hasBadSectors)
failures = false;
if (hasBadSectors)
failures = false;
std::cout << std::endl
<< " ";
std::cout << std::endl
<< " ";
if (!hasBadSectors)
if (!hasBadSectors)
break;
if (!track->fluxsource->retryable())
break;
if (!track->fluxsource->retryable())
break;
if (retry == 0)
std::cout << "giving up" << std::endl
<< " ";
else
std::cout << retry << " retries remaining" << std::endl;
}
if (dumpRecords)
{
std::cout << "\nRaw (undecoded) records follow:\n\n";
for (auto& record : track->rawrecords)
{
std::cout << fmt::format("I+{:.2f}us with {:.2f}us clock\n",
record.position.ns() / 1000.0, record.clock / 1000.0);
hexdump(std::cout, record.data);
std::cout << std::endl;
if (retry == 0)
std::cout << "giving up" << std::endl
<< " ";
else
std::cout << retry << " retries remaining" << std::endl;
}
}
if (dumpSectors)
{
std::cout << "\nDecoded sectors follow:\n\n";
for (auto& sector : track->sectors)
{
std::cout << fmt::format("{}.{:02}.{:02}: I+{:.2f}us with {:.2f}us clock: status {}\n",
sector.logicalTrack, sector.logicalSide, sector.logicalSector,
sector.position.ns() / 1000.0, sector.clock / 1000.0,
sector.status);
hexdump(std::cout, sector.data);
std::cout << std::endl;
}
}
int size = 0;
bool printedTrack = false;
for (auto& i : readSectors)
{
auto& sector = i.second;
if (sector)
if (dumpRecords)
{
if (!printedTrack)
std::cout << "\nRaw (undecoded) records follow:\n\n";
for (auto& record : track->rawrecords)
{
std::cout << fmt::format("logical track {}.{}; ", sector->logicalTrack, sector->logicalSide);
printedTrack = true;
std::cout << fmt::format("I+{:.2f}us with {:.2f}us clock\n",
record.position.ns() / 1000.0, record.clock / 1000.0);
hexdump(std::cout, record.data);
std::cout << std::endl;
}
size += sector->data.size();
std::unique_ptr<Sector>& replacing = allSectors.get(sector->logicalTrack, sector->logicalSide, sector->logicalSector);
replace_sector(replacing, *sector);
}
}
std::cout << size << " bytes decoded." << std::endl;
}
if (dumpSectors)
{
std::cout << "\nDecoded sectors follow:\n\n";
for (auto& sector : track->sectors)
{
std::cout << fmt::format("{}.{:02}.{:02}: I+{:.2f}us with {:.2f}us clock: status {}\n",
sector.logicalTrack, sector.logicalSide, sector.logicalSector,
sector.position.ns() / 1000.0, sector.clock / 1000.0,
sector.status);
hexdump(std::cout, sector.data);
std::cout << std::endl;
}
}
int size = 0;
bool printedTrack = false;
for (auto& i : readSectors)
{
auto& sector = i.second;
if (sector)
{
if (!printedTrack)
{
std::cout << fmt::format("logical track {}.{}; ", sector->logicalTrack, sector->logicalSide);
printedTrack = true;
}
size += sector->data.size();
std::unique_ptr<Sector>& replacing = allSectors.get(sector->logicalTrack, sector->logicalSide, sector->logicalSector);
replace_sector(replacing, *sector);
}
}
std::cout << size << " bytes decoded." << std::endl;
}
}
Error() << "write to image not done";
//writeSectorsToFile(allSectors, outputSpec);
writer.printMap(allSectors);
if (!csvFile.get().empty())
writer.writeCsv(allSectors, csvFile.get());
writer.writeImage(allSectors);
if (failures)
std::cerr << "Warning: some sectors could not be decoded." << std::endl;
}

View File

@@ -18,6 +18,8 @@ static void syntax()
int mainConvertImage(int argc, const char* argv[])
{
Error() << "unimplemented";
#if 0
auto filenames = flags.parseFlagsWithFilenames(argc, argv);
if (filenames.size() != 2)
syntax();
@@ -32,6 +34,7 @@ int mainConvertImage(int argc, const char* argv[])
writer->adjustGeometry();
writer->printMap();
writer->writeImage();
#endif
return 0;
}

View File

@@ -40,11 +40,7 @@ int mainRead(int argc, const char* argv[])
else
Error() << "no input disk format specified";
std::unique_ptr<ImageWriter> writer;
// if (config.output().file().has_img())
// write.reset(new ImgImageWriter());
// else
// Error() << "no output image format specified";
std::unique_ptr<ImageWriter> writer(ImageWriter::create(config.output().file()));
readDiskCommand(*fluxSource, *decoder, *writer);

View File

@@ -1,5 +1,6 @@
input {
disk {
fluxfile: "samples/brother-clean.flux"
brother {}
}
}