Merge from master.

This commit is contained in:
David Given
2021-05-07 22:27:45 +02:00
20 changed files with 202 additions and 73 deletions

View File

@@ -149,7 +149,10 @@ std::unique_ptr<Fluxmap> IbmEncoder::encode(
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId); const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
if (!sectorData) if (!sectorData)
Error() << fmt::format("format tried to find sector {} which wasn't in the input file", sectorId); {
/* If there are any missing sectors, this is an empty track. */
return std::unique_ptr<Fluxmap>();
}
/* Writing the sector and data records are fantastically annoying. /* Writing the sector and data records are fantastically annoying.
* The CRC is calculated from the *very start* of the record, and * The CRC is calculated from the *very start* of the record, and

View File

@@ -46,6 +46,10 @@ You should end up with a `brother.img` which is 239616 bytes long.
Writing disks Writing disks
------------- -------------
Only 240kB disks can be written, currently ( [get in
touch](https://github.com/davidgiven/fluxengine/issues/new) if you want to
write 120kB disks).
Just do: Just do:
``` ```

View File

@@ -49,6 +49,34 @@ You _can_ work with more than one FluxEngine at the same time, using different
invocations of the client; but be careful of USB bandwidth. If the devices are invocations of the client; but be careful of USB bandwidth. If the devices are
connected via the same hub, the bandwidth will be shared. connected via the same hub, the bandwidth will be shared.
### Logical and physical tracks
In general, FluxEngine will read one track off disk, and write it to one track
in a file, or vice versa. Sometimes these don't match. Two important FluxEngine
concepts are that of the _physical track_ and the _logical track_.
_Physical tracks_ are how FluxEngine locates tracks on the disk. The numbering
used by 80-track drives is always used, even if you actually have a 40-track
drive attached (this actually makes things simpler).
_Logical tracks_ are where the data is in the filesystem. This doesn't need to
match the physical track. The logical track number is usually encoded on the
disk itself in the sector header. FluxEngine uses this for placing the data in
the output file.
The most common situation where these won't match is when you have a 40-track
disk in an 80-track drive. Because each 40-track track is twice the width of an
80-track track, you'll see logical track 0 on physical tracks 0 and 1, and
logical track 1 on physical tracks 2 and 3, and logical track 2 on physical
tracks 4 and 5, etc.
When reading from a disk, this will usually take care of itself as disks are
mostly self-describing --- FluxEngine can tell which logical track data is
located at from the sector header. However, when writing to a disk, this isn't
the case, and you may to supply extra parameters to tell FluxEngine the mapping
from data in the image to physical tracks. This is most likely to happen when
using 40-track disks.
### Source and destination specifiers ### Source and destination specifiers
When reading from or writing _flux_ (either from or to a real disk, or a flux When reading from or writing _flux_ (either from or to a real disk, or a flux
@@ -78,11 +106,11 @@ fluxengine read ibm -s fakedisk.flux:t=0-79:s=0
`some/files/:t=0-10`. There must be a files for a single disk only `some/files/:t=0-10`. There must be a files for a single disk only
in the directory. in the directory.
Source and destination specifiers work entirely in *physical units*. Source and destination specifiers work entirely in *physical units*. As
FluxEngine is intended to be connected to an 80 (or 82) track double sided described above, FluxEngine is intended to be connected to an 80 (or 82) track
drive, and these are the units used. If the format you're trying to access double sided drive, and these are the units used. If the format you're trying
lays out its tracks differently, then you'll need a specifier which tells to access lays out its tracks differently, then you'll need a specifier which
FluxEngine how to find those tracks. See the 40-track disk example above. tells FluxEngine how to find those tracks. See the 40-track disk example above.
If you _don't_ specify a modifier, you'll get the default, which should be If you _don't_ specify a modifier, you'll get the default, which should be
sensible for the command you're using. sensible for the command you're using.
@@ -104,6 +132,11 @@ exact format varies according to the extension:
geometry will be autodetected if left unspecified. For input files you geometry will be autodetected if left unspecified. For input files you
normally have to specify it. normally have to specify it.
If one logical track does not map directly onto on physical track, you can
change this with `:o=1:t=2`: `o` specifies the offset, and `t` specifies
the step. So, with this format, cylinder 1 in the image will be written to
track 3 on the disk.
- `.ldbs`: John Elliott's [LDBS disk image - `.ldbs`: John Elliott's [LDBS disk image
format](http://www.seasip.info/Unix/LibDsk/ldbs.html), which is format](http://www.seasip.info/Unix/LibDsk/ldbs.html), which is
consumable by the [libdsk](http://www.seasip.info/Unix/LibDsk/) suite of consumable by the [libdsk](http://www.seasip.info/Unix/LibDsk/) suite of
@@ -152,7 +185,7 @@ disks, and have different magnetic properties. 3.5" drives can usually
autodetect what kind of medium is inserted into the drive based on the hole autodetect what kind of medium is inserted into the drive based on the hole
in the disk casing, but 5.25" drives can't. As a result, you need to in the disk casing, but 5.25" drives can't. As a result, you need to
explicitly tell FluxEngine on the command line whether you're using a high explicitly tell FluxEngine on the command line whether you're using a high
density disk or not with the `--hd` flag. density disk or not with the `-H` flag.
**If you don't do this, your disks may not read correctly and will _certainly_ **If you don't do this, your disks may not read correctly and will _certainly_
fail to write correctly.** fail to write correctly.**
@@ -164,6 +197,31 @@ case, and reading the disk label is much more reliable.
[Lots more information on high density vs double density disks can be found [Lots more information on high density vs double density disks can be found
here.](http://www.retrotechnology.com/herbs_stuff/guzis.html) here.](http://www.retrotechnology.com/herbs_stuff/guzis.html)
### 40-track disks and drives
These require special handling.
- reading a 40-track disk from an 80-track drive: everything should just work
via autodetection.
- writing a 40-track disk to an 80-track drive: you want to write _all
physical tracks_, so `-d :t=0-79`. For `.img` files you will also need `-i
:t=2` to set the mapping between logical tracks in the image and physical
tracks on the disk.
- reading a 40-track disk from a 40-track drive: use `--40-track` to tell
FluxEngine you have a 40-track drive; everything should just work via
autodetection.
- writing a 40-track disk to a 40-track drive: you want to write _even tracks
only_, so `-d :t=0-79x2`, and for `.img` files you will also need `-i
:t=2`.
The `--40-track` or `-4` option tells FluxEngine that it's plugged into a
40-track drive. It will assume that each step of the drive corresponds to two
physical tracks. Only even tracks are accessible in this mode.
### Other important flags ### Other important flags
These flags apply to many operations and are useful for modifying the overall These flags apply to many operations and are useful for modifying the overall

View File

@@ -162,6 +162,8 @@ ImageSpec::ImageSpec(const DataSpec& spec)
if (!spec.has("c") && !spec.has("h") && !spec.has("s") && !spec.has("b")) if (!spec.has("c") && !spec.has("h") && !spec.has("s") && !spec.has("b"))
{ {
cylinders = heads = sectors = bytes = 0; cylinders = heads = sectors = bytes = 0;
physicalOffset = 0;
physicalStep = 1;
initialised = false; initialised = false;
} }
else else
@@ -170,6 +172,8 @@ ImageSpec::ImageSpec(const DataSpec& spec)
heads = spec.at("h").only(); heads = spec.at("h").only();
sectors = spec.at("s").only(); sectors = spec.at("s").only();
bytes = spec.at("b").only(); bytes = spec.at("b").only();
physicalOffset = spec.atOr("o", 0);
physicalStep = spec.atOr("t", 1);
initialised = true; initialised = true;
} }
} }
@@ -181,18 +185,22 @@ ImageSpec::ImageSpec(const DataSpec& spec)
for (const auto& e : spec.modifiers) for (const auto& e : spec.modifiers)
{ {
const auto name = e.second.name; const auto name = e.second.name;
if ((name != "c") && (name != "h") && (name != "s") && (name != "b")) static const std::set<std::string> modifiers { "c", "h", "s", "b", "o", "t" };
Error() << fmt::format("unknown fluxspec modifier '{}'", name); if (modifiers.find(name) == modifiers.end())
Error() << fmt::format("unknown imagespec modifier '{}'", name);
} }
} }
ImageSpec::ImageSpec(const std::string filename, ImageSpec::ImageSpec(const std::string filename,
unsigned cylinders, unsigned heads, unsigned sectors, unsigned bytes): unsigned cylinders, unsigned heads, unsigned sectors, unsigned bytes,
int physicalOffset, int physicalStep):
filename(filename), filename(filename),
cylinders(cylinders), cylinders(cylinders),
heads(heads), heads(heads),
sectors(sectors), sectors(sectors),
bytes(bytes), bytes(bytes),
physicalOffset(physicalOffset),
physicalStep(physicalStep),
initialised(true) initialised(true)
{} {}

View File

@@ -48,6 +48,9 @@ public:
const Modifier& at(const std::string& mod) const; const Modifier& at(const std::string& mod) const;
bool has(const std::string& mod) const; bool has(const std::string& mod) const;
unsigned atOr(const std::string& mod, unsigned value) const
{ return has(mod) ? at(mod).only() : value; }
std::string filename; std::string filename;
std::map<std::string, Modifier> modifiers; std::map<std::string, Modifier> modifiers;
}; };
@@ -82,7 +85,8 @@ class ImageSpec
public: public:
ImageSpec(const DataSpec& dataspec); ImageSpec(const DataSpec& dataspec);
ImageSpec(const std::string filename, ImageSpec(const std::string filename,
unsigned cylinders, unsigned heads, unsigned sectors, unsigned bytes); unsigned cylinders, unsigned heads, unsigned sectors, unsigned bytes,
int physicalOffset=0, int physicalStep=1);
public: public:
std::string filename; std::string filename;
@@ -90,6 +94,8 @@ public:
unsigned heads; unsigned heads;
unsigned sectors; unsigned sectors;
unsigned bytes; unsigned bytes;
int physicalOffset;
int physicalStep;
bool initialised : 1; bool initialised : 1;
}; };

View File

@@ -0,0 +1,15 @@
#include "globals.h"
#include "flags.h"
#include "flaggroups/fluxsourcesink.h"
FlagGroup fluxSourceSinkFlags;
SettableFlag fluxSourceSinkFortyTrack(
{ "--40-track", "-4" },
"indicates a 40 track drive");
SettableFlag fluxSourceSinkHighDensity(
{ "--high-density", "-H" },
"set the drive to high density mode");

View File

@@ -0,0 +1,13 @@
#ifndef FLUXSOURCESINK_H
#define FLUXSOURCESINK_H
#include "flags.h"
extern FlagGroup fluxSourceSinkFlags;
extern SettableFlag fluxSourceSinkFortyTrack;
extern SettableFlag fluxSourceSinkHighDensity;
#endif

View File

@@ -23,7 +23,6 @@ public:
virtual void writeFlux(int track, int side, Fluxmap& fluxmap) = 0; virtual void writeFlux(int track, int side, Fluxmap& fluxmap) = 0;
}; };
extern void setHardwareFluxSinkDensity(bool high_density);
extern void setHardwareFluxSinkHardSectorCount(int sectorCount); extern void setHardwareFluxSinkHardSectorCount(int sectorCount);
#endif #endif

View File

@@ -3,14 +3,14 @@
#include "fluxmap.h" #include "fluxmap.h"
#include "usb/usb.h" #include "usb/usb.h"
#include "fluxsink/fluxsink.h" #include "fluxsink/fluxsink.h"
#include "flaggroups/fluxsourcesink.h"
#include "fmt/format.h" #include "fmt/format.h"
FlagGroup hardwareFluxSinkFlags = { FlagGroup hardwareFluxSinkFlags = {
&fluxSourceSinkFlags,
&usbFlags, &usbFlags,
}; };
static bool high_density = false;
static IntFlag indexMode( static IntFlag indexMode(
{ "--write-index-mode" }, { "--write-index-mode" },
"index pulse source (0=drive, 1=300 RPM fake source, 2=360 RPM fake source", "index pulse source (0=drive, 1=300 RPM fake source, 2=360 RPM fake source",
@@ -21,11 +21,6 @@ static IntFlag hardSectorCount(
"number of hard sectors on the disk (0=soft sectors)", "number of hard sectors on the disk (0=soft sectors)",
0); 0);
void setHardwareFluxSinkDensity(bool high_density)
{
::high_density = high_density;
}
void setHardwareFluxSinkHardSectorCount(int sectorCount) void setHardwareFluxSinkHardSectorCount(int sectorCount)
{ {
::hardSectorCount.setDefaultValue(sectorCount); ::hardSectorCount.setDefaultValue(sectorCount);
@@ -39,7 +34,7 @@ public:
{ {
if (hardSectorCount != 0) if (hardSectorCount != 0)
{ {
usbSetDrive(_drive, high_density, indexMode); usbSetDrive(_drive, fluxSourceSinkHighDensity, indexMode);
std::cerr << "Measuring rotational speed... " << std::flush; std::cerr << "Measuring rotational speed... " << std::flush;
nanoseconds_t oneRevolution = usbGetRotationalPeriod(hardSectorCount); nanoseconds_t oneRevolution = usbGetRotationalPeriod(hardSectorCount);
_hardSectorThreshold = oneRevolution * 3 / (4 * hardSectorCount); _hardSectorThreshold = oneRevolution * 3 / (4 * hardSectorCount);
@@ -56,8 +51,15 @@ public:
public: public:
void writeFlux(int track, int side, Fluxmap& fluxmap) void writeFlux(int track, int side, Fluxmap& fluxmap)
{ {
usbSetDrive(_drive, high_density, indexMode); usbSetDrive(_drive, fluxSourceSinkHighDensity, indexMode);
usbSeek(track); if (fluxSourceSinkFortyTrack)
{
if (track & 1)
Error() << "cannot write to odd physical tracks in 40-track mode";
usbSeek(track / 2);
}
else
usbSeek(track);
return usbWrite(side, fluxmap.rawBytes(), _hardSectorThreshold); return usbWrite(side, fluxmap.rawBytes(), _hardSectorThreshold);
} }

View File

@@ -28,7 +28,6 @@ public:
}; };
extern void setHardwareFluxSourceRevolutions(double revolutions); extern void setHardwareFluxSourceRevolutions(double revolutions);
extern void setHardwareFluxSourceDensity(bool high_density);
extern void setHardwareFluxSourceSynced(bool synced); extern void setHardwareFluxSourceSynced(bool synced);
extern void setHardwareFluxSourceHardSectorCount(int sectorCount); extern void setHardwareFluxSourceHardSectorCount(int sectorCount);

View File

@@ -3,9 +3,11 @@
#include "fluxmap.h" #include "fluxmap.h"
#include "usb/usb.h" #include "usb/usb.h"
#include "fluxsource/fluxsource.h" #include "fluxsource/fluxsource.h"
#include "flaggroups/fluxsourcesink.h"
#include "fmt/format.h" #include "fmt/format.h"
FlagGroup hardwareFluxSourceFlags = { FlagGroup hardwareFluxSourceFlags = {
&fluxSourceSinkFlags,
&usbFlags &usbFlags
}; };
@@ -29,20 +31,13 @@ static IntFlag hardSectorCount(
"number of hard sectors on the disk (0=soft sectors)", "number of hard sectors on the disk (0=soft sectors)",
0); 0);
static bool high_density = false;
void setHardwareFluxSourceDensity(bool high_density)
{
::high_density = high_density;
}
class HardwareFluxSource : public FluxSource class HardwareFluxSource : public FluxSource
{ {
public: public:
HardwareFluxSource(unsigned drive): HardwareFluxSource(unsigned drive):
_drive(drive) _drive(drive)
{ {
usbSetDrive(_drive, high_density, indexMode); usbSetDrive(_drive, fluxSourceSinkHighDensity, indexMode);
std::cerr << "Measuring rotational speed... " << std::flush; std::cerr << "Measuring rotational speed... " << std::flush;
_oneRevolution = usbGetRotationalPeriod(hardSectorCount); _oneRevolution = usbGetRotationalPeriod(hardSectorCount);
if (hardSectorCount != 0) if (hardSectorCount != 0)
@@ -59,8 +54,16 @@ public:
public: public:
std::unique_ptr<Fluxmap> readFlux(int track, int side) std::unique_ptr<Fluxmap> readFlux(int track, int side)
{ {
usbSetDrive(_drive, high_density, indexMode); usbSetDrive(_drive, fluxSourceSinkHighDensity, indexMode);
usbSeek(track); if (fluxSourceSinkFortyTrack)
{
if (track & 1)
Error() << "cannot read from odd physical tracks in 40-track mode";
usbSeek(track / 2);
}
else
usbSeek(track);
Bytes data = usbRead( Bytes data = usbRead(
side, synced, revolutions * _oneRevolution, _hardSectorThreshold); side, synced, revolutions * _oneRevolution, _hardSectorThreshold);
auto fluxmap = std::make_unique<Fluxmap>(); auto fluxmap = std::make_unique<Fluxmap>();

View File

@@ -30,6 +30,9 @@ public:
spec.sectors, spec.bytes, spec.sectors, spec.bytes,
spec.cylinders * trackSize / 1024) spec.cylinders * trackSize / 1024)
<< std::endl; << std::endl;
if ((spec.physicalOffset != 0) || (spec.physicalStep != 1))
std::cout << fmt::format("logical to physical track mapping: physical = logical*{} + {}\n",
spec.physicalStep, spec.physicalOffset);
SectorSet sectors; SectorSet sectors;
for (int track = 0; track < spec.cylinders; track++) for (int track = 0; track < spec.cylinders; track++)
@@ -43,10 +46,12 @@ public:
Bytes data(spec.bytes); Bytes data(spec.bytes);
inputFile.read((char*) data.begin(), spec.bytes); inputFile.read((char*) data.begin(), spec.bytes);
std::unique_ptr<Sector>& sector = sectors.get(track, head, sectorId); int physicalTrack = track*spec.physicalStep + spec.physicalOffset;
std::unique_ptr<Sector>& sector = sectors.get(physicalTrack, head, sectorId);
sector.reset(new Sector); sector.reset(new Sector);
sector->status = Sector::OK; sector->status = Sector::OK;
sector->logicalTrack = sector->physicalTrack = track; sector->logicalTrack = track;
sector->physicalTrack = physicalTrack;
sector->logicalSide = sector->physicalSide = head; sector->logicalSide = sector->physicalSide = head;
sector->logicalSector = sectorId; sector->logicalSector = sectorId;
sector->data = data; sector->data = data;

View File

@@ -58,10 +58,6 @@ static IntFlag retries(
"How many times to retry each track in the event of a read failure.", "How many times to retry each track in the event of a read failure.",
5); 5);
static SettableFlag highDensityFlag(
{ "--high-density", "--hd" },
"set the drive to high density mode");
static StringFlag csvFile( static StringFlag csvFile(
{ "--write-csv" }, { "--write-csv" },
"write a CSV report of the disk state", "write a CSV report of the disk state",
@@ -117,8 +113,6 @@ std::vector<std::unique_ptr<Track>> readTracks()
std::cout << "Reading from: " << source << std::endl; std::cout << "Reading from: " << source << std::endl;
setHardwareFluxSourceDensity(highDensityFlag);
if (!destination.get().empty()) if (!destination.get().empty())
{ {
std::cout << "Writing a copy of the flux to " << destination.get() << std::endl; std::cout << "Writing a copy of the flux to " << destination.get() << std::endl;

View File

@@ -27,10 +27,6 @@ static DataSpecFlag input(
"input image file to read from", "input image file to read from",
""); "");
static SettableFlag highDensityFlag(
{ "--high-density", "-H" },
"set the drive to high density mode");
static sqlite3* outdb; static sqlite3* outdb;
void setWriterDefaultDest(const std::string& dest) void setWriterDefaultDest(const std::string& dest)
@@ -60,9 +56,6 @@ void writeTracks(
std::cout << "Writing to: " << dest << std::endl; std::cout << "Writing to: " << dest << std::endl;
setHardwareFluxSourceDensity(highDensityFlag);
setHardwareFluxSinkDensity(highDensityFlag);
std::shared_ptr<FluxSink> fluxSink = FluxSink::create(spec); std::shared_ptr<FluxSink> fluxSink = FluxSink::create(spec);
for (const auto& location : spec.locations) for (const auto& location : spec.locations)
@@ -71,16 +64,21 @@ void writeTracks(
std::unique_ptr<Fluxmap> fluxmap = producer(location.track, location.side); std::unique_ptr<Fluxmap> fluxmap = producer(location.track, location.side);
if (!fluxmap) if (!fluxmap)
{ {
/* Create an empty fluxmap for writing. */ /* Erase this track rather than writing. */
fluxmap.reset(new Fluxmap());
}
/* Precompensation actually seems to make things worse, so let's leave fluxmap.reset(new Fluxmap());
* it disabled for now. */ fluxSink->writeFlux(location.track, location.side, *fluxmap);
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2); std::cout << "erased\n";
fluxSink->writeFlux(location.track, location.side, *fluxmap); }
std::cout << fmt::format( else
"{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl; {
/* Precompensation actually seems to make things worse, so let's leave
* it disabled for now. */
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
fluxSink->writeFlux(location.track, location.side, *fluxmap);
std::cout << fmt::format(
"{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl;
}
} }
} }

View File

@@ -233,6 +233,7 @@ buildlibrary libbackend.a \
lib/decoders/fluxmapreader.cc \ lib/decoders/fluxmapreader.cc \
lib/decoders/fmmfm.cc \ lib/decoders/fmmfm.cc \
lib/encoders/encoders.cc \ lib/encoders/encoders.cc \
lib/flaggroups/fluxsourcesink.cc \
lib/flags.cc \ lib/flags.cc \
lib/fluxmap.cc \ lib/fluxmap.cc \
lib/fluxsink/fluxsink.cc \ lib/fluxsink/fluxsink.cc \

View File

@@ -7,11 +7,13 @@
#include "writer.h" #include "writer.h"
#include "protocol.h" #include "protocol.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "flaggroups/fluxsourcesink.h"
#include "dep/agg/include/agg2d.h" #include "dep/agg/include/agg2d.h"
#include "dep/stb/stb_image_write.h" #include "dep/stb/stb_image_write.h"
#include <fstream> #include <fstream>
static FlagGroup flags = { static FlagGroup flags = {
&fluxSourceSinkFlags,
&usbFlags, &usbFlags,
}; };
@@ -186,8 +188,15 @@ int mainAnalyseDriveResponse(int argc, const char* argv[])
if (spec.locations.size() != 1) if (spec.locations.size() != 1)
Error() << "the destination dataspec must contain exactly one track (two sides count as two tracks)"; Error() << "the destination dataspec must contain exactly one track (two sides count as two tracks)";
usbSetDrive(spec.drive, false, F_INDEX_REAL); usbSetDrive(spec.drive, fluxSourceSinkHighDensity, F_INDEX_REAL);
usbSeek(spec.locations[0].track); int track = spec.locations[0].track;
if (fluxSourceSinkFortyTrack)
{
if (track & 1)
Error() << "you can only seek to even tracks on a 40-track disk";
track /= 2;
}
usbSeek(track);
std::cout << "Measuring rotational speed...\n"; std::cout << "Measuring rotational speed...\n";
nanoseconds_t period = usbGetRotationalPeriod(0); nanoseconds_t period = usbGetRotationalPeriod(0);

View File

@@ -22,10 +22,6 @@ static StringFlag output(
"output AU file to write", "output AU file to write",
"output.au"); "output.au");
static SettableFlag highDensityFlag(
{ "--high-density", "--hd" },
"set the drive to high density mode");
static SettableFlag withIndex( static SettableFlag withIndex(
{ "--with-index" }, { "--with-index" },
"place index markers in the right hand channel"); "place index markers in the right hand channel");
@@ -41,7 +37,6 @@ int mainConvertFluxToAu(int argc, const char* argv[])
const auto& location = *(locations.begin()); const auto& location = *(locations.begin());
std::cerr << "Reading source flux...\n"; std::cerr << "Reading source flux...\n";
setHardwareFluxSourceDensity(highDensityFlag);
std::shared_ptr<FluxSource> fluxsource = FluxSource::create(spec); std::shared_ptr<FluxSource> fluxsource = FluxSource::create(spec);
const auto& fluxmap = fluxsource->readFlux(location.track, location.side); const auto& fluxmap = fluxsource->readFlux(location.track, location.side);
unsigned totalTicks = fluxmap->ticks() + 2; unsigned totalTicks = fluxmap->ticks() + 2;

View File

@@ -22,10 +22,6 @@ static StringFlag output(
"output VCD file to write", "output VCD file to write",
"output.vcd"); "output.vcd");
static SettableFlag highDensityFlag(
{ "--high-density", "--hd" },
"set the drive to high density mode");
int mainConvertFluxToVcd(int argc, const char* argv[]) int mainConvertFluxToVcd(int argc, const char* argv[])
{ {
flags.parseFlags(argc, argv); flags.parseFlags(argc, argv);
@@ -37,7 +33,6 @@ int mainConvertFluxToVcd(int argc, const char* argv[])
const auto& location = *(locations.begin()); const auto& location = *(locations.begin());
std::cerr << "Reading source flux...\n"; std::cerr << "Reading source flux...\n";
setHardwareFluxSourceDensity(highDensityFlag);
std::shared_ptr<FluxSource> fluxsource = FluxSource::create(spec); std::shared_ptr<FluxSource> fluxsource = FluxSource::create(spec);
const auto& fluxmap = fluxsource->readFlux(location.track, location.side); const auto& fluxmap = fluxsource->readFlux(location.track, location.side);

View File

@@ -1,9 +1,11 @@
#include "globals.h" #include "globals.h"
#include "flags.h" #include "flags.h"
#include "usb/usb.h" #include "usb/usb.h"
#include "flaggroups/fluxsourcesink.h"
#include "protocol.h" #include "protocol.h"
static FlagGroup flags = { static FlagGroup flags = {
&fluxSourceSinkFlags,
&usbFlags, &usbFlags,
}; };
@@ -22,6 +24,13 @@ int mainSeek(int argc, const char* argv[])
flags.parseFlags(argc, argv); flags.parseFlags(argc, argv);
usbSetDrive(drive, false, F_INDEX_REAL); usbSetDrive(drive, false, F_INDEX_REAL);
usbSeek(track); if (fluxSourceSinkFortyTrack)
{
if (track & 1)
Error() << "you can only seek to even tracks on a 40-track drive";
usbSeek(track / 2);
}
else
usbSeek(track);
return 0; return 0;
} }

View File

@@ -111,15 +111,28 @@ static void test_fluxspec(void)
static void test_imagespec(void) static void test_imagespec(void)
{ {
DataSpec spec("foo:c=9:h=2:s=99:b=256");
{ {
DataSpec spec("foo:c=9:h=2:s=99:b=256");
ImageSpec ispec(spec); ImageSpec ispec(spec);
assert(ispec.filename == "foo"); assert(ispec.filename == "foo");
assert(ispec.cylinders == 9); assert(ispec.cylinders == 9);
assert(ispec.heads == 2); assert(ispec.heads == 2);
assert(ispec.sectors == 99); assert(ispec.sectors == 99);
assert(ispec.bytes = 256); assert(ispec.bytes == 256);
assert(ispec.physicalOffset == 0);
assert(ispec.physicalStep == 1);
}
{
DataSpec spec("foo:c=9:h=2:s=99:b=256:o=2:t=9");
ImageSpec ispec(spec);
assert(ispec.filename == "foo");
assert(ispec.cylinders == 9);
assert(ispec.heads == 2);
assert(ispec.sectors == 99);
assert(ispec.bytes == 256);
assert(ispec.physicalOffset == 2);
assert(ispec.physicalStep == 9);
} }
} }