mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Merge from master.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
70
doc/using.md
70
doc/using.md
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
15
lib/flaggroups/fluxsourcesink.cc
Normal file
15
lib/flaggroups/fluxsourcesink.cc
Normal 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");
|
||||||
|
|
||||||
|
|
||||||
13
lib/flaggroups/fluxsourcesink.h
Normal file
13
lib/flaggroups/fluxsourcesink.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef FLUXSOURCESINK_H
|
||||||
|
#define FLUXSOURCESINK_H
|
||||||
|
|
||||||
|
#include "flags.h"
|
||||||
|
|
||||||
|
extern FlagGroup fluxSourceSinkFlags;
|
||||||
|
|
||||||
|
extern SettableFlag fluxSourceSinkFortyTrack;
|
||||||
|
extern SettableFlag fluxSourceSinkHighDensity;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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,7 +51,14 @@ 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);
|
||||||
|
if (fluxSourceSinkFortyTrack)
|
||||||
|
{
|
||||||
|
if (track & 1)
|
||||||
|
Error() << "cannot write to odd physical tracks in 40-track mode";
|
||||||
|
usbSeek(track / 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
usbSeek(track);
|
usbSeek(track);
|
||||||
|
|
||||||
return usbWrite(side, fluxmap.rawBytes(), _hardSectorThreshold);
|
return usbWrite(side, fluxmap.rawBytes(), _hardSectorThreshold);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
if (fluxSourceSinkFortyTrack)
|
||||||
|
{
|
||||||
|
if (track & 1)
|
||||||
|
Error() << "cannot read from odd physical tracks in 40-track mode";
|
||||||
|
usbSeek(track / 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
usbSeek(track);
|
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>();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,10 +64,14 @@ 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fluxmap.reset(new Fluxmap());
|
||||||
|
fluxSink->writeFlux(location.track, location.side, *fluxmap);
|
||||||
|
std::cout << "erased\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Precompensation actually seems to make things worse, so let's leave
|
/* Precompensation actually seems to make things worse, so let's leave
|
||||||
* it disabled for now. */
|
* it disabled for now. */
|
||||||
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
|
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
|
||||||
@@ -82,6 +79,7 @@ void writeTracks(
|
|||||||
std::cout << fmt::format(
|
std::cout << fmt::format(
|
||||||
"{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl;
|
"{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillBitmapTo(std::vector<bool>& bitmap,
|
void fillBitmapTo(std::vector<bool>& bitmap,
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
if (fluxSourceSinkFortyTrack)
|
||||||
|
{
|
||||||
|
if (track & 1)
|
||||||
|
Error() << "you can only seek to even tracks on a 40-track drive";
|
||||||
|
usbSeek(track / 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
usbSeek(track);
|
usbSeek(track);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user