First largely untested draft of a working verifier.

This commit is contained in:
David Given
2021-07-19 00:13:06 +02:00
parent d51160babb
commit b887bebb26
28 changed files with 177 additions and 47 deletions

View File

@@ -51,7 +51,7 @@ static void write_bits(std::vector<bool>& bits, unsigned& cursor, const Bytes& b
}
}
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector)
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector)
{
if ((sector->data.size() != 512) && (sector->data.size() != 528))
Error() << "unsupported sector size --- you must pick 512 or 528";
@@ -104,7 +104,24 @@ public:
_config(config.amiga()) {}
public:
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const Image& image)
std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
{
std::vector<std::shared_ptr<Sector>> sectors;
if ((physicalTrack >= 0) && (physicalTrack < AMIGA_TRACKS_PER_DISK))
{
for (int sectorId=0; sectorId<AMIGA_SECTORS_PER_TRACK; sectorId++)
{
const auto& sector = image.get(physicalTrack, physicalSide, sectorId);
if (sector)
sectors.push_back(sector);
}
}
return sectors;
}
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const Image& image) override
{
if ((physicalTrack < 0) || (physicalTrack >= AMIGA_TRACKS_PER_DISK))
return std::unique_ptr<Fluxmap>();
@@ -118,7 +135,7 @@ public:
for (int sectorId=0; sectorId<AMIGA_SECTORS_PER_TRACK; sectorId++)
{
const auto* sectorData = image.get(physicalTrack, physicalSide, sectorId);
const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId);
if (sectorData)
write_sector(bits, cursor, sectorData);
}

View File

@@ -171,7 +171,7 @@ public:
double dataMs = headerMs + postHeaderSpacingMs;
unsigned dataCursor = dataMs*1e3 / clockRateUs;
const auto* sectorData = image.get(logicalTrack, 0, sectorId);
const auto& sectorData = image.get(logicalTrack, 0, sectorId);
fillBitmapTo(bits, cursor, headerCursor, { true, false });
write_sector_header(bits, cursor, logicalTrack, sectorId);

View File

@@ -220,7 +220,7 @@ public:
* contains the BAM.
*/
const auto* sectorData = image.get(C64_BAM_TRACK*2, 0, 0); //Read de BAM to get the DISK ID bytes
const auto& sectorData = image.get(C64_BAM_TRACK*2, 0, 0); //Read de BAM to get the DISK ID bytes
if (sectorData)
{
ByteReader br(sectorData->data);
@@ -246,7 +246,7 @@ public:
unsigned writtenSectors = 0;
for (int sectorId=0; sectorId<numSectors; sectorId++)
{
const auto* sectorData = image.get(physicalTrack, physicalSide, sectorId);
const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId);
if (sectorData)
{
writeSector(bits, cursor, sectorData);
@@ -266,7 +266,7 @@ public:
}
private:
void writeSector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector) const
void writeSector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector) const
{
/* Source: http://www.unusedino.de/ec64/technical/formats/g64.html
* 1. Header sync FF FF FF FF FF (40 'on' bits, not GCR)

View File

@@ -174,7 +174,7 @@ public:
writeFillerBytes(trackdata.gap3(), gapFill);
first = false;
const auto* sectorData = image.get(physicalTrack, physicalSide, sectorId);
const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId);
if (!sectorData)
{
/* If there are any missing sectors, this is an empty track. */

View File

@@ -164,7 +164,7 @@ static uint8_t encode_side(uint8_t track, uint8_t side)
return (side ? 0x20 : 0x00) | ((track>0x3f) ? 0x01 : 0x00);
}
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector)
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector)
{
if ((sector->data.size() != 512) && (sector->data.size() != 524))
Error() << "unsupported sector size --- you must pick 512 or 524";
@@ -224,7 +224,7 @@ public:
unsigned numSectors = sectorsForTrack(physicalTrack);
for (int sectorId=0; sectorId<numSectors; sectorId++)
{
const auto* sectorData = image.get(physicalTrack, physicalSide, sectorId);
const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId);
write_sector(bits, cursor, sectorData);
}

View File

@@ -17,7 +17,7 @@
#define TOTAL_SECTOR_BYTES ()
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector)
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector)
{
int preambleSize = 0;
int encodedSectorSize = 0;
@@ -116,7 +116,7 @@ public:
if ((physicalTrack < 0) || (physicalTrack >= 35))
return std::unique_ptr<Fluxmap>();
const auto* sector = image.get(physicalTrack, physicalSide, 0);
const auto& sector = image.get(physicalTrack, physicalSide, 0);
if (sector->data.size() == NORTHSTAR_PAYLOAD_SIZE_SD) {
bitsPerRevolution /= 2; // FM
@@ -129,7 +129,7 @@ public:
for (int sectorId = 0; sectorId < 10; sectorId++)
{
const auto* sectorData = image.get(physicalTrack, physicalSide, sectorId);
const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId);
write_sector(bits, cursor, sectorData);
}

View File

@@ -79,7 +79,7 @@ public:
writeBytes(_config.gap3_bytes(), 0x55);
first = false;
const auto* sectorData = image.get(physicalTrack, physicalSide, sectorId);
const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId);
if (!sectorData)
Error() << fmt::format("format tried to find sector {} which wasn't in the input file", sectorId);

View File

@@ -4,6 +4,7 @@
class Fluxmap;
class EncoderProto;
class Image;
class Sector;
class AbstractEncoder
{
@@ -13,6 +14,9 @@ public:
static std::unique_ptr<AbstractEncoder> create(const EncoderProto& config);
public:
virtual std::vector<std::shared_ptr<Sector>> collectSectors(int physicalCylinder, int physicalHead, const Image& image)
{ return {}; }
virtual std::unique_ptr<Fluxmap> encode(
int physicalCylinder, int physicalHead, const Image& image) = 0;
};

View File

@@ -15,21 +15,22 @@ Image::Image(std::set<std::shared_ptr<Sector>>& sectors)
calculateSize();
}
Sector* Image::get(unsigned track, unsigned side, unsigned sectorid) const
const std::shared_ptr<Sector>& Image::get(unsigned track, unsigned side, unsigned sectorid) const
{
const static std::shared_ptr<Sector> NONE;
key_t key = std::make_tuple(track, side, sectorid);
auto i = _sectors.find(key);
if (i == _sectors.end())
return nullptr;
return i->second.get();
return NONE;
return i->second;
}
Sector* Image::put(unsigned track, unsigned side, unsigned sectorid)
const std::shared_ptr<Sector>& Image::put(unsigned track, unsigned side, unsigned sectorid)
{
key_t key = std::make_tuple(track, side, sectorid);
std::shared_ptr<Sector> sector = std::make_shared<Sector>();
_sectors[key] = sector;
return sector.get();
return _sectors[key] = sector;
}
void Image::calculateSize()

View File

@@ -38,8 +38,8 @@ public:
public:
void calculateSize();
Sector* get(unsigned track, unsigned side, unsigned sectorId) const;
Sector* put(unsigned track, unsigned side, unsigned sectorId);
const std::shared_ptr<Sector>& get(unsigned track, unsigned side, unsigned sectorId) const;
const std::shared_ptr<Sector>& put(unsigned track, unsigned side, unsigned sectorId);
const_iterator begin() const { return const_iterator(_sectors.cbegin()); }
const_iterator end() const { return const_iterator(_sectors.cend()); }

View File

@@ -62,7 +62,7 @@ public:
{
for (int sectorId = 0; sectorId < numSectors; sectorId++)
{
Sector* sector = image.put(track, head, sectorId);
const auto& sector = image.put(track, head, sectorId);
if ((offset < inputFileSize))
{ //still data available sector OK
br.seek(offset);

View File

@@ -105,7 +105,7 @@ public:
Bytes tag = br.read(12);
tagPtr += 12;
Sector* sector = image.put(track, head, sectorId);
const auto& sector = image.put(track, head, sectorId);
sector->status = Sector::OK;
sector->logicalTrack = sector->physicalCylinder = track;
sector->logicalSide = sector->physicalHead = head;

View File

@@ -192,7 +192,7 @@ public:
for (int s = 0; s < header.numSectors; s++)
{
Bytes sectordata;
Sector* sector = image.put(header.track, header.Head, sector_map[s]);
const auto& sector = image.put(header.track, header.Head, sector_map[s]);
//read the status of the sector
unsigned int Status_Sector = br.read_8();
headerPtr++;

View File

@@ -40,7 +40,7 @@ public:
Bytes data(trackdata.sector_size());
inputFile.read((char*) data.begin(), data.size());
Sector* sector = image.put(physicalCylinder, side, sectorId);
const auto& sector = image.put(physicalCylinder, side, sectorId);
sector->status = Sector::OK;
sector->logicalTrack = track;
sector->physicalCylinder = physicalCylinder;

View File

@@ -110,7 +110,7 @@ public:
inputFile.read((char*) data.begin(), sectorSize);
unsigned head = !!(header.flags & JV3_SIDE);
Sector* sector = image.put(header.track, head, header.sector);
const auto& sector = image.put(header.track, head, header.sector);
sector->status = Sector::OK;
sector->logicalTrack = sector->physicalCylinder = header.track;
sector->logicalSide = sector->physicalHead = head;

View File

@@ -87,7 +87,7 @@ public:
Bytes data(sectorSize);
inputFile.read((char*) data.begin(), sectorSize);
Sector* sector = image.put(track, head, sectorId);
const auto& sector = image.put(track, head, sectorId);
sector->status = Sector::OK;
sector->logicalTrack = sector->physicalCylinder = track;
sector->logicalSide = sector->physicalHead = head;

View File

@@ -42,7 +42,7 @@ public:
int sectorCount = sectors_per_track(track);
for (int sectorId = 0; sectorId < sectorCount; sectorId++)
{
const auto* sector = image.get(track, 0, sectorId);
const auto& sector = image.get(track, 0, sectorId);
if (sector)
{
outputFile.seekp(offset);

View File

@@ -89,7 +89,7 @@ public:
int sectorCount = sectors_per_track(track);
for (int sectorId = 0; sectorId < sectorCount; sectorId++)
{
const auto* sector = image.get(track, side, sectorId);
const auto& sector = image.get(track, side, sectorId);
if (sector)
{
bw.seek(offset);

View File

@@ -131,7 +131,7 @@ void ImageWriter::printMap(const Image& image)
std::cout << fmt::format("{}.{:2} ", side, sectorId);
for (int track = 0; track < geometry.numTracks; track++)
{
const auto* sector = image.get(track, side, sectorId);
const auto& sector = image.get(track, side, sectorId);
if (!sector)
{
std::cout << 'X';

View File

@@ -39,7 +39,7 @@ public:
for (int sectorId = 0; sectorId < numSectors; sectorId++)
{
const auto* sector = image.get(track, side, sectorId);
const auto& sector = image.get(track, side, sectorId);
if (sector)
sector->data.slice(0, sectorSize).writeTo(outputFile);
else

View File

@@ -43,7 +43,7 @@ public:
int actualSectors = 0;
for (int sectorId = 0; sectorId < geometry.numSectors; sectorId++)
{
const auto* sector = image.get(track, side, sectorId);
const auto& sector = image.get(track, side, sectorId);
if (sector)
actualSectors++;
}
@@ -59,7 +59,7 @@ public:
for (int sectorId = 0; sectorId < geometry.numSectors; sectorId++)
{
const auto* sector = image.get(track, side, sectorId);
const auto& sector = image.get(track, side, sectorId);
if (sector)
{
uint32_t sectorLabel = (('S') << 24) | ((track & 0xff) << 16) | (side << 8) | sectorId;

View File

@@ -46,7 +46,7 @@ public:
int side = (track < geometry.numTracks) ? 0 : 1;
for (int sectorId = 0; sectorId < geometry.numSectors; sectorId++)
{
const auto* sector = image.get(track % geometry.numTracks, side, sectorId);
const auto& sector = image.get(track % geometry.numTracks, side, sectorId);
if (sector)
{
if (side == 0) { /* Side 0 is from track 0-34 */

View File

@@ -30,3 +30,18 @@ Sector::Status Sector::stringToStatus(const std::string& value)
return Status::INTERNAL_ERROR;
}
bool sectorPointerSortPredicate(std::shared_ptr<Sector>& lhs, std::shared_ptr<Sector>& rhs)
{
return *lhs < *rhs;
}
bool sectorPointerEqualsPredicate(std::shared_ptr<Sector>& lhs, std::shared_ptr<Sector>& rhs)
{
if (!lhs && !rhs)
return true;
if (!lhs || !rhs)
return false;
return *lhs == *rhs;
}

View File

@@ -38,10 +38,23 @@ public:
int logicalSide = 0;
int logicalSector = 0;
Bytes data;
std::tuple<int, int, int, Status> key() const
{ return std::make_tuple(logicalTrack, logicalSide, logicalSector, status); }
bool operator == (const Sector& rhs) const
{ return key() == rhs.key(); }
bool operator != (const Sector& rhs) const
{ return key() != rhs.key(); }
bool operator < (const Sector& rhs) const
{ return key() < rhs.key(); }
};
inline Sector& getSector(const std::set<std::shared_ptr<Sector>>& sectors,
unsigned track, unsigned side, unsigned sector);
extern bool sectorPointerSortPredicate(std::shared_ptr<Sector>& lhs, std::shared_ptr<Sector>& rhs);
extern bool sectorPointerEqualsPredicate(std::shared_ptr<Sector>& lhs, std::shared_ptr<Sector>& rhs);
#endif

View File

@@ -6,6 +6,7 @@
#include "protocol.h"
#include "usb/usb.h"
#include "encoders/encoders.h"
#include "decoders/decoders.h"
#include "fluxsource/fluxsource.h"
#include "fluxsink/fluxsink.h"
#include "imagereader/imagereader.h"
@@ -50,6 +51,69 @@ void writeTracks(
}
}
void writeTracksAndVerify(
FluxSink& fluxSink,
AbstractEncoder& encoder,
FluxSource& fluxSource,
AbstractDecoder& decoder,
Image& image)
{
std::cout << "Writing to: " << fluxSink << std::endl;
for (unsigned cylinder : iterate(config.cylinders()))
{
for (unsigned head : iterate(config.heads()))
{
std::cout << fmt::format("{0:>3}.{1}: Write: ", cylinder, head) << std::flush;
std::unique_ptr<Fluxmap> fluxmap = encoder.encode(cylinder, head, image);
if (!fluxmap)
{
/* Erase this track rather than writing. */
fluxmap.reset(new Fluxmap());
fluxSink.writeFlux(cylinder, head, *fluxmap);
std::cout << "erased\n";
}
else
{
for (int retry = 0;; retry++)
{
/* Precompensation actually seems to make things worse, so let's leave
* it disabled for now. */
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
fluxSink.writeFlux(cylinder, head, *fluxmap);
std::cout << fmt::format(
"{0} ms in {1} bytes\n", int(fluxmap->duration()/1e6), fluxmap->bytes());
std::cout << fmt::format(" Verify: ", cylinder, head) << std::flush;
std::shared_ptr<Fluxmap> writtenFluxmap = fluxSource.readFlux(cylinder, head);
std::cout << fmt::format(
"{0} ms in {1} bytes\n", int(writtenFluxmap->duration()/1e6), writtenFluxmap->bytes());
const auto trackdata = decoder.decodeToSectors(writtenFluxmap, cylinder, head);
std::vector<std::shared_ptr<Sector>> gotSectors = trackdata->sectors;
std::remove_if(gotSectors.begin(), gotSectors.end(), [](const auto& s) { return s->status != Sector::OK; });
std::sort(gotSectors.begin(), gotSectors.end(), sectorPointerSortPredicate);
auto newLast = std::unique(gotSectors.begin(), gotSectors.end(), sectorPointerEqualsPredicate);
gotSectors.erase(newLast, gotSectors.end());
std::vector<std::shared_ptr<Sector>> wantedSectors = encoder.collectSectors(cylinder, head, image);
std::sort(wantedSectors.begin(), wantedSectors.end(), sectorPointerSortPredicate);
if (std::equal(gotSectors.begin(), gotSectors.end(), wantedSectors.begin(), wantedSectors.end(),
sectorPointerEqualsPredicate))
break;
if (retry == config.decoder().retries())
Error() << "Write failed; uncorrectable error during write.";
std::cout << fmt::format(" Rewrite: ", cylinder, head) << std::flush;
}
}
}
}
}
void fillBitmapTo(std::vector<bool>& bitmap,
unsigned& cursor, unsigned terminateAt,
const std::vector<bool>& pattern)
@@ -64,15 +128,19 @@ void fillBitmapTo(std::vector<bool>& bitmap,
}
}
void writeDiskCommand(ImageReader& imageReader, AbstractEncoder& encoder, FluxSink& fluxSink)
void writeDiskCommand(ImageReader& imageReader, AbstractEncoder& encoder, FluxSink& fluxSink,
AbstractDecoder* decoder, FluxSource* fluxSource)
{
Image image = imageReader.readImage();
writeTracks(fluxSink,
[&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
{
return encoder.encode(physicalTrack, physicalSide, image);
}
);
if (fluxSource && decoder)
writeTracksAndVerify(fluxSink, encoder, *fluxSource, *decoder, image);
else
writeTracks(fluxSink,
[&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
{
return encoder.encode(physicalTrack, physicalSide, image);
}
);
}
void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink)

View File

@@ -2,6 +2,7 @@
#define WRITER_H
class Fluxmap;
class AbstractDecoder;
class AbstractEncoder;
class ImageReader;
class FluxSource;
@@ -13,7 +14,8 @@ extern void fillBitmapTo(std::vector<bool>& bitmap,
unsigned& cursor, unsigned terminateAt,
const std::vector<bool>& pattern);
extern void writeDiskCommand(ImageReader& imageReader, AbstractEncoder& encoder, FluxSink& fluxSink);
extern void writeDiskCommand(ImageReader& imageReader, AbstractEncoder& encoder, FluxSink& fluxSink,
AbstractDecoder* decoder = nullptr, FluxSource* fluxSource = nullptr);
extern void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink);
#endif

View File

@@ -191,7 +191,7 @@ static void readRow(const std::vector<std::string>& row, Image& image)
int logicalSide = std::stoi(row[3]);
int logicalSector = std::stoi(row[4]);
Sector* sector = image.put(logicalTrack, logicalSide, logicalSector);
const auto& sector = image.put(logicalTrack, logicalSide, logicalSector);
sector->physicalCylinder = std::stoi(row[0]);
sector->physicalHead = std::stoi(row[1]);
sector->logicalTrack = logicalTrack;

View File

@@ -7,6 +7,7 @@
#include "sector.h"
#include "proto.h"
#include "fluxsink/fluxsink.h"
#include "fluxsource/fluxsource.h"
#include "arch/brother/brother.h"
#include "arch/ibm/ibm.h"
#include "imagereader/imagereader.h"
@@ -33,6 +34,7 @@ static StringFlag destFlux(
[](const auto& value)
{
FluxSink::updateConfigForFilename(config.mutable_flux_sink(), value);
FluxSource::updateConfigForFilename(config.mutable_flux_source(), value);
});
static StringFlag destCylinders(
@@ -63,7 +65,15 @@ int mainWrite(int argc, const char* argv[])
std::unique_ptr<AbstractEncoder> encoder(AbstractEncoder::create(config.encoder()));
std::unique_ptr<FluxSink> fluxSink(FluxSink::create(config.flux_sink()));
writeDiskCommand(*reader, *encoder, *fluxSink);
std::unique_ptr<AbstractDecoder> decoder;
if (config.has_decoder())
decoder = AbstractDecoder::create(config.decoder());
std::unique_ptr<FluxSource> fluxSource;
if (config.has_flux_source())
fluxSource = FluxSource::create(config.flux_source());
writeDiskCommand(*reader, *encoder, *fluxSink, decoder.get(), fluxSource.get());
return 0;
}