Output images now get geometry specs to indicate what kind of file to write.

This commit is contained in:
David Given
2019-08-07 23:23:07 +02:00
parent eb924780ab
commit d8172154c3
27 changed files with 201 additions and 187 deletions

View File

@@ -5,6 +5,11 @@
#include <regex>
#include <sstream>
MissingModifierException::MissingModifierException(const std::string& mod):
mod(mod),
std::runtime_error(fmt::format("missing mandatory modifier '{}'", mod))
{}
std::vector<std::string> DataSpec::split(
const std::string& s, const std::string& delimiter)
{
@@ -82,45 +87,86 @@ void DataSpec::set(const std::string& spec)
}
}
const DataSpec::Modifier& DataSpec::at(const std::string& mod) const
{
try
{
return modifiers.at(mod);
}
catch (const std::out_of_range& e)
{
throw MissingModifierException(mod);
}
}
bool DataSpec::has(const std::string& mod) const
{
return modifiers.find(mod) != modifiers.end();
}
FluxSpec::FluxSpec(const DataSpec& spec)
{
filename = spec.filename;
locations.clear();
const auto& drives = spec.modifiers.at("d").data;
if (drives.size() != 1)
Error() << "you must specify exactly one drive";
drive = *drives.begin();
const auto& tracks = spec.modifiers.at("t").data;
const auto& sides = spec.modifiers.at("s").data;
for (auto track : tracks)
try
{
for (auto side : sides)
locations.push_back({ drive, track, side });
filename = spec.filename;
locations.clear();
const auto& drives = spec.at("d").data;
if (drives.size() != 1)
Error() << "you must specify exactly one drive";
drive = *drives.begin();
const auto& tracks = spec.at("t").data;
const auto& sides = spec.at("s").data;
for (auto track : tracks)
{
for (auto side : sides)
locations.push_back({ drive, track, side });
}
for (const auto& e : spec.modifiers)
{
const auto name = e.second.name;
if ((name != "t") && (name != "s") && (name != "d"))
Error() << fmt::format("unknown fluxspec modifier '{}'", name);
}
}
for (const auto& e : spec.modifiers)
catch (const MissingModifierException& e)
{
const auto name = e.second.name;
if ((name != "t") && (name != "s") && (name != "d"))
Error() << fmt::format("unknown fluxspec modifier '{}'", name);
Error() << e.what() << " in fluxspec '" << spec << "'";
}
}
ImageSpec::ImageSpec(const DataSpec& spec)
{
filename = spec.filename;
try
{
filename = spec.filename;
tracks = spec.modifiers.at("t").only();
heads = spec.modifiers.at("h").only();
sectors = spec.modifiers.at("s").only();
if (!spec.has("c") && !spec.has("h") && !spec.has("s") && !spec.has("b"))
{
cylinders = heads = sectors = bytes = 0;
initialised = false;
}
else
{
cylinders = spec.at("c").only();
heads = spec.at("h").only();
sectors = spec.at("s").only();
bytes = spec.at("b").only();
initialised = true;
}
}
catch (const MissingModifierException& e)
{
Error() << e.what() << " in imagespec '" << spec << "'";
}
for (const auto& e : spec.modifiers)
{
const auto name = e.second.name;
if ((name != "t") && (name != "h") && (name != "s"))
if ((name != "c") && (name != "h") && (name != "s") && (name != "b"))
Error() << fmt::format("unknown fluxspec modifier '{}'", name);
}
}

View File

@@ -1,6 +1,13 @@
#ifndef DATASPEC_H
#define DATASPEC_H
class MissingModifierException : public std::runtime_error
{
public:
MissingModifierException(const std::string& mod);
const std::string mod;
};
class DataSpec
{
public:
@@ -36,6 +43,9 @@ public:
void set(const std::string& spec);
operator std::string () const;
const Modifier& at(const std::string& mod) const;
bool has(const std::string& mod) const;
std::string filename;
std::map<std::string, Modifier> modifiers;
};
@@ -72,9 +82,11 @@ public:
public:
std::string filename;
unsigned tracks;
unsigned cylinders;
unsigned heads;
unsigned sectors;
unsigned bytes;
bool initialised : 1;
};
static inline std::ostream& operator << (std::ostream& os, const DataSpec& dataSpec)

View File

@@ -3,43 +3,37 @@
#include "sector.h"
#include "sectorset.h"
#include "fmt/format.h"
#include "flags.h"
#include "dataspec.h"
#include <algorithm>
#include <iostream>
#include <fstream>
Geometry guessGeometry(const SectorSet& sectors)
void readSectorsFromFile(SectorSet& sectors, const ImageSpec& spec)
{
Geometry g;
sectors.calculateSize(g.tracks, g.heads, g.sectors, g.sectorSize);
return g;
}
void readSectorsFromFile(SectorSet& sectors, const Geometry& geometry,
const std::string& filename)
{
std::ifstream inputFile(filename, std::ios::in | std::ios::binary);
std::ifstream inputFile(spec.filename, std::ios::in | std::ios::binary);
if (!inputFile.is_open())
Error() << "cannot open input file";
size_t headSize = geometry.sectors * geometry.sectorSize;
size_t trackSize = headSize * geometry.heads;
size_t headSize = spec.sectors * spec.bytes;
size_t trackSize = headSize * spec.heads;
std::cout << fmt::format("{} tracks, {} heads, {} sectors, {} bytes per sector, {} kB total",
geometry.tracks, geometry.heads,
geometry.sectors, geometry.sectorSize,
geometry.tracks * trackSize / 1024)
spec.cylinders, spec.heads,
spec.sectors, spec.bytes,
spec.cylinders * trackSize / 1024)
<< std::endl;
for (int track = 0; track < geometry.tracks; track++)
for (int track = 0; track < spec.cylinders; track++)
{
for (int head = 0; head < geometry.heads; head++)
for (int head = 0; head < spec.heads; head++)
{
for (int sectorId = 0; sectorId < geometry.sectors; sectorId++)
for (int sectorId = 0; sectorId < spec.sectors; sectorId++)
{
inputFile.seekg(track*trackSize + head*headSize + sectorId*geometry.sectorSize, std::ios::beg);
inputFile.seekg(track*trackSize + head*headSize + sectorId*spec.bytes, std::ios::beg);
Bytes data(geometry.sectorSize);
inputFile.read((char*) data.begin(), geometry.sectorSize);
Bytes data(spec.bytes);
inputFile.read((char*) data.begin(), spec.bytes);
std::unique_ptr<Sector>& sector = sectors.get(track, head, sectorId);
sector.reset(new Sector);
@@ -53,21 +47,30 @@ void readSectorsFromFile(SectorSet& sectors, const Geometry& geometry,
}
}
void writeSectorsToFile(const SectorSet& sectors, const Geometry& geometry,
const std::string& filename)
void writeSectorsToFile(const SectorSet& sectors, const ImageSpec& spec)
{
unsigned numCylinders = spec.cylinders;
unsigned numHeads = spec.heads;
unsigned numSectors = spec.sectors;
unsigned numBytes = spec.bytes;
if (!spec.initialised)
{
sectors.calculateSize(numCylinders, numHeads, numSectors, numBytes);
std::cout << "Autodetecting output geometry\n";
}
/* Emit the map. */
int badSectors = 0;
int missingSectors = 0;
int totalSectors = 0;
std::cout << "H.SS Tracks --->" << std::endl;
for (int head = 0; head < geometry.heads; head++)
for (int head = 0; head < numHeads; head++)
{
for (int sectorId = 0; sectorId < geometry.sectors; sectorId++)
for (int sectorId = 0; sectorId < numSectors; sectorId++)
{
std::cout << fmt::format("{}.{:2} ", head, sectorId);
for (int track = 0; track < geometry.tracks; track++)
for (int track = 0; track < numCylinders; track++)
{
Sector* sector = sectors.get(track, head, sectorId);
if (!sector)
@@ -119,29 +122,29 @@ void writeSectorsToFile(const SectorSet& sectors, const Geometry& geometry,
<< std::endl;
}
size_t headSize = geometry.sectors * geometry.sectorSize;
size_t trackSize = headSize * geometry.heads;
size_t headSize = numSectors * numBytes;
size_t trackSize = headSize * numHeads;
std::cout << fmt::format("{} tracks, {} heads, {} sectors, {} bytes per sector, {} kB total",
geometry.tracks, geometry.heads,
geometry.sectors, geometry.sectorSize,
geometry.tracks * trackSize / 1024)
numCylinders, numHeads,
numSectors, numBytes,
numCylinders * trackSize / 1024)
<< std::endl;
std::ofstream outputFile(filename, std::ios::out | std::ios::binary);
std::ofstream outputFile(spec.filename, std::ios::out | std::ios::binary);
if (!outputFile.is_open())
Error() << "cannot open output file";
for (int track = 0; track < geometry.tracks; track++)
for (int track = 0; track < numCylinders; track++)
{
for (int head = 0; head < geometry.heads; head++)
for (int head = 0; head < numHeads; head++)
{
for (int sectorId = 0; sectorId < geometry.sectors; sectorId++)
for (int sectorId = 0; sectorId < numSectors; sectorId++)
{
auto sector = sectors.get(track, head, sectorId);
if (sector)
{
outputFile.seekp(sector->logicalTrack*trackSize + sector->logicalSide*headSize + sector->logicalSector*geometry.sectorSize, std::ios::beg);
outputFile.seekp(sector->logicalTrack*trackSize + sector->logicalSide*headSize + sector->logicalSector*numBytes, std::ios::beg);
outputFile.write((const char*) sector->data.cbegin(), sector->data.size());
}
}

View File

@@ -2,26 +2,14 @@
#define IMAGE_H
class SectorSet;
class Geometry
{
public:
int tracks;
int heads;
int sectors;
int sectorSize;
};
extern Geometry guessGeometry(const SectorSet& sectors);
class ImageSpec;
extern void readSectorsFromFile(
SectorSet& sectors,
const Geometry& geometry,
const std::string& filename);
const ImageSpec& filename);
extern void writeSectorsToFile(
const SectorSet& sectors,
const Geometry& geometry,
const std::string& filename);
const ImageSpec& filename);
#endif

View File

@@ -23,6 +23,11 @@ static DataSpecFlag source(
"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",
@@ -52,6 +57,11 @@ void setReaderDefaultSource(const std::string& source)
::source.set(source);
}
void setReaderDefaultOutput(const std::string& output)
{
::output.set(output);
}
void setReaderRevolutions(int revolutions)
{
setHardwareFluxSourceRevolutions(revolutions);
@@ -140,8 +150,10 @@ static void replace_sector(std::unique_ptr<Sector>& replacing, Sector& replaceme
}
}
void readDiskCommand(AbstractDecoder& decoder, const std::string& outputFilename)
void readDiskCommand(AbstractDecoder& decoder)
{
const ImageSpec outputSpec(output);
bool failures = false;
SectorSet allSectors;
auto tracks = readTracks();
@@ -239,8 +251,7 @@ void readDiskCommand(AbstractDecoder& decoder, const std::string& outputFilename
std::cout << size << " bytes decoded." << std::endl;
}
Geometry geometry = guessGeometry(allSectors);
writeSectorsToFile(allSectors, geometry, outputFilename);
writeSectorsToFile(allSectors, outputSpec);
if (failures)
std::cerr << "Warning: some sectors could not be decoded." << std::endl;
}

View File

@@ -11,10 +11,11 @@ class Track;
extern FlagGroup readerFlags;
extern void setReaderDefaultSource(const std::string& source);
extern void setReaderDefaultOutput(const std::string& output);
extern void setReaderRevolutions(int revolutions);
extern std::vector<std::unique_ptr<Track>> readTracks();
extern void readDiskCommand(AbstractDecoder& decoder, const std::string& outputFilename);
extern void readDiskCommand(AbstractDecoder& decoder);
#endif

View File

@@ -18,8 +18,9 @@ Sector* SectorSet::get(int track, int head, int sector) const
return i->second.get();
}
void SectorSet::calculateSize(int& numTracks, int& numHeads, int& numSectors,
int& sectorSize) const
void SectorSet::calculateSize(
unsigned& numTracks, unsigned& numHeads,
unsigned& numSectors, unsigned& sectorSize) const
{
numTracks = numHeads = numSectors = sectorSize = 0;
@@ -28,10 +29,10 @@ void SectorSet::calculateSize(int& numTracks, int& numHeads, int& numSectors,
auto& sector = i.second;
if (sector)
{
numTracks = std::max(numTracks, sector->logicalTrack+1);
numHeads = std::max(numHeads, sector->logicalSide+1);
numSectors = std::max(numSectors, sector->logicalSector+1);
sectorSize = std::max(sectorSize, (int)sector->data.size());
numTracks = std::max(numTracks, (unsigned)sector->logicalTrack+1);
numHeads = std::max(numHeads, (unsigned)sector->logicalSide+1);
numSectors = std::max(numSectors, (unsigned)sector->logicalSector+1);
sectorSize = std::max(sectorSize, (unsigned)sector->data.size());
}
}
}

View File

@@ -17,8 +17,9 @@ public:
std::unique_ptr<Sector>& get(int track, int head, int sector);
Sector* get(int track, int head, int sector) const;
void calculateSize(int& numTracks, int& numHeads, int& numSectors,
int& sectorSize) const;
void calculateSize(
unsigned& numTracks, unsigned& numHeads, unsigned& numSectors,
unsigned& sectorSize) const;
private:
std::map<const key_t, std::unique_ptr<Sector>> _data;

View File

@@ -22,6 +22,11 @@ static DataSpecFlag dest(
"destination for data",
":d=0:t=0-79:s=0-1");
static DataSpecFlag input(
{ "--input", "-i" },
"input image file to read from",
"");
static SettableFlag highDensityFlag(
{ "--high-density", "-H" },
"set the drive to high density mode");
@@ -33,6 +38,11 @@ void setWriterDefaultDest(const std::string& dest)
::dest.set(dest);
}
void setWriterDefaultInput(const std::string& input)
{
::input.set(input);
}
void writeTracks(
const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
{
@@ -103,12 +113,12 @@ void fillBitmapTo(std::vector<bool>& bitmap,
}
}
void writeDiskCommand(
AbstractEncoder& encoder, const Geometry& geometry, const std::string& inputFilename)
void writeDiskCommand(AbstractEncoder& encoder)
{
SectorSet allSectors;
readSectorsFromFile(allSectors, geometry, inputFilename);
const ImageSpec spec(input);
readSectorsFromFile(allSectors, spec);
writeTracks(
[&](int track, int side) -> std::unique_ptr<Fluxmap>
{

View File

@@ -10,6 +10,7 @@ class AbstractEncoder;
class Geometry;
extern void setWriterDefaultDest(const std::string& dest);
extern void setWriterDefaultInput(const std::string& input);
extern void writeTracks(const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer);
@@ -17,7 +18,6 @@ extern void fillBitmapTo(std::vector<bool>& bitmap,
unsigned& cursor, unsigned terminateAt,
const std::vector<bool>& pattern);
extern void writeDiskCommand(
AbstractEncoder& encoder, const Geometry& geometry, const std::string& inputFilename);
extern void writeDiskCommand(AbstractEncoder& encoder);
#endif

View File

@@ -12,11 +12,6 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"adfs.img");
static IntFlag sectorIdBase(
{ "--sector-id-base" },
"Sector ID of the first sector.",
@@ -25,10 +20,11 @@ static IntFlag sectorIdBase(
int mainReadADFS(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0-1");
setReaderDefaultOutput("adfs.img");
flags.parseFlags(argc, argv);
IbmDecoder decoder(sectorIdBase);
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -20,11 +20,12 @@ static StringFlag outputFilename(
int mainReadAESLanier(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0");
setReaderDefaultOutput("aeslanier.img");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
AesLanierDecoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -13,19 +13,15 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"amiga.adf");
int mainReadAmiga(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0-1");
setReaderDefaultOutput("amiga.adf");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
AmigaDecoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -12,11 +12,6 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"ampro.img");
static IntFlag sectorIdBase(
{ "--sector-id-base" },
"Sector ID of the first sector.",
@@ -25,11 +20,12 @@ static IntFlag sectorIdBase(
int mainReadAmpro(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0");
setReaderDefaultOutput("ampro.adf");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
IbmDecoder decoder(sectorIdBase);
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -13,19 +13,15 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"apple2.img");
int mainReadApple2(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0");
setReaderDefaultOutput("apple2.adf");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
Apple2Decoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -14,19 +14,15 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"brother.img");
int mainReadBrother(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-81:s=0");
setReaderDefaultOutput("brother.img");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
BrotherDecoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -13,19 +13,15 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"c64.img");
int mainReadC64(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79x2:s=0");
setReaderDefaultOutput("c64.img");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
Commodore64Decoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -12,11 +12,6 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"dfs.img");
static IntFlag sectorIdBase(
{ "--sector-id-base" },
"Sector ID of the first sector.",
@@ -25,11 +20,12 @@ static IntFlag sectorIdBase(
int mainReadDFS(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0");
setReaderDefaultOutput("dfs.img");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
IbmDecoder decoder(sectorIdBase);
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -13,19 +13,15 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"f85.img");
int mainReadF85(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0");
setReaderDefaultOutput("f85.img");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
DurangoF85Decoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -12,19 +12,15 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"fb100.img");
int mainReadFB100(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79x2:s=0");
setReaderDefaultOutput("fb100.img");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
Fb100Decoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -12,11 +12,6 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"ibm.img");
static IntFlag sectorIdBase(
{ "--sector-id-base" },
"Sector ID of the first sector.",
@@ -25,10 +20,11 @@ static IntFlag sectorIdBase(
int mainReadIBM(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0-1");
setReaderDefaultOutput("ibm.img");
flags.parseFlags(argc, argv);
IbmDecoder decoder(sectorIdBase);
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -13,19 +13,15 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"mac.img");
int mainReadMac(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0-1");
setReaderDefaultOutput("mac.img");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
MacintoshDecoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -12,18 +12,14 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"mx.img");
int mainReadMx(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0-1");
setReaderDefaultOutput("mx.img");
flags.parseFlags(argc, argv);
MxDecoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -13,19 +13,15 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"victor9k.img");
int mainReadVictor9K(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79:s=0");
setReaderDefaultOutput("victor9k.img");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
Victor9kDecoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -12,19 +12,15 @@
static FlagGroup flags { &readerFlags };
static StringFlag outputFilename(
{ "--output", "-o" },
"The output image file to write to.",
"zilogmcz.img");
int mainReadZilogMCZ(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-76:s=0");
setReaderDefaultOutput("zilogmcz.img");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);
ZilogMczDecoder decoder;
readDiskCommand(decoder, outputFilename);
readDiskCommand(decoder);
return 0;
}

View File

@@ -10,19 +10,14 @@
static FlagGroup flags { &writerFlags, &brotherEncoderFlags };
static StringFlag inputFilename(
{ "--input", "-i" },
"The input image file to read from.",
"brother.img");
int mainWriteBrother(int argc, const char* argv[])
{
setWriterDefaultInput(":c=78:h=1:s=12:b=256");
setWriterDefaultDest(":d=0:t=0-77:s=0");
flags.parseFlags(argc, argv);
BrotherEncoder encoder;
Geometry geometry = {78, 1, 12, 256};
writeDiskCommand(encoder, geometry, inputFilename);
writeDiskCommand(encoder);
return 0;
}

View File

@@ -89,14 +89,15 @@ static void test_fluxspec(void)
static void test_imagespec(void)
{
DataSpec spec("foo:t=9:h=2:s=99");
DataSpec spec("foo:c=9:h=2:s=99:b=256");
{
ImageSpec ispec(spec);
assert(ispec.filename == "foo");
assert(ispec.tracks == 9);
assert(ispec.cylinders == 9);
assert(ispec.heads == 2);
assert(ispec.sectors == 99);
assert(ispec.bytes = 256);
}
}