mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
The writer now works with the new config system.
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class BrotherInput;
|
||||
class BrotherOutput;
|
||||
|
||||
class BrotherDecoder : public AbstractDecoder
|
||||
{
|
||||
@@ -31,20 +32,17 @@ public:
|
||||
class BrotherEncoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
BrotherEncoder(int format, int bias):
|
||||
_format(format),
|
||||
_bias(bias)
|
||||
BrotherEncoder(const BrotherOutput& config):
|
||||
_config(config)
|
||||
{}
|
||||
|
||||
virtual ~BrotherEncoder() {}
|
||||
|
||||
private:
|
||||
int _format;
|
||||
int _bias;
|
||||
const BrotherOutput& _config;
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
};
|
||||
|
||||
extern FlagGroup brotherEncoderFlags;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,11 +2,19 @@ syntax = "proto2";
|
||||
|
||||
message BrotherInput {}
|
||||
|
||||
enum BrotherFormat {
|
||||
BROTHER240 = 0;
|
||||
BROTHER120 = 1;
|
||||
};
|
||||
|
||||
message BrotherOutput {
|
||||
optional double clock_rate_us = 1 [default = 3.83];
|
||||
optional double post_index_gap_ms = 2 [default = 1.0];
|
||||
optional double sector_spacing_ms = 3 [default = 16.2];
|
||||
optional double post_header_spacing_ms = 4 [default = 0.69];
|
||||
optional string sector_skew = 5 [default = "05a3816b4927"];
|
||||
|
||||
optional BrotherFormat format = 6 [default = BROTHER240];
|
||||
optional int32 bias = 7 [default = 0];
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "crc.h"
|
||||
#include "sectorset.h"
|
||||
#include "writer.h"
|
||||
#include "arch/brother/brother.pb.h"
|
||||
|
||||
FlagGroup brotherEncoderFlags;
|
||||
|
||||
@@ -132,17 +133,17 @@ std::unique_ptr<Fluxmap> BrotherEncoder::encode(
|
||||
int logicalTrack;
|
||||
if (physicalSide != 0)
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
physicalTrack -= _bias;
|
||||
switch (_format)
|
||||
physicalTrack -= _config.bias();
|
||||
switch (_config.format())
|
||||
{
|
||||
case 120:
|
||||
case BROTHER120:
|
||||
if ((physicalTrack < 0) || (physicalTrack >= (BROTHER_TRACKS_PER_120KB_DISK*2))
|
||||
|| (physicalTrack & 1))
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
logicalTrack = physicalTrack/2;
|
||||
break;
|
||||
|
||||
case 240:
|
||||
case BROTHER240:
|
||||
if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_240KB_DISK))
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
logicalTrack = physicalTrack;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "crc.h"
|
||||
#include "sectorset.h"
|
||||
#include "writer.h"
|
||||
#include "arch/ibm/ibm.pb.h"
|
||||
#include "fmt/format.h"
|
||||
#include <ctype.h>
|
||||
|
||||
@@ -78,7 +79,7 @@ void IbmEncoder::writeRawBits(uint32_t data, int width)
|
||||
|
||||
void IbmEncoder::writeBytes(const Bytes& bytes)
|
||||
{
|
||||
if (_parameters.useFm)
|
||||
if (_config.use_fm())
|
||||
encodeFm(_bits, _cursor, bytes);
|
||||
else
|
||||
encodeMfm(_bits, _cursor, bytes, _lastBit);
|
||||
@@ -102,21 +103,21 @@ static uint8_t decodeUint16(uint16_t raw)
|
||||
std::unique_ptr<Fluxmap> IbmEncoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
if (_parameters.swapSides)
|
||||
if (_config.swap_sides())
|
||||
physicalSide = 1 - physicalSide;
|
||||
double clockRateUs = 1e3 / _parameters.clockRateKhz;
|
||||
if (!_parameters.useFm)
|
||||
double clockRateUs = 1e3 / _config.clock_rate_khz();
|
||||
if (!_config.use_fm())
|
||||
clockRateUs /= 2.0;
|
||||
int bitsPerRevolution = (_parameters.trackLengthMs * 1000.0) / clockRateUs;
|
||||
int bitsPerRevolution = (_config.track_length_ms() * 1000.0) / clockRateUs;
|
||||
_bits.resize(bitsPerRevolution);
|
||||
_cursor = 0;
|
||||
|
||||
uint8_t idamUnencoded = decodeUint16(_parameters.idamByte);
|
||||
uint8_t damUnencoded = decodeUint16(_parameters.damByte);
|
||||
uint8_t idamUnencoded = decodeUint16(_config.idam_byte());
|
||||
uint8_t damUnencoded = decodeUint16(_config.dam_byte());
|
||||
|
||||
uint8_t sectorSize = 0;
|
||||
{
|
||||
int s = _parameters.sectorSize >> 7;
|
||||
int s = _config.sector_size() >> 7;
|
||||
while (s > 1)
|
||||
{
|
||||
s >>= 1;
|
||||
@@ -124,27 +125,27 @@ std::unique_ptr<Fluxmap> IbmEncoder::encode(
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t gapFill = _parameters.useFm ? 0x00 : 0x4e;
|
||||
uint8_t gapFill = _config.use_fm() ? 0x00 : 0x4e;
|
||||
|
||||
writeBytes(_parameters.gap0, gapFill);
|
||||
if (_parameters.emitIam)
|
||||
writeBytes(_config.gap0(), gapFill);
|
||||
if (_config.emit_iam())
|
||||
{
|
||||
writeBytes(_parameters.useFm ? 6 : 12, 0x00);
|
||||
if (!_parameters.useFm)
|
||||
writeBytes(_config.use_fm() ? 6 : 12, 0x00);
|
||||
if (!_config.use_fm())
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
writeRawBits(MFM_IAM_SEPARATOR, 16);
|
||||
}
|
||||
writeRawBits(_parameters.useFm ? FM_IAM_RECORD : MFM_IAM_RECORD, 16);
|
||||
writeBytes(_parameters.gap1, gapFill);
|
||||
writeRawBits(_config.use_fm() ? FM_IAM_RECORD : MFM_IAM_RECORD, 16);
|
||||
writeBytes(_config.gap1(), gapFill);
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
for (char sectorChar : _parameters.sectorSkew)
|
||||
for (char sectorChar : _config.sector_skew())
|
||||
{
|
||||
int sectorId = charToInt(sectorChar);
|
||||
if (!first)
|
||||
writeBytes(_parameters.gap3, gapFill);
|
||||
writeBytes(_config.gap3(), gapFill);
|
||||
first = false;
|
||||
|
||||
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
|
||||
@@ -166,8 +167,8 @@ std::unique_ptr<Fluxmap> IbmEncoder::encode(
|
||||
Bytes header;
|
||||
ByteWriter bw(header);
|
||||
|
||||
writeBytes(_parameters.useFm ? 6 : 12, 0x00);
|
||||
if (!_parameters.useFm)
|
||||
writeBytes(_config.use_fm() ? 6 : 12, 0x00);
|
||||
if (!_config.use_fm())
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
bw.write_8(MFM_RECORD_SEPARATOR_BYTE);
|
||||
@@ -175,53 +176,53 @@ std::unique_ptr<Fluxmap> IbmEncoder::encode(
|
||||
bw.write_8(idamUnencoded);
|
||||
bw.write_8(sectorData->logicalTrack);
|
||||
bw.write_8(sectorData->logicalSide);
|
||||
bw.write_8(sectorData->logicalSector + _parameters.startSectorId);
|
||||
bw.write_8(sectorData->logicalSector + _config.start_sector_id());
|
||||
bw.write_8(sectorSize);
|
||||
uint16_t crc = crc16(CCITT_POLY, header);
|
||||
bw.write_be16(crc);
|
||||
|
||||
int conventionalHeaderStart = 0;
|
||||
if (!_parameters.useFm)
|
||||
if (!_config.use_fm())
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
writeRawBits(MFM_RECORD_SEPARATOR, 16);
|
||||
conventionalHeaderStart += 3;
|
||||
|
||||
}
|
||||
writeRawBits(_parameters.idamByte, 16);
|
||||
writeRawBits(_config.idam_byte(), 16);
|
||||
conventionalHeaderStart += 1;
|
||||
|
||||
writeBytes(header.slice(conventionalHeaderStart));
|
||||
}
|
||||
|
||||
writeBytes(_parameters.gap2, gapFill);
|
||||
writeBytes(_config.gap2(), gapFill);
|
||||
|
||||
{
|
||||
Bytes data;
|
||||
ByteWriter bw(data);
|
||||
|
||||
writeBytes(_parameters.useFm ? 6 : 12, 0x00);
|
||||
if (!_parameters.useFm)
|
||||
writeBytes(_config.use_fm() ? 6 : 12, 0x00);
|
||||
if (!_config.use_fm())
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
bw.write_8(MFM_RECORD_SEPARATOR_BYTE);
|
||||
}
|
||||
bw.write_8(damUnencoded);
|
||||
|
||||
Bytes truncatedData = sectorData->data.slice(0, _parameters.sectorSize);
|
||||
Bytes truncatedData = sectorData->data.slice(0, _config.sector_size());
|
||||
bw += truncatedData;
|
||||
uint16_t crc = crc16(CCITT_POLY, data);
|
||||
bw.write_be16(crc);
|
||||
|
||||
int conventionalHeaderStart = 0;
|
||||
if (!_parameters.useFm)
|
||||
if (!_config.use_fm())
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
writeRawBits(MFM_RECORD_SEPARATOR, 16);
|
||||
conventionalHeaderStart += 3;
|
||||
|
||||
}
|
||||
writeRawBits(_parameters.damByte, 16);
|
||||
writeRawBits(_config.dam_byte(), 16);
|
||||
conventionalHeaderStart += 1;
|
||||
|
||||
writeBytes(data.slice(conventionalHeaderStart));
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "encoders/encoders.h"
|
||||
|
||||
class IBMInput;
|
||||
class IBMOutput;
|
||||
|
||||
/* IBM format (i.e. ordinary PC floppies). */
|
||||
|
||||
@@ -50,29 +51,11 @@ private:
|
||||
unsigned _currentHeaderLength;
|
||||
};
|
||||
|
||||
struct IbmParameters
|
||||
{
|
||||
int trackLengthMs;
|
||||
int sectorSize;
|
||||
bool emitIam;
|
||||
int startSectorId;
|
||||
int clockRateKhz;
|
||||
bool useFm;
|
||||
uint16_t idamByte;
|
||||
uint16_t damByte;
|
||||
int gap0;
|
||||
int gap1;
|
||||
int gap2;
|
||||
int gap3;
|
||||
std::string sectorSkew;
|
||||
bool swapSides;
|
||||
};
|
||||
|
||||
class IbmEncoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
IbmEncoder(const IbmParameters& parameters):
|
||||
_parameters(parameters)
|
||||
IbmEncoder(const IBMOutput& config):
|
||||
_config(config)
|
||||
{}
|
||||
|
||||
virtual ~IbmEncoder() {}
|
||||
@@ -87,7 +70,7 @@ private:
|
||||
void writeSync();
|
||||
|
||||
private:
|
||||
IbmParameters _parameters;
|
||||
const IBMOutput& _config;
|
||||
std::vector<bool> _bits;
|
||||
unsigned _cursor;
|
||||
bool _lastBit;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
syntax = "proto2";
|
||||
|
||||
import "lib/range.proto";
|
||||
import "lib/common.proto";
|
||||
|
||||
message IBMInput {
|
||||
optional int32 sector_base = 1 [default=0];
|
||||
@@ -9,24 +9,19 @@ message IBMInput {
|
||||
}
|
||||
|
||||
message IBMOutput {
|
||||
enum FmMfm {
|
||||
USE_MFM = 0;
|
||||
USE_FM = 1;
|
||||
}
|
||||
|
||||
optional double track_length_ms = 1;
|
||||
optional int32 sector_size_bytes = 2;
|
||||
optional bool emit_iam = 3;
|
||||
optional int32 start_sector_id = 4;
|
||||
optional int32 sector_size = 2 [default=512];
|
||||
optional bool emit_iam = 3 [default=true];
|
||||
optional int32 start_sector_id = 4 [default=1];
|
||||
optional double clock_rate_khz = 5;
|
||||
optional FmMfm use_fm = 6 [default = USE_MFM];
|
||||
optional int32 idam_byte = 7;
|
||||
optional int32 dam_byte = 8;
|
||||
optional int32 gap0 = 9;
|
||||
optional int32 gap1 = 10;
|
||||
optional int32 gap2 = 11;
|
||||
optional int32 gap3 = 12;
|
||||
optional bool use_fm = 6 [default=false];
|
||||
optional int32 idam_byte = 7 [default=0x5554];
|
||||
optional int32 dam_byte = 8 [default=0x5545];
|
||||
optional int32 gap0 = 9 [default=80];
|
||||
optional int32 gap1 = 10 [default=50];
|
||||
optional int32 gap2 = 11 [default=22];
|
||||
optional int32 gap3 = 12 [default=80];
|
||||
optional string sector_skew = 13;
|
||||
optional bool swap_sizes = 14;
|
||||
optional bool swap_sides = 14 [default=false];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import "arch/brother/brother.proto";
|
||||
import "arch/ibm/ibm.proto";
|
||||
import "lib/decoders/decoder.proto";
|
||||
import "lib/imagereader/img.proto";
|
||||
import "lib/range.proto";
|
||||
import "lib/common.proto";
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
extend google.protobuf.FieldOptions {
|
||||
@@ -67,6 +67,6 @@ message Config {
|
||||
optional Decoder decoder = 3;
|
||||
|
||||
optional Range cylinders = 4;
|
||||
optional Range sides = 5;
|
||||
optional Range heads = 5;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,23 +2,11 @@
|
||||
#include "flags.h"
|
||||
#include "dataspec.h"
|
||||
#include "fluxsink/fluxsink.h"
|
||||
#include "lib/config.pb.h"
|
||||
|
||||
static bool ends_with(const std::string& value, const std::string& ending)
|
||||
std::unique_ptr<FluxSink> FluxSink::create(const Config_OutputDisk& config)
|
||||
{
|
||||
if (ending.size() > value.size())
|
||||
return false;
|
||||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||
}
|
||||
|
||||
std::unique_ptr<FluxSink> FluxSink::create(const FluxSpec& spec)
|
||||
{
|
||||
const auto& filename = spec.filename;
|
||||
|
||||
if (filename.empty())
|
||||
return createHardwareFluxSink(spec.drive);
|
||||
else if (ends_with(filename, ".flux"))
|
||||
return createSqliteFluxSink(filename);
|
||||
|
||||
Error() << "unrecognised flux filename extension";
|
||||
return std::unique_ptr<FluxSink>();
|
||||
if (config.has_fluxfile())
|
||||
return createSqliteFluxSink(config.fluxfile());
|
||||
return createHardwareFluxSink(config.drive());
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
#define FLUXSINK_H
|
||||
|
||||
#include "flags.h"
|
||||
#include <ostream>
|
||||
|
||||
extern FlagGroup hardwareFluxSinkFlags;
|
||||
extern FlagGroup sqliteFluxSinkFlags;
|
||||
|
||||
class Fluxmap;
|
||||
class FluxSpec;
|
||||
class Config_OutputDisk;
|
||||
|
||||
class FluxSink
|
||||
{
|
||||
@@ -17,13 +18,19 @@ public:
|
||||
static std::unique_ptr<FluxSink> createSqliteFluxSink(const std::string& filename);
|
||||
static std::unique_ptr<FluxSink> createHardwareFluxSink(unsigned drive);
|
||||
|
||||
static std::unique_ptr<FluxSink> create(const FluxSpec& spec);
|
||||
static std::unique_ptr<FluxSink> create(const Config_OutputDisk& config);
|
||||
|
||||
public:
|
||||
virtual void writeFlux(int track, int side, Fluxmap& fluxmap) = 0;
|
||||
|
||||
virtual operator std::string () const = 0;
|
||||
};
|
||||
|
||||
extern void setHardwareFluxSinkHardSectorCount(int sectorCount);
|
||||
inline std::ostream& operator << (std::ostream& stream, FluxSink& flushSink)
|
||||
{
|
||||
stream << (std::string)flushSink;
|
||||
return stream;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -64,6 +64,11 @@ public:
|
||||
return usbWrite(side, fluxmap.rawBytes(), _hardSectorThreshold);
|
||||
}
|
||||
|
||||
operator std::string () const
|
||||
{
|
||||
return fmt::format("drive {}", _drive);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned _drive;
|
||||
nanoseconds_t _hardSectorThreshold;
|
||||
|
||||
@@ -19,7 +19,8 @@ static SettableFlag overwriteFlag(
|
||||
class SqliteFluxSink : public FluxSink
|
||||
{
|
||||
public:
|
||||
SqliteFluxSink(const std::string& filename)
|
||||
SqliteFluxSink(const std::string& filename):
|
||||
_filename(filename)
|
||||
{
|
||||
if (mergeFlag && overwriteFlag)
|
||||
Error() << "you can't specify --merge and --overwrite";
|
||||
@@ -58,8 +59,15 @@ public:
|
||||
return sqlWriteFlux(_outdb, track, side, fluxmap);
|
||||
}
|
||||
|
||||
|
||||
operator std::string () const
|
||||
{
|
||||
return fmt::format("fluxfile {}", _filename);
|
||||
}
|
||||
|
||||
private:
|
||||
sqlite3* _outdb;
|
||||
std::string _filename;
|
||||
};
|
||||
|
||||
std::unique_ptr<FluxSink> FluxSink::createSqliteFluxSink(const std::string& filename)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
#include "imagereader/imagereader.h"
|
||||
#include "lib/config.pb.h"
|
||||
#include "fmt/format.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -12,13 +13,13 @@
|
||||
class DiskCopyImageReader : public ImageReader
|
||||
{
|
||||
public:
|
||||
DiskCopyImageReader(const ImageSpec& spec):
|
||||
ImageReader(spec)
|
||||
DiskCopyImageReader(const Config_InputFile& config):
|
||||
ImageReader(config)
|
||||
{}
|
||||
|
||||
SectorSet readImage()
|
||||
{
|
||||
std::ifstream inputFile(spec.filename, std::ios::in | std::ios::binary);
|
||||
std::ifstream inputFile(_config.filename(), std::ios::in | std::ios::binary);
|
||||
if (!inputFile.is_open())
|
||||
Error() << "cannot open input file";
|
||||
|
||||
@@ -120,9 +121,9 @@ public:
|
||||
};
|
||||
|
||||
std::unique_ptr<ImageReader> ImageReader::createDiskCopyImageReader(
|
||||
const ImageSpec& spec)
|
||||
const Config_InputFile& config)
|
||||
{
|
||||
return std::unique_ptr<ImageReader>(new DiskCopyImageReader(spec));
|
||||
return std::unique_ptr<ImageReader>(new DiskCopyImageReader(config));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,49 +6,20 @@
|
||||
#include "imagereader/imagereader.h"
|
||||
#include "utils.h"
|
||||
#include "fmt/format.h"
|
||||
#include "lib/config.pb.h"
|
||||
#include <algorithm>
|
||||
#include <ctype.h>
|
||||
|
||||
std::map<std::string, ImageReader::Constructor> ImageReader::formats =
|
||||
std::unique_ptr<ImageReader> ImageReader::create(const Config_InputFile& config)
|
||||
{
|
||||
{".adf", ImageReader::createImgImageReader},
|
||||
{".d81", ImageReader::createImgImageReader},
|
||||
{".diskcopy", ImageReader::createDiskCopyImageReader},
|
||||
{".img", ImageReader::createImgImageReader},
|
||||
{".ima", ImageReader::createImgImageReader},
|
||||
{".jv1", ImageReader::createImgImageReader},
|
||||
{".jv3", ImageReader::createJv3ImageReader},
|
||||
{".st", ImageReader::createImgImageReader},
|
||||
{".imd", ImageReader::createIMDImageReader},
|
||||
{".IMD", ImageReader::createIMDImageReader},
|
||||
};
|
||||
|
||||
ImageReader::Constructor ImageReader::findConstructor(const ImageSpec& spec)
|
||||
{
|
||||
const auto& filename = spec.filename;
|
||||
|
||||
for (const auto& e : formats)
|
||||
{
|
||||
if (endsWith(filename, e.first))
|
||||
return e.second;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
if (config.has_img())
|
||||
return ImageReader::createImgImageReader(config);
|
||||
else
|
||||
Error() << "bad input file config";
|
||||
return std::unique_ptr<ImageReader>();
|
||||
}
|
||||
|
||||
std::unique_ptr<ImageReader> ImageReader::create(const ImageSpec& spec)
|
||||
{
|
||||
verifyImageSpec(spec);
|
||||
return findConstructor(spec)(spec);
|
||||
}
|
||||
|
||||
void ImageReader::verifyImageSpec(const ImageSpec& spec)
|
||||
{
|
||||
if (!findConstructor(spec))
|
||||
Error() << "unrecognised input image filename extension";
|
||||
}
|
||||
|
||||
ImageReader::ImageReader(const ImageSpec& spec):
|
||||
spec(spec)
|
||||
ImageReader::ImageReader(const Config_InputFile& config):
|
||||
_config(config)
|
||||
{}
|
||||
|
||||
|
||||
@@ -3,38 +3,28 @@
|
||||
|
||||
class SectorSet;
|
||||
class ImageSpec;
|
||||
class Config_InputFile;
|
||||
|
||||
class ImageReader
|
||||
{
|
||||
public:
|
||||
ImageReader(const ImageSpec& spec);
|
||||
ImageReader(const Config_InputFile& config);
|
||||
virtual ~ImageReader() {};
|
||||
|
||||
public:
|
||||
static std::unique_ptr<ImageReader> create(const ImageSpec& spec);
|
||||
static void verifyImageSpec(const ImageSpec& spec);
|
||||
static std::unique_ptr<ImageReader> create(const Config_InputFile& config);
|
||||
|
||||
private:
|
||||
typedef
|
||||
std::function<
|
||||
std::unique_ptr<ImageReader>(const ImageSpec& spec)
|
||||
>
|
||||
Constructor;
|
||||
|
||||
static std::map<std::string, Constructor> formats;
|
||||
|
||||
static std::unique_ptr<ImageReader> createDiskCopyImageReader(const ImageSpec& spec);
|
||||
static std::unique_ptr<ImageReader> createImgImageReader(const ImageSpec& spec);
|
||||
static std::unique_ptr<ImageReader> createJv3ImageReader(const ImageSpec& spec);
|
||||
static std::unique_ptr<ImageReader> createIMDImageReader(const ImageSpec& spec);
|
||||
|
||||
static Constructor findConstructor(const ImageSpec& spec);
|
||||
public:
|
||||
static std::unique_ptr<ImageReader> createDiskCopyImageReader(const Config_InputFile& config);
|
||||
static std::unique_ptr<ImageReader> createImgImageReader(const Config_InputFile& config);
|
||||
static std::unique_ptr<ImageReader> createJv3ImageReader(const Config_InputFile& config);
|
||||
static std::unique_ptr<ImageReader> createIMDImageReader(const Config_InputFile& config);
|
||||
|
||||
public:
|
||||
virtual SectorSet readImage() = 0;
|
||||
|
||||
protected:
|
||||
ImageSpec spec;
|
||||
const Config_InputFile& _config;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
#include "imagereader/imagereader.h"
|
||||
#include "lib/config.pb.h"
|
||||
#include "fmt/format.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -84,8 +85,8 @@ static unsigned getSectorSize(uint8_t flags)
|
||||
class IMDImageReader : public ImageReader
|
||||
{
|
||||
public:
|
||||
IMDImageReader(const ImageSpec& spec):
|
||||
ImageReader(spec)
|
||||
IMDImageReader(const Config_InputFile& config):
|
||||
ImageReader(config)
|
||||
{}
|
||||
|
||||
SectorSet readImage()
|
||||
@@ -109,7 +110,7 @@ public:
|
||||
*/
|
||||
{
|
||||
//Read File
|
||||
std::ifstream inputFile(spec.filename, std::ios::in | std::ios::binary);
|
||||
std::ifstream inputFile(_config.filename(), std::ios::in | std::ios::binary);
|
||||
if (!inputFile.is_open())
|
||||
Error() << "cannot open input file";
|
||||
//define some variables
|
||||
@@ -273,9 +274,9 @@ public:
|
||||
};
|
||||
|
||||
std::unique_ptr<ImageReader> ImageReader::createIMDImageReader(
|
||||
const ImageSpec& spec)
|
||||
const Config_InputFile& config)
|
||||
{
|
||||
return std::unique_ptr<ImageReader>(new IMDImageReader(spec));
|
||||
return std::unique_ptr<ImageReader>(new IMDImageReader(config));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,10 +5,12 @@ message ImgInputOutput {
|
||||
optional int32 track = 1;
|
||||
optional int32 side = 2;
|
||||
|
||||
optional int64 file_offset = 3;
|
||||
optional int32 sector_size = 4;
|
||||
optional int32 sector_size = 3 [default=512];
|
||||
optional int32 sectors = 4;
|
||||
}
|
||||
|
||||
repeated Format format = 4;
|
||||
optional int32 tracks = 5 [default=80];
|
||||
optional int32 sides = 6 [default=2];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
#include "imagereader/imagereader.h"
|
||||
#include "lib/config.pb.h"
|
||||
#include "fmt/format.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -12,59 +13,69 @@
|
||||
class ImgImageReader : public ImageReader
|
||||
{
|
||||
public:
|
||||
ImgImageReader(const ImageSpec& spec):
|
||||
ImageReader(spec)
|
||||
ImgImageReader(const Config_InputFile& config):
|
||||
ImageReader(config)
|
||||
{}
|
||||
|
||||
SectorSet readImage()
|
||||
{
|
||||
std::ifstream inputFile(spec.filename, std::ios::in | std::ios::binary);
|
||||
std::ifstream inputFile(_config.filename(), std::ios::in | std::ios::binary);
|
||||
if (!inputFile.is_open())
|
||||
Error() << "cannot open input file";
|
||||
|
||||
size_t headSize = spec.sectors * spec.bytes;
|
||||
size_t trackSize = headSize * spec.heads;
|
||||
|
||||
std::cout << fmt::format("reading {} tracks, {} heads, {} sectors, {} bytes per sector, {} kB total",
|
||||
spec.cylinders, spec.heads,
|
||||
spec.sectors, spec.bytes,
|
||||
spec.cylinders * trackSize / 1024)
|
||||
<< 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;
|
||||
for (int track = 0; track < spec.cylinders; track++)
|
||||
for (int track = 0; track < _config.img().tracks(); track++)
|
||||
{
|
||||
for (int head = 0; head < spec.heads; head++)
|
||||
for (int side = 0; side < _config.img().sides(); side++)
|
||||
{
|
||||
for (int sectorId = 0; sectorId < spec.sectors; sectorId++)
|
||||
ImgInputOutput::Format format;
|
||||
getTrackFormat(format, track, side);
|
||||
|
||||
for (int sectorId = 0; sectorId < format.sectors(); sectorId++)
|
||||
{
|
||||
inputFile.seekg(track*trackSize + head*headSize + sectorId*spec.bytes, std::ios::beg);
|
||||
Bytes data(format.sector_size());
|
||||
inputFile.read((char*) data.begin(), data.size());
|
||||
|
||||
Bytes data(spec.bytes);
|
||||
inputFile.read((char*) data.begin(), spec.bytes);
|
||||
|
||||
int physicalTrack = track*spec.physicalStep + spec.physicalOffset;
|
||||
std::unique_ptr<Sector>& sector = sectors.get(physicalTrack, head, sectorId);
|
||||
std::unique_ptr<Sector>& sector = sectors.get(track, side, sectorId);
|
||||
sector.reset(new Sector);
|
||||
sector->status = Sector::OK;
|
||||
sector->logicalTrack = track;
|
||||
sector->physicalTrack = physicalTrack;
|
||||
sector->logicalSide = sector->physicalSide = head;
|
||||
sector->physicalTrack = track;
|
||||
sector->logicalSide = sector->physicalSide = side;
|
||||
sector->logicalSector = sectorId;
|
||||
sector->data = data;
|
||||
}
|
||||
}
|
||||
|
||||
if (inputFile.eof())
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << fmt::format("reading {} tracks, {} sides, {} kB total\n",
|
||||
_config.img().tracks(), _config.img().sides(),
|
||||
inputFile.tellg() / 1024);
|
||||
return sectors;
|
||||
}
|
||||
|
||||
private:
|
||||
void getTrackFormat(ImgInputOutput::Format& format, unsigned track, unsigned side)
|
||||
{
|
||||
format.Clear();
|
||||
for (const ImgInputOutput::Format& f : _config.img().format())
|
||||
{
|
||||
if (f.has_track() && (f.track() != track))
|
||||
continue;
|
||||
if (f.has_side() && (f.side() != side))
|
||||
continue;
|
||||
|
||||
format.MergeFrom(f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<ImageReader> ImageReader::createImgImageReader(
|
||||
const ImageSpec& spec)
|
||||
const Config_InputFile& config)
|
||||
{
|
||||
return std::unique_ptr<ImageReader>(new ImgImageReader(spec));
|
||||
return std::unique_ptr<ImageReader>(new ImgImageReader(config));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "sectorset.h"
|
||||
#include "imagereader/imagereader.h"
|
||||
#include "fmt/format.h"
|
||||
#include "lib/config.pb.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
@@ -13,7 +14,7 @@
|
||||
* in any order, followed by the same again for more sectors. To find the second data block
|
||||
* you need to know the size of the first data block, which requires parsing it.
|
||||
*
|
||||
* https://www.tim-mann.org/trs80/dskspec.html
|
||||
* https://www.tim-mann.org/trs80/dskconfig.html
|
||||
*
|
||||
* typedef struct {
|
||||
* SectorHeader headers1[2901];
|
||||
@@ -77,13 +78,13 @@ static unsigned getSectorSize(uint8_t flags)
|
||||
class Jv3ImageReader : public ImageReader
|
||||
{
|
||||
public:
|
||||
Jv3ImageReader(const ImageSpec& spec):
|
||||
ImageReader(spec)
|
||||
Jv3ImageReader(const Config_InputFile& config):
|
||||
ImageReader(config)
|
||||
{}
|
||||
|
||||
SectorSet readImage()
|
||||
{
|
||||
std::ifstream inputFile(spec.filename, std::ios::in | std::ios::binary);
|
||||
std::ifstream inputFile(_config.filename(), std::ios::in | std::ios::binary);
|
||||
if (!inputFile.is_open())
|
||||
Error() << "cannot open input file";
|
||||
|
||||
@@ -132,10 +133,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<ImageReader> ImageReader::createJv3ImageReader(
|
||||
const ImageSpec& spec)
|
||||
std::unique_ptr<ImageReader> ImageReader::createJv3ImageReader(const Config_InputFile& config)
|
||||
{
|
||||
return std::unique_ptr<ImageReader>(new Jv3ImageReader(spec));
|
||||
return std::unique_ptr<ImageReader>(new Jv3ImageReader(config));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -136,9 +136,9 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
|
||||
SectorSet allSectors;
|
||||
for (int cylinder : iterate(config.cylinders()))
|
||||
{
|
||||
for (int side : iterate(config.sides()))
|
||||
for (int head : iterate(config.heads()))
|
||||
{
|
||||
auto track = std::make_unique<Track>(cylinder, side);
|
||||
auto track = std::make_unique<Track>(cylinder, head);
|
||||
track->fluxsource = &fluxsource;
|
||||
|
||||
std::map<int, std::unique_ptr<Sector>> readSectors;
|
||||
|
||||
@@ -14,70 +14,42 @@
|
||||
#include "record.h"
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
#include "lib/config.pb.h"
|
||||
#include "proto.h"
|
||||
|
||||
FlagGroup writerFlags { &hardwareFluxSourceFlags, &sqliteFluxSinkFlags, &hardwareFluxSinkFlags };
|
||||
|
||||
static DataSpecFlag dest(
|
||||
{ "--dest", "-d" },
|
||||
"destination for data",
|
||||
":d=0:t=0-79:s=0-1");
|
||||
|
||||
static DataSpecFlag input(
|
||||
{ "--input", "-i" },
|
||||
"input image file to read from",
|
||||
"");
|
||||
|
||||
static sqlite3* outdb;
|
||||
|
||||
void setWriterDefaultDest(const std::string& dest)
|
||||
{
|
||||
::dest.set(dest);
|
||||
}
|
||||
|
||||
void setWriterDefaultInput(const std::string& input)
|
||||
{
|
||||
::input.set(input);
|
||||
}
|
||||
|
||||
void setWriterHardSectorCount(int sectorCount)
|
||||
{
|
||||
setHardwareFluxSinkHardSectorCount(sectorCount);
|
||||
}
|
||||
|
||||
static SectorSet readSectorsFromFile(const ImageSpec& spec)
|
||||
{
|
||||
return ImageReader::create(spec)->readImage();
|
||||
}
|
||||
|
||||
void writeTracks(
|
||||
FluxSink& fluxSink,
|
||||
const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
|
||||
{
|
||||
const FluxSpec spec(dest);
|
||||
std::cout << "Writing to: " << fluxSink << std::endl;
|
||||
|
||||
std::cout << "Writing to: " << dest << std::endl;
|
||||
|
||||
std::shared_ptr<FluxSink> fluxSink = FluxSink::create(spec);
|
||||
|
||||
for (const auto& location : spec.locations)
|
||||
{
|
||||
std::cout << fmt::format("{0:>3}.{1}: ", location.track, location.side) << std::flush;
|
||||
std::unique_ptr<Fluxmap> fluxmap = producer(location.track, location.side);
|
||||
if (!fluxmap)
|
||||
{
|
||||
/* Erase this track rather than writing. */
|
||||
|
||||
fluxmap.reset(new Fluxmap());
|
||||
fluxSink->writeFlux(location.track, location.side, *fluxmap);
|
||||
std::cout << "erased\n";
|
||||
}
|
||||
else
|
||||
for (unsigned cylinder : iterate(config.cylinders()))
|
||||
{
|
||||
for (unsigned head : iterate(config.heads()))
|
||||
{
|
||||
/* 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;
|
||||
std::cout << fmt::format("{0:>3}.{1}: ", cylinder, head) << std::flush;
|
||||
std::unique_ptr<Fluxmap> fluxmap = producer(cylinder, head);
|
||||
if (!fluxmap)
|
||||
{
|
||||
/* Erase this track rather than writing. */
|
||||
|
||||
fluxmap.reset(new Fluxmap());
|
||||
fluxSink.writeFlux(cylinder, head, *fluxmap);
|
||||
std::cout << "erased\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,11 +68,10 @@ void fillBitmapTo(std::vector<bool>& bitmap,
|
||||
}
|
||||
}
|
||||
|
||||
void writeDiskCommand(AbstractEncoder& encoder)
|
||||
void writeDiskCommand(ImageReader& imageReader, AbstractEncoder& encoder, FluxSink& fluxSink)
|
||||
{
|
||||
const ImageSpec spec(input);
|
||||
SectorSet allSectors = readSectorsFromFile(spec);
|
||||
writeTracks(
|
||||
SectorSet allSectors = imageReader.readImage();
|
||||
writeTracks(fluxSink,
|
||||
[&](int track, int side) -> std::unique_ptr<Fluxmap>
|
||||
{
|
||||
return encoder.encode(track, side, allSectors);
|
||||
|
||||
@@ -8,17 +8,19 @@ extern FlagGroup writerFlags;
|
||||
class Fluxmap;
|
||||
class AbstractEncoder;
|
||||
class Geometry;
|
||||
class ImageReader;
|
||||
class FluxSink;
|
||||
|
||||
extern void setWriterDefaultDest(const std::string& dest);
|
||||
extern void setWriterDefaultInput(const std::string& input);
|
||||
extern void setWriterHardSectorCount(int sectorCount);
|
||||
|
||||
extern void writeTracks(const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer);
|
||||
extern void writeTracks(FluxSink& fluxSink, const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer);
|
||||
|
||||
extern void fillBitmapTo(std::vector<bool>& bitmap,
|
||||
unsigned& cursor, unsigned terminateAt,
|
||||
const std::vector<bool>& pattern);
|
||||
|
||||
extern void writeDiskCommand(AbstractEncoder& encoder);
|
||||
extern void writeDiskCommand(ImageReader& imageReader, AbstractEncoder& encoder, FluxSink& fluxSink);
|
||||
|
||||
#endif
|
||||
|
||||
17
mkninja.sh
17
mkninja.sh
@@ -13,7 +13,7 @@ rule proto
|
||||
description = PROTO \$in
|
||||
|
||||
rule protoencode
|
||||
command = (echo '#include <string>' && echo 'static const char data[] = {' && ($PROTOC \$flags --encode=\$messagetype \$\$(cat \$def)< \$in | $XXD -i) && echo '}; extern std::string \$name(); std::string \$name() { return std::string(data, sizeof(data)); }') > \$out
|
||||
command = (echo '#include <string>' && echo 'static const unsigned char data[] = {' && ($PROTOC \$flags --encode=\$messagetype \$\$(cat \$def)< \$in | $XXD -i) && echo '}; extern std::string \$name(); std::string \$name() { return std::string((const char*)data, sizeof(data)); }') > \$out
|
||||
description = PROTOENCODE \$in
|
||||
|
||||
rule binencode
|
||||
@@ -232,7 +232,7 @@ buildproto libproto.a \
|
||||
lib/config.proto \
|
||||
lib/decoders/decoder.proto \
|
||||
lib/imagereader/img.proto \
|
||||
lib/range.proto \
|
||||
lib/common.proto \
|
||||
|
||||
buildlibrary libbackend.a \
|
||||
-I$OBJDIR/proto \
|
||||
@@ -308,6 +308,14 @@ for pb in \
|
||||
readables_${pb}_pb src/readables/$pb.textpb $OBJDIR/proto/src/readables/$pb.cc
|
||||
done
|
||||
|
||||
for pb in \
|
||||
brother240 \
|
||||
ibm1440 \
|
||||
; do
|
||||
buildencodedproto $OBJDIR/proto/libproto.def Config \
|
||||
writables_${pb}_pb src/writables/$pb.textpb $OBJDIR/proto/src/writables/$pb.cc
|
||||
done
|
||||
|
||||
buildlibrary libfrontend.a \
|
||||
-I$OBJDIR/proto \
|
||||
src/fe-analysedriveresponse.cc \
|
||||
@@ -319,18 +327,21 @@ buildlibrary libfrontend.a \
|
||||
src/fe-fluxtovcd.cc \
|
||||
src/fe-image.cc \
|
||||
src/fe-inspect.cc \
|
||||
src/fe-read.cc \
|
||||
src/fe-rpm.cc \
|
||||
src/fe-scptoflux.cc \
|
||||
src/fe-seek.cc \
|
||||
src/fe-testbandwidth.cc \
|
||||
src/fe-testvoltages.cc \
|
||||
src/fe-upgradefluxfile.cc \
|
||||
src/fe-write.cc \
|
||||
src/fe-writeflux.cc \
|
||||
src/fe-writetestpattern.cc \
|
||||
src/fe-read.cc \
|
||||
src/fluxengine.cc \
|
||||
$OBJDIR/proto/src/readables/brother.cc \
|
||||
$OBJDIR/proto/src/readables/ibm.cc \
|
||||
$OBJDIR/proto/src/writables/brother240.cc \
|
||||
$OBJDIR/proto/src/writables/ibm1440.cc \
|
||||
|
||||
# src/fe-readadfs.cc \
|
||||
# src/fe-readaeslanier.cc \
|
||||
|
||||
@@ -7,15 +7,18 @@ static FlagGroup flags { &writerFlags };
|
||||
|
||||
int mainErase(int argc, const char* argv[])
|
||||
{
|
||||
setWriterDefaultDest(":t=0-81:s=0-1");
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
Error() << "TODO";
|
||||
|
||||
#if 0
|
||||
writeTracks(
|
||||
[](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
|
||||
{
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
68
src/fe-write.cc
Normal file
68
src/fe-write.cc
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "writer.h"
|
||||
#include "fluxmap.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
#include "record.h"
|
||||
#include "proto.h"
|
||||
#include "dataspec.h"
|
||||
#include "fluxsink/fluxsink.h"
|
||||
#include "arch/brother/brother.h"
|
||||
#include "arch/ibm/ibm.h"
|
||||
#include "imagereader/imagereader.h"
|
||||
#include "fmt/format.h"
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <fstream>
|
||||
|
||||
static FlagGroup flags { &writerFlags };
|
||||
|
||||
extern std::string writables_brother240_pb();
|
||||
extern std::string writables_ibm1440_pb();
|
||||
|
||||
static std::map<std::string, std::function<std::string()>> writables = {
|
||||
{ "brother240", writables_brother240_pb },
|
||||
{ "ibm1440", writables_ibm1440_pb },
|
||||
};
|
||||
|
||||
int mainWrite(int argc, const char* argv[])
|
||||
{
|
||||
std::vector<std::string> filenames = flags.parseFlagsWithFilenames(argc, argv);
|
||||
for (const auto& filename : filenames)
|
||||
{
|
||||
if (writables.find(filename) != writables.end())
|
||||
{
|
||||
if (!config.ParseFromString(writables[filename]()))
|
||||
Error() << "couldn't load config proto";
|
||||
}
|
||||
else
|
||||
Error() << "configs in files not supported yet";
|
||||
}
|
||||
|
||||
if (!config.has_input() || !config.has_output())
|
||||
Error() << "incomplete config (did you remember to specify the format?)";
|
||||
|
||||
std::string s;
|
||||
google::protobuf::TextFormat::PrintToString(config, &s);
|
||||
std::cout << s << '\n';
|
||||
|
||||
std::unique_ptr<ImageReader> reader(ImageReader::create(config.input().file()));
|
||||
|
||||
const auto& disk = config.output().disk();
|
||||
std::unique_ptr<AbstractEncoder> encoder;
|
||||
if (disk.has_brother())
|
||||
encoder.reset(new BrotherEncoder(disk.brother()));
|
||||
else if (disk.has_ibm())
|
||||
encoder.reset(new IbmEncoder(disk.ibm()));
|
||||
else
|
||||
Error() << "no output disk format specified";
|
||||
|
||||
std::unique_ptr<FluxSink> fluxSink(FluxSink::create(config.output().disk()));
|
||||
|
||||
writeDiskCommand(*reader, *encoder, *fluxSink);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,11 +22,12 @@ static DoubleFlag sequenceLength(
|
||||
|
||||
int mainWriteTestPattern(int argc, const char* argv[])
|
||||
{
|
||||
setWriterDefaultDest(":t=0-81:s=0-1");
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
unsigned ticksPerInterval = (unsigned) (interval * TICKS_PER_US);
|
||||
|
||||
Error() << "TODO";
|
||||
#if 0
|
||||
writeTracks(
|
||||
[&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
|
||||
{
|
||||
@@ -41,6 +42,7 @@ int mainWriteTestPattern(int argc, const char* argv[])
|
||||
return fluxmap;
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,42 +4,21 @@ typedef int command_cb(int agrc, const char* argv[]);
|
||||
|
||||
extern command_cb mainAnalyseDriveResponse;
|
||||
extern command_cb mainAnalyseLayout;
|
||||
extern command_cb mainErase;
|
||||
extern command_cb mainConvertCwfToFlux;
|
||||
extern command_cb mainConvertFluxToAu;
|
||||
extern command_cb mainConvertFluxToScp;
|
||||
extern command_cb mainConvertFluxToVcd;
|
||||
extern command_cb mainConvertImage;
|
||||
extern command_cb mainConvertScpToFlux;
|
||||
extern command_cb mainErase;
|
||||
extern command_cb mainInspect;
|
||||
extern command_cb mainReadADFS;
|
||||
extern command_cb mainReadAESLanier;
|
||||
extern command_cb mainReadAmiga;
|
||||
extern command_cb mainReadAmpro;
|
||||
extern command_cb mainReadApple2;
|
||||
extern command_cb mainReadAtariST;
|
||||
extern command_cb mainReadBrother;
|
||||
extern command_cb mainReadC64;
|
||||
extern command_cb mainReadDFS;
|
||||
extern command_cb mainReadF85;
|
||||
extern command_cb mainReadFB100;
|
||||
extern command_cb mainReadIBM;
|
||||
extern command_cb mainReadMac;
|
||||
extern command_cb mainReadMicropolis;
|
||||
extern command_cb mainReadMx;
|
||||
extern command_cb mainReadTiDs990;
|
||||
extern command_cb mainReadVictor9K;
|
||||
extern command_cb mainReadZilogMCZ;
|
||||
extern command_cb mainRead;
|
||||
extern command_cb mainRpm;
|
||||
extern command_cb mainSeek;
|
||||
extern command_cb mainTestBandwidth;
|
||||
extern command_cb mainTestVoltages;
|
||||
extern command_cb mainUpgradeFluxFile;
|
||||
extern command_cb mainWriteAmiga;
|
||||
extern command_cb mainWriteBrother;
|
||||
extern command_cb mainWriteIbm;
|
||||
extern command_cb mainWriteMac;
|
||||
extern command_cb mainWriteTiDs990;
|
||||
extern command_cb mainWrite;
|
||||
extern command_cb mainWriteFlux;
|
||||
extern command_cb mainWriteTestPattern;
|
||||
|
||||
@@ -50,8 +29,6 @@ struct Command
|
||||
std::string help;
|
||||
};
|
||||
|
||||
extern command_cb mainRead;
|
||||
static command_cb mainWrite;
|
||||
static command_cb mainConvert;
|
||||
static command_cb mainAnalyse;
|
||||
static command_cb mainTest;
|
||||
@@ -156,12 +133,6 @@ static int mainExtended(std::vector<Command>& subcommands, const std::string& co
|
||||
return 1;
|
||||
}
|
||||
|
||||
//static int mainRead(int argc, const char* argv[])
|
||||
//{ return mainExtended(readables, "read", argc, argv); }
|
||||
|
||||
static int mainWrite(int argc, const char* argv[])
|
||||
{ return mainExtended(writeables, "write", argc, argv); }
|
||||
|
||||
static int mainConvert(int argc, const char* argv[])
|
||||
{ return mainExtended(convertables, "convert", argc, argv); }
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ cylinders {
|
||||
end: 81
|
||||
}
|
||||
|
||||
sides {
|
||||
heads {
|
||||
start: 0
|
||||
end: 0
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ cylinders {
|
||||
end: 81
|
||||
}
|
||||
|
||||
sides {
|
||||
heads {
|
||||
start: 0
|
||||
end: 1
|
||||
}
|
||||
|
||||
28
src/writables/brother240.textpb
Normal file
28
src/writables/brother240.textpb
Normal file
@@ -0,0 +1,28 @@
|
||||
input {
|
||||
file {
|
||||
filename: "brother240.img"
|
||||
img {
|
||||
format {
|
||||
sectors: 12
|
||||
sector_size: 256
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output {
|
||||
disk {
|
||||
brother {}
|
||||
}
|
||||
}
|
||||
|
||||
cylinders {
|
||||
start: 0
|
||||
end: 77
|
||||
}
|
||||
|
||||
heads {
|
||||
start: 0
|
||||
end: 0
|
||||
}
|
||||
|
||||
32
src/writables/ibm1440.textpb
Normal file
32
src/writables/ibm1440.textpb
Normal file
@@ -0,0 +1,32 @@
|
||||
input {
|
||||
file {
|
||||
filename: "ibm1440.img"
|
||||
img {
|
||||
format {
|
||||
sectors: 18
|
||||
sector_size: 512
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output {
|
||||
disk {
|
||||
ibm {
|
||||
track_length_ms: 200
|
||||
clock_rate_khz: 500
|
||||
sector_skew: "0123456789abcdefgh"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cylinders {
|
||||
start: 0
|
||||
end: 79
|
||||
}
|
||||
|
||||
heads {
|
||||
start: 0
|
||||
end: 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user