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:
@@ -347,7 +347,7 @@ ReadResult readGroup(FluxSourceIteratorHolder& fluxSourceIteratorHolder,
|
|||||||
ReadResult result = BAD_AND_CAN_NOT_RETRY;
|
ReadResult result = BAD_AND_CAN_NOT_RETRY;
|
||||||
|
|
||||||
for (unsigned offset = 0; offset < trackInfo->groupSize;
|
for (unsigned offset = 0; offset < trackInfo->groupSize;
|
||||||
offset += Layout::getHeadWidth())
|
offset += Layout::getHeadWidth())
|
||||||
{
|
{
|
||||||
log(BeginReadOperationLogMessage{
|
log(BeginReadOperationLogMessage{
|
||||||
trackInfo->physicalTrack + offset, trackInfo->physicalSide});
|
trackInfo->physicalTrack + offset, trackInfo->physicalSide});
|
||||||
@@ -404,7 +404,7 @@ void writeTracks(FluxSink& fluxSink,
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
for (int offset = 0; offset < trackInfo->groupSize;
|
for (int offset = 0; offset < trackInfo->groupSize;
|
||||||
offset += Layout::getHeadWidth())
|
offset += Layout::getHeadWidth())
|
||||||
{
|
{
|
||||||
unsigned physicalTrack = trackInfo->physicalTrack + offset;
|
unsigned physicalTrack = trackInfo->physicalTrack + offset;
|
||||||
|
|
||||||
@@ -734,7 +734,7 @@ void readDiskCommand(
|
|||||||
if (globalConfig()->decoder().has_write_csv_to())
|
if (globalConfig()->decoder().has_write_csv_to())
|
||||||
writer.writeCsv(
|
writer.writeCsv(
|
||||||
*diskflux->image, globalConfig()->decoder().write_csv_to());
|
*diskflux->image, globalConfig()->decoder().write_csv_to());
|
||||||
writer.writeMappedImage(*diskflux->image);
|
writer.writeImage(*diskflux->image);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink)
|
void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink)
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class Flag
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Flag(const std::vector<std::string>& names, const std::string helptext);
|
Flag(const std::vector<std::string>& names, const std::string helptext);
|
||||||
virtual ~Flag(){};
|
virtual ~Flag() {};
|
||||||
|
|
||||||
void checkInitialised() const
|
void checkInitialised() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,8 +22,9 @@ message LayoutProto
|
|||||||
enum Order
|
enum Order
|
||||||
{
|
{
|
||||||
UNDEFINED = 0;
|
UNDEFINED = 0;
|
||||||
CHS = 1;
|
CHS = 1; // sort by cylinder, then head, then sector -- libdsk 'alt'
|
||||||
HCS = 2;
|
HCS = 2; // sort by head, then cylinder, then sector -- libdsk 'outout'
|
||||||
|
HCS_RH1 = 3; // as HCS, except the cylinder count for head 1 is reversed -- libdsk 'outback'
|
||||||
}
|
}
|
||||||
|
|
||||||
message LayoutdataProto
|
message LayoutdataProto
|
||||||
@@ -54,10 +55,12 @@ message LayoutProto
|
|||||||
[ default = 0, (help) = "number of tracks in image" ];
|
[ default = 0, (help) = "number of tracks in image" ];
|
||||||
optional int32 sides = 3
|
optional int32 sides = 3
|
||||||
[ default = 0, (help) = "number of sides in image" ];
|
[ default = 0, (help) = "number of sides in image" ];
|
||||||
optional Order order = 4
|
optional Order filesystem_track_order = 4
|
||||||
[ default = CHS, (help) = "the order of sectors in the filesystem" ];
|
[ default = CHS, (help) = "the order of sectors in the filesystem" ];
|
||||||
optional bool swap_sides = 5
|
optional Order image_track_order = 5
|
||||||
|
[ default = CHS, (help) = "the order of sectors in disk images" ];
|
||||||
|
optional bool swap_sides = 6
|
||||||
[ default = false, (help) = "the sides are inverted on this disk" ];
|
[ default = false, (help) = "the sides are inverted on this disk" ];
|
||||||
optional FormatType format_type = 6
|
optional FormatType format_type = 7
|
||||||
[ default = FORMATTYPE_UNKNOWN, (help) = "Format type of image" ];
|
[ default = FORMATTYPE_UNKNOWN, (help) = "Format type of image" ];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "lib/data/sector.h"
|
#include "lib/data/sector.h"
|
||||||
#include "lib/data/image.h"
|
#include "lib/data/image.h"
|
||||||
#include "lib/data/layout.h"
|
#include "lib/data/layout.h"
|
||||||
|
#include "lib/config/config.h"
|
||||||
|
|
||||||
Image::Image() {}
|
Image::Image() {}
|
||||||
|
|
||||||
@@ -25,7 +26,8 @@ void Image::clear()
|
|||||||
void Image::createBlankImage()
|
void Image::createBlankImage()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
for (const auto& trackAndHead : Layout::getTrackOrdering())
|
for (const auto& trackAndHead : Layout::getTrackOrdering(
|
||||||
|
globalConfig()->layout().filesystem_track_order()))
|
||||||
{
|
{
|
||||||
unsigned track = trackAndHead.first;
|
unsigned track = trackAndHead.first;
|
||||||
unsigned side = trackAndHead.second;
|
unsigned side = trackAndHead.second;
|
||||||
|
|||||||
@@ -108,21 +108,21 @@ void Layout::getBounds(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<int, int>> Layout::getTrackOrdering(
|
std::vector<std::pair<int, int>> Layout::getTrackOrdering(
|
||||||
unsigned guessedTracks, unsigned guessedSides)
|
LayoutProto::Order ordering, unsigned guessedTracks, unsigned guessedSides)
|
||||||
{
|
{
|
||||||
auto layout = globalConfig()->layout();
|
auto layout = globalConfig()->layout();
|
||||||
int tracks = layout.has_tracks() ? layout.tracks() : guessedTracks;
|
int tracks = layout.has_tracks() ? layout.tracks() : guessedTracks;
|
||||||
int sides = layout.has_sides() ? layout.sides() : guessedSides;
|
int sides = layout.has_sides() ? layout.sides() : guessedSides;
|
||||||
|
|
||||||
std::vector<std::pair<int, int>> ordering;
|
std::vector<std::pair<int, int>> trackList;
|
||||||
switch (layout.order())
|
switch (ordering)
|
||||||
{
|
{
|
||||||
case LayoutProto::CHS:
|
case LayoutProto::CHS:
|
||||||
{
|
{
|
||||||
for (int track = 0; track < tracks; track++)
|
for (int track = 0; track < tracks; track++)
|
||||||
{
|
{
|
||||||
for (int side = 0; side < sides; side++)
|
for (int side = 0; side < sides; side++)
|
||||||
ordering.push_back(std::make_pair(track, side));
|
trackList.push_back(std::make_pair(track, side));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -132,16 +132,30 @@ std::vector<std::pair<int, int>> Layout::getTrackOrdering(
|
|||||||
for (int side = 0; side < sides; side++)
|
for (int side = 0; side < sides; side++)
|
||||||
{
|
{
|
||||||
for (int track = 0; track < tracks; track++)
|
for (int track = 0; track < tracks; track++)
|
||||||
ordering.push_back(std::make_pair(track, side));
|
trackList.push_back(std::make_pair(track, side));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LayoutProto::HCS_RH1:
|
||||||
|
{
|
||||||
|
for (int side = 0; side < sides; side++)
|
||||||
|
{
|
||||||
|
if (side == 0)
|
||||||
|
for (int track = 0; track < tracks; track++)
|
||||||
|
trackList.push_back(std::make_pair(track, side));
|
||||||
|
if (side == 1)
|
||||||
|
for (int track = tracks; track >= 0; track--)
|
||||||
|
trackList.push_back(std::make_pair(track - 1, side));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error("LAYOUT: invalid track ordering");
|
error("LAYOUT: invalid track trackList");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ordering;
|
return trackList;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned> Layout::expandSectorList(
|
std::vector<unsigned> Layout::expandSectorList(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define LAYOUT_H
|
#define LAYOUT_H
|
||||||
|
|
||||||
#include "lib/data/flux.h"
|
#include "lib/data/flux.h"
|
||||||
|
#include "lib/config/layout.pb.h"
|
||||||
|
|
||||||
class SectorListProto;
|
class SectorListProto;
|
||||||
class TrackInfo;
|
class TrackInfo;
|
||||||
@@ -39,7 +40,9 @@ public:
|
|||||||
/* Returns a series of <track, side> pairs representing the filesystem
|
/* Returns a series of <track, side> pairs representing the filesystem
|
||||||
* ordering of the disk, in logical numbers. */
|
* ordering of the disk, in logical numbers. */
|
||||||
static std::vector<std::pair<int, int>> getTrackOrdering(
|
static std::vector<std::pair<int, int>> getTrackOrdering(
|
||||||
unsigned guessedTracks = 0, unsigned guessedSides = 0);
|
LayoutProto::Order ordering,
|
||||||
|
unsigned guessedTracks = 0,
|
||||||
|
unsigned guessedSides = 0);
|
||||||
|
|
||||||
/* Returns the layout of a given track. */
|
/* Returns the layout of a given track. */
|
||||||
static std::shared_ptr<const TrackInfo> getLayoutOfTrack(
|
static std::shared_ptr<const TrackInfo> getLayoutOfTrack(
|
||||||
|
|||||||
@@ -98,10 +98,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void beginTrack(){};
|
virtual void beginTrack() {};
|
||||||
virtual nanoseconds_t advanceToNextRecord() = 0;
|
virtual nanoseconds_t advanceToNextRecord() = 0;
|
||||||
virtual void decodeSectorRecord() = 0;
|
virtual void decodeSectorRecord() = 0;
|
||||||
virtual void decodeDataRecord(){};
|
virtual void decodeDataRecord() {};
|
||||||
|
|
||||||
const DecoderProto& _config;
|
const DecoderProto& _config;
|
||||||
std::shared_ptr<TrackDataFlux> _trackdata;
|
std::shared_ptr<TrackDataFlux> _trackdata;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public:
|
|||||||
auto physical = layoutdata->mutable_physical();
|
auto physical = layoutdata->mutable_physical();
|
||||||
|
|
||||||
for (int sectorInTrack = 0; sectorInTrack < currentSectorsInTrack;
|
for (int sectorInTrack = 0; sectorInTrack < currentSectorsInTrack;
|
||||||
sectorInTrack++)
|
sectorInTrack++)
|
||||||
{
|
{
|
||||||
Bytes sectorHeader(0x10);
|
Bytes sectorHeader(0x10);
|
||||||
inputFile.read(
|
inputFile.read(
|
||||||
|
|||||||
@@ -63,26 +63,3 @@ std::unique_ptr<ImageReader> ImageReader::create(const ImageReaderProto& config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImageReader::ImageReader(const ImageReaderProto& config): _config(config) {}
|
ImageReader::ImageReader(const ImageReaderProto& config): _config(config) {}
|
||||||
|
|
||||||
std::unique_ptr<Image> ImageReader::readMappedImage()
|
|
||||||
{
|
|
||||||
auto rawImage = readImage();
|
|
||||||
|
|
||||||
if (!_config.filesystem_sector_order())
|
|
||||||
return rawImage;
|
|
||||||
|
|
||||||
log("READER: converting from filesystem sector order to disk order");
|
|
||||||
std::set<std::shared_ptr<const Sector>> sectors;
|
|
||||||
for (const auto& e : *rawImage)
|
|
||||||
{
|
|
||||||
auto trackLayout =
|
|
||||||
Layout::getLayoutOfTrack(e->logicalTrack, e->logicalSide);
|
|
||||||
auto newSector = std::make_shared<Sector>();
|
|
||||||
*newSector = *e;
|
|
||||||
newSector->logicalSector =
|
|
||||||
trackLayout->filesystemToNaturalSectorMap.at(e->logicalSector);
|
|
||||||
sectors.insert(newSector);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_unique<Image>(sectors);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class ImageReader
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageReader(const ImageReaderProto& config);
|
ImageReader(const ImageReaderProto& config);
|
||||||
virtual ~ImageReader(){};
|
virtual ~ImageReader() {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<ImageReader> create(Config& config);
|
static std::unique_ptr<ImageReader> create(Config& config);
|
||||||
@@ -51,15 +51,10 @@ public:
|
|||||||
return _extraConfig;
|
return _extraConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Directly reads the image. */
|
/* Reads the image. */
|
||||||
|
|
||||||
virtual std::unique_ptr<Image> readImage() = 0;
|
virtual std::unique_ptr<Image> readImage() = 0;
|
||||||
|
|
||||||
/* Reads the image, and then applies any optional mapping to go from
|
|
||||||
* filesystem ordering to disk ordering. */
|
|
||||||
|
|
||||||
std::unique_ptr<Image> readMappedImage();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const ImageReaderProto& _config;
|
const ImageReaderProto& _config;
|
||||||
ConfigProto _extraConfig;
|
ConfigProto _extraConfig;
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ syntax = "proto2";
|
|||||||
|
|
||||||
import "lib/config/common.proto";
|
import "lib/config/common.proto";
|
||||||
|
|
||||||
message ImgInputOutputProto {}
|
message ImgInputOutputProto {
|
||||||
|
optional bool filesystem_sector_order = 1 [
|
||||||
|
(help) = "read/write sector image in filesystem order",
|
||||||
|
default = false
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
message DiskCopyInputProto {}
|
message DiskCopyInputProto {}
|
||||||
message ImdInputProto {}
|
message ImdInputProto {}
|
||||||
@@ -15,16 +20,12 @@ message FdiInputProto {}
|
|||||||
message D88InputProto {}
|
message D88InputProto {}
|
||||||
message NfdInputProto {}
|
message NfdInputProto {}
|
||||||
|
|
||||||
// NEXT_TAG: 15
|
// NEXT_TAG: 14
|
||||||
message ImageReaderProto
|
message ImageReaderProto
|
||||||
{
|
{
|
||||||
optional string filename = 1 [ (help) = "filename of input sector image" ];
|
optional string filename = 1 [ (help) = "filename of input sector image" ];
|
||||||
optional bool filesystem_sector_order = 13 [
|
|
||||||
(help) = "read/write sector image in filesystem order",
|
|
||||||
default = false
|
|
||||||
];
|
|
||||||
|
|
||||||
optional ImageReaderWriterType type = 14
|
optional ImageReaderWriterType type = 13
|
||||||
[default = IMAGETYPE_NOT_SET, (help) = "input image type"];
|
[default = IMAGETYPE_NOT_SET, (help) = "input image type"];
|
||||||
|
|
||||||
optional ImgInputOutputProto img = 2;
|
optional ImgInputOutputProto img = 2;
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ public:
|
|||||||
|
|
||||||
switch (Status_Sector)
|
switch (Status_Sector)
|
||||||
{
|
{
|
||||||
// clang-format off
|
// clang-format off
|
||||||
/* fluxengine knows of a few sector statussen but not all of the statussen in IMD.
|
/* fluxengine knows of a few sector statussen but not all of the statussen in IMD.
|
||||||
* // the statussen are in sector.h. Translation to fluxengine is as follows:
|
* // the statussen are in sector.h. Translation to fluxengine is as follows:
|
||||||
* Statussen fluxengine | Status IMD
|
* Statussen fluxengine | Status IMD
|
||||||
|
|||||||
@@ -31,8 +31,11 @@ public:
|
|||||||
"IMG: bad configuration; did you remember to set the "
|
"IMG: bad configuration; did you remember to set the "
|
||||||
"tracks, sides and trackdata fields in the layout?");
|
"tracks, sides and trackdata fields in the layout?");
|
||||||
|
|
||||||
|
bool in_filesystem_order = _config.img().filesystem_sector_order();
|
||||||
std::unique_ptr<Image> image(new Image);
|
std::unique_ptr<Image> image(new Image);
|
||||||
for (const auto& p : Layout::getTrackOrdering())
|
for (const auto& p : Layout::getTrackOrdering(
|
||||||
|
in_filesystem_order ? layout.filesystem_track_order()
|
||||||
|
: layout.image_track_order()))
|
||||||
{
|
{
|
||||||
int track = p.first;
|
int track = p.first;
|
||||||
int side = p.second;
|
int side = p.second;
|
||||||
@@ -46,6 +49,9 @@ public:
|
|||||||
Bytes data(trackLayout->sectorSize);
|
Bytes data(trackLayout->sectorSize);
|
||||||
inputFile.read((char*)data.begin(), data.size());
|
inputFile.read((char*)data.begin(), data.size());
|
||||||
|
|
||||||
|
if (in_filesystem_order)
|
||||||
|
sectorId =
|
||||||
|
trackLayout->filesystemToNaturalSectorMap.at(sectorId);
|
||||||
const auto& sector = image->put(track, side, sectorId);
|
const auto& sector = image->put(track, side, sectorId);
|
||||||
sector->status = Sector::OK;
|
sector->status = Sector::OK;
|
||||||
sector->data = data;
|
sector->data = data;
|
||||||
|
|||||||
@@ -65,15 +65,15 @@ public:
|
|||||||
uint32_t trackOffset = 688;
|
uint32_t trackOffset = 688;
|
||||||
|
|
||||||
for (int track = 0; track < geometry.numTracks * geometry.numSides;
|
for (int track = 0; track < geometry.numTracks * geometry.numSides;
|
||||||
track++)
|
track++)
|
||||||
{
|
{
|
||||||
headerWriter.seek(0x20 + 4 * track);
|
headerWriter.seek(0x20 + 4 * track);
|
||||||
headerWriter.write_le32(trackOffset);
|
headerWriter.write_le32(trackOffset);
|
||||||
int side = track & 1;
|
int side = track & 1;
|
||||||
std::vector<std::shared_ptr<const Sector>> sectors;
|
std::vector<std::shared_ptr<const Sector>> sectors;
|
||||||
for (int sectorId = geometry.firstSector;
|
for (int sectorId = geometry.firstSector;
|
||||||
sectorId <= geometry.numSectors;
|
sectorId <= geometry.numSectors;
|
||||||
sectorId++)
|
sectorId++)
|
||||||
{
|
{
|
||||||
const auto& sector = image.get(track >> 1, side, sectorId);
|
const auto& sector = image.get(track >> 1, side, sectorId);
|
||||||
if (sector)
|
if (sector)
|
||||||
|
|||||||
@@ -173,27 +173,3 @@ void ImageWriter::printMap(const Image& image)
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageWriter::writeMappedImage(const Image& image)
|
|
||||||
{
|
|
||||||
if (_config.filesystem_sector_order())
|
|
||||||
{
|
|
||||||
log("WRITER: converting from disk sector order to filesystem order");
|
|
||||||
|
|
||||||
std::set<std::shared_ptr<const Sector>> sectors;
|
|
||||||
for (const auto& e : image)
|
|
||||||
{
|
|
||||||
auto trackLayout =
|
|
||||||
Layout::getLayoutOfTrack(e->logicalTrack, e->logicalSide);
|
|
||||||
auto newSector = std::make_shared<Sector>();
|
|
||||||
*newSector = *e;
|
|
||||||
newSector->logicalSector =
|
|
||||||
trackLayout->naturalToFilesystemSectorMap.at(e->logicalSector);
|
|
||||||
sectors.insert(newSector);
|
|
||||||
}
|
|
||||||
|
|
||||||
writeImage(Image(sectors));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
writeImage(image);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class ImageWriter
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageWriter(const ImageWriterProto& config);
|
ImageWriter(const ImageWriterProto& config);
|
||||||
virtual ~ImageWriter(){};
|
virtual ~ImageWriter() {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<ImageWriter> create(Config& config);
|
static std::unique_ptr<ImageWriter> create(Config& config);
|
||||||
@@ -37,11 +37,8 @@ public:
|
|||||||
void writeCsv(const Image& sectors, const std::string& filename);
|
void writeCsv(const Image& sectors, const std::string& filename);
|
||||||
|
|
||||||
/* Writes a raw image. */
|
/* Writes a raw image. */
|
||||||
virtual void writeImage(const Image& sectors) = 0;
|
|
||||||
|
|
||||||
/* Writes an image applying any optional mapping from disk sector numbering
|
virtual void writeImage(const Image& sectors) = 0;
|
||||||
* to filesystem sector numbering. */
|
|
||||||
void writeMappedImage(const Image& sectors);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const ImageWriterProto& _config;
|
const ImageWriterProto& _config;
|
||||||
|
|||||||
@@ -67,12 +67,8 @@ message ImdOutputProto
|
|||||||
message ImageWriterProto
|
message ImageWriterProto
|
||||||
{
|
{
|
||||||
optional string filename = 1 [ (help) = "filename of output sector image" ];
|
optional string filename = 1 [ (help) = "filename of output sector image" ];
|
||||||
optional bool filesystem_sector_order = 10 [
|
|
||||||
(help) = "read/write sector image in filesystem order",
|
|
||||||
default = false
|
|
||||||
];
|
|
||||||
|
|
||||||
optional ImageReaderWriterType type = 11
|
optional ImageReaderWriterType type = 10
|
||||||
[ default = IMAGETYPE_NOT_SET, (help) = "image writer type" ];
|
[ default = IMAGETYPE_NOT_SET, (help) = "image writer type" ];
|
||||||
|
|
||||||
optional ImgInputOutputProto img = 2;
|
optional ImgInputOutputProto img = 2;
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ public:
|
|||||||
// determine how the optional cylinder map looks like
|
// determine how the optional cylinder map looks like
|
||||||
// write the corresponding logical ID
|
// write the corresponding logical ID
|
||||||
for (int sectorId = 0; sectorId < numSectorsinTrack;
|
for (int sectorId = 0; sectorId < numSectorsinTrack;
|
||||||
sectorId++)
|
sectorId++)
|
||||||
{
|
{
|
||||||
// const auto& sector = sectors.get(track, head,
|
// const auto& sector = sectors.get(track, head,
|
||||||
// sectorId);
|
// sectorId);
|
||||||
@@ -372,7 +372,7 @@ public:
|
|||||||
// determine how the optional head map looks like
|
// determine how the optional head map looks like
|
||||||
// write the corresponding logical ID
|
// write the corresponding logical ID
|
||||||
for (int sectorId = 0; sectorId < numSectorsinTrack;
|
for (int sectorId = 0; sectorId < numSectorsinTrack;
|
||||||
sectorId++)
|
sectorId++)
|
||||||
{
|
{
|
||||||
// const auto& sector = sectors.get(track, head,
|
// const auto& sector = sectors.get(track, head,
|
||||||
// sectorId);
|
// sectorId);
|
||||||
@@ -440,7 +440,7 @@ public:
|
|||||||
}
|
}
|
||||||
switch (sector->status)
|
switch (sector->status)
|
||||||
{
|
{
|
||||||
// clang-format off
|
// clang-format off
|
||||||
/* fluxengine knows of a few sector statussen but not all of the statussen in IMD.
|
/* fluxengine knows of a few sector statussen but not all of the statussen in IMD.
|
||||||
* // the statussen are in sector.h. Translation to fluxengine is as follows:
|
* // the statussen are in sector.h. Translation to fluxengine is as follows:
|
||||||
* Statussen fluxengine | Status IMD
|
* Statussen fluxengine | Status IMD
|
||||||
|
|||||||
@@ -31,7 +31,12 @@ public:
|
|||||||
if (!outputFile.is_open())
|
if (!outputFile.is_open())
|
||||||
error("cannot open output file");
|
error("cannot open output file");
|
||||||
|
|
||||||
for (const auto& p : Layout::getTrackOrdering(tracks, sides))
|
bool in_filesystem_order = _config.img().filesystem_sector_order();
|
||||||
|
for (const auto& p : Layout::getTrackOrdering(
|
||||||
|
in_filesystem_order ? layout.filesystem_track_order()
|
||||||
|
: layout.image_track_order(),
|
||||||
|
tracks,
|
||||||
|
sides))
|
||||||
{
|
{
|
||||||
int track = p.first;
|
int track = p.first;
|
||||||
int side = p.second;
|
int side = p.second;
|
||||||
@@ -39,6 +44,10 @@ public:
|
|||||||
auto trackLayout = Layout::getLayoutOfTrack(track, side);
|
auto trackLayout = Layout::getLayoutOfTrack(track, side);
|
||||||
for (int sectorId : trackLayout->naturalSectorOrder)
|
for (int sectorId : trackLayout->naturalSectorOrder)
|
||||||
{
|
{
|
||||||
|
if (in_filesystem_order)
|
||||||
|
sectorId =
|
||||||
|
trackLayout->filesystemToNaturalSectorMap.at(sectorId);
|
||||||
|
|
||||||
const auto& sector = image.get(track, side, sectorId);
|
const auto& sector = image.get(track, side, sectorId);
|
||||||
if (sector)
|
if (sector)
|
||||||
sector->data.slice(0, trackLayout->sectorSize)
|
sector->data.slice(0, trackLayout->sectorSize)
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public:
|
|||||||
|
|
||||||
int actualSectors = 0;
|
int actualSectors = 0;
|
||||||
for (int sectorId = 0; sectorId < geometry.numSectors;
|
for (int sectorId = 0; sectorId < geometry.numSectors;
|
||||||
sectorId++)
|
sectorId++)
|
||||||
{
|
{
|
||||||
const auto& sector = image.get(track, side, sectorId);
|
const auto& sector = image.get(track, side, sectorId);
|
||||||
if (sector)
|
if (sector)
|
||||||
@@ -81,7 +81,7 @@ public:
|
|||||||
trackHeaderWriter.write_le16(0); /* approximate track length */
|
trackHeaderWriter.write_le16(0); /* approximate track length */
|
||||||
|
|
||||||
for (int sectorId = 0; sectorId < geometry.numSectors;
|
for (int sectorId = 0; sectorId < geometry.numSectors;
|
||||||
sectorId++)
|
sectorId++)
|
||||||
{
|
{
|
||||||
const auto& sector = image.get(track, side, sectorId);
|
const auto& sector = image.get(track, side, sectorId);
|
||||||
if (sector)
|
if (sector)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
|
|
||||||
unsigned sectorFileOffset;
|
unsigned sectorFileOffset;
|
||||||
for (int track = 0; track < geometry.numTracks * geometry.numSides;
|
for (int track = 0; track < geometry.numTracks * geometry.numSides;
|
||||||
track++)
|
track++)
|
||||||
{
|
{
|
||||||
int side = (track < geometry.numTracks) ? 0 : 1;
|
int side = (track < geometry.numTracks) ? 0 : 1;
|
||||||
for (int sectorId = 0; sectorId < geometry.numSectors; sectorId++)
|
for (int sectorId = 0; sectorId < geometry.numSectors; sectorId++)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public:
|
|||||||
|
|
||||||
unsigned sectorFileOffset;
|
unsigned sectorFileOffset;
|
||||||
for (int track = 0; track < geometry.numTracks * geometry.numSides;
|
for (int track = 0; track < geometry.numTracks * geometry.numSides;
|
||||||
track++)
|
track++)
|
||||||
{
|
{
|
||||||
int side = (track < geometry.numTracks) ? 0 : 1;
|
int side = (track < geometry.numTracks) ? 0 : 1;
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ class CbmfsFilesystem : public Filesystem
|
|||||||
usedBlocks = 0;
|
usedBlocks = 0;
|
||||||
unsigned block = 0;
|
unsigned block = 0;
|
||||||
for (int track = 0; track < globalConfig()->layout().tracks();
|
for (int track = 0; track < globalConfig()->layout().tracks();
|
||||||
track++)
|
track++)
|
||||||
{
|
{
|
||||||
uint8_t blocks = br.read_8();
|
uint8_t blocks = br.read_8();
|
||||||
uint32_t bitmap = br.read_le24();
|
uint32_t bitmap = br.read_le24();
|
||||||
|
|||||||
@@ -44,14 +44,14 @@ public:
|
|||||||
|
|
||||||
void flushChanges() override
|
void flushChanges() override
|
||||||
{
|
{
|
||||||
_writer->writeMappedImage(*_image);
|
_writer->writeImage(*_image);
|
||||||
_changed = false;
|
_changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void discardChanges() override
|
void discardChanges() override
|
||||||
{
|
{
|
||||||
if (_reader)
|
if (_reader)
|
||||||
_image = _reader->readMappedImage();
|
_image = _reader->readImage();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_image = std::make_shared<Image>();
|
_image = std::make_shared<Image>();
|
||||||
|
|||||||
@@ -160,8 +160,8 @@ Filesystem::Filesystem(std::shared_ptr<SectorInterface> sectors):
|
|||||||
"information");
|
"information");
|
||||||
|
|
||||||
unsigned block = 0;
|
unsigned block = 0;
|
||||||
for (const auto& p :
|
for (const auto& p : Layout::getTrackOrdering(
|
||||||
Layout::getTrackOrdering(layout.tracks(), layout.sides()))
|
layout.filesystem_track_order(), layout.tracks(), layout.sides()))
|
||||||
{
|
{
|
||||||
int track = p.first;
|
int track = p.first;
|
||||||
int side = p.second;
|
int side = p.second;
|
||||||
|
|||||||
@@ -154,7 +154,4 @@ message FilesystemProto
|
|||||||
optional MicrodosProto microdos = 15;
|
optional MicrodosProto microdos = 15;
|
||||||
optional ZDosProto zdos = 16;
|
optional ZDosProto zdos = 16;
|
||||||
optional RolandFsProto roland = 17;
|
optional RolandFsProto roland = 17;
|
||||||
|
|
||||||
optional SectorListProto sector_order = 9
|
|
||||||
[ (help) = "specify the filesystem order of sectors" ];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ int mainWrite(int argc, const char* argv[])
|
|||||||
flags.parseFlagsWithConfigFiles(argc, argv, formats);
|
flags.parseFlagsWithConfigFiles(argc, argv, formats);
|
||||||
|
|
||||||
auto reader = ImageReader::create(globalConfig());
|
auto reader = ImageReader::create(globalConfig());
|
||||||
std::shared_ptr<Image> image = reader->readMappedImage();
|
std::shared_ptr<Image> image = reader->readImage();
|
||||||
|
|
||||||
auto encoder = Arch::createEncoder(globalConfig());
|
auto encoder = Arch::createEncoder(globalConfig());
|
||||||
auto fluxSink = FluxSink::create(globalConfig());
|
auto fluxSink = FluxSink::create(globalConfig());
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ option_group {
|
|||||||
format_type: FORMATTYPE_80TRACK
|
format_type: FORMATTYPE_80TRACK
|
||||||
tracks: 80
|
tracks: 80
|
||||||
sides: 2
|
sides: 2
|
||||||
order: HCS
|
image_track_order: HCS
|
||||||
|
filesystem_track_order: HCS
|
||||||
layoutdata {
|
layoutdata {
|
||||||
sector_size: 256
|
sector_size: 256
|
||||||
physical {
|
physical {
|
||||||
@@ -136,11 +137,15 @@ option_group {
|
|||||||
|
|
||||||
config {
|
config {
|
||||||
image_reader {
|
image_reader {
|
||||||
filesystem_sector_order: true
|
img {
|
||||||
|
filesystem_sector_order: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image_writer {
|
image_writer {
|
||||||
filesystem_sector_order: true
|
img {
|
||||||
|
filesystem_sector_order: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystem {
|
filesystem {
|
||||||
@@ -179,11 +184,15 @@ option_group {
|
|||||||
|
|
||||||
config {
|
config {
|
||||||
image_reader {
|
image_reader {
|
||||||
filesystem_sector_order: true
|
img {
|
||||||
|
filesystem_sector_order: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image_writer {
|
image_writer {
|
||||||
filesystem_sector_order: true
|
img {
|
||||||
|
filesystem_sector_order: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystem {
|
filesystem {
|
||||||
@@ -221,11 +230,15 @@ option_group {
|
|||||||
|
|
||||||
config {
|
config {
|
||||||
image_reader {
|
image_reader {
|
||||||
filesystem_sector_order: true
|
img {
|
||||||
|
filesystem_sector_order: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image_writer {
|
image_writer {
|
||||||
filesystem_sector_order: true
|
img {
|
||||||
|
filesystem_sector_order: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystem {
|
filesystem {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ formats = [
|
|||||||
"hplif",
|
"hplif",
|
||||||
"ibm",
|
"ibm",
|
||||||
"icl30",
|
"icl30",
|
||||||
|
"juku",
|
||||||
"mac",
|
"mac",
|
||||||
"micropolis",
|
"micropolis",
|
||||||
"ms2000",
|
"ms2000",
|
||||||
|
|||||||
99
src/formats/juku.textpb
Normal file
99
src/formats/juku.textpb
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
shortname: 'Juku E5104'
|
||||||
|
comment: 'CP/M'
|
||||||
|
|
||||||
|
documentation:
|
||||||
|
<<<
|
||||||
|
Juku E5104 is an Estonian school computer from late 1980s and
|
||||||
|
early 1990s. It was designed by EKTA in 1985, and starting
|
||||||
|
from 1988 produced in Narva "Baltijets" factory. Arguably
|
||||||
|
the school computer was technically outdated already when
|
||||||
|
released, but still occupies a precious spot in the memories
|
||||||
|
of a whole generation of Estonian IT professionals.
|
||||||
|
|
||||||
|
The system uses dual 5.25 inch ИЗОТ ЕС5323 (IZOT ES5323)
|
||||||
|
diskette drive with regular MFM encoded DSDD. The disks have
|
||||||
|
a sector skew factor 2 and tracks start from outside of the
|
||||||
|
diskette _for both sides_, which is a combination that somewhat
|
||||||
|
complicates reading CP/M filesystem content with common tools.
|
||||||
|
|
||||||
|
Mostly 800kB (786kB) DSDD disks were used, but there are also
|
||||||
|
400kB (386kB) SSDD floppies in circulation.
|
||||||
|
|
||||||
|
## References (all in Estonian)
|
||||||
|
|
||||||
|
- [How to read the content of Juku disks?](https://github.com/infoaed/juku3000/blob/master/docs/kettad.md)
|
||||||
|
- [List of recovered Juku software](https://github.com/infoaed/juku3000/blob/master/docs/tarkvara-kataloog.md)
|
||||||
|
- [System disks for E5104](https://elektroonikamuuseum.ee/juku_arvuti_tarkvara.html)
|
||||||
|
>>>
|
||||||
|
|
||||||
|
image_reader {
|
||||||
|
filename: "image.juk"
|
||||||
|
type: IMAGETYPE_IMG
|
||||||
|
}
|
||||||
|
|
||||||
|
image_writer {
|
||||||
|
filename: "image.juk"
|
||||||
|
type: IMAGETYPE_IMG
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder {
|
||||||
|
ibm {}
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder {
|
||||||
|
ibm {}
|
||||||
|
}
|
||||||
|
|
||||||
|
layout {
|
||||||
|
format_type: FORMATTYPE_80TRACK
|
||||||
|
tracks: 80
|
||||||
|
sides: 2
|
||||||
|
filesystem_track_order: HCS
|
||||||
|
layoutdata {
|
||||||
|
sector_size: 512
|
||||||
|
physical {
|
||||||
|
start_sector: 1
|
||||||
|
count: 10
|
||||||
|
}
|
||||||
|
filesystem {
|
||||||
|
start_sector: 1
|
||||||
|
count: 10
|
||||||
|
skew: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
option_group {
|
||||||
|
comment: "$formats"
|
||||||
|
|
||||||
|
option {
|
||||||
|
name: "800"
|
||||||
|
comment: '800kB 80-track 10-sector DSDD'
|
||||||
|
set_by_default: true
|
||||||
|
}
|
||||||
|
|
||||||
|
option {
|
||||||
|
name: "400"
|
||||||
|
comment: '400kB 80-track 10-sector SSDD'
|
||||||
|
|
||||||
|
config {
|
||||||
|
layout {
|
||||||
|
sides: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
filesystem {
|
||||||
|
type: CPMFS
|
||||||
|
cpmfs {
|
||||||
|
filesystem_start {
|
||||||
|
side: 0
|
||||||
|
track: 2
|
||||||
|
}
|
||||||
|
block_size: 4096
|
||||||
|
dir_entries: 128
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -124,7 +124,8 @@ option {
|
|||||||
layoutdata {
|
layoutdata {
|
||||||
sector_size: 275
|
sector_size: 275
|
||||||
}
|
}
|
||||||
order: HCS
|
filesystem_track_order: HCS
|
||||||
|
image_track_order: HCS
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder {
|
decoder {
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ layout {
|
|||||||
format_type: FORMATTYPE_80TRACK
|
format_type: FORMATTYPE_80TRACK
|
||||||
tracks: 80
|
tracks: 80
|
||||||
sides: 2
|
sides: 2
|
||||||
order: HCS
|
image_track_order: HCS
|
||||||
|
filesystem_track_order: HCS
|
||||||
swap_sides: true
|
swap_sides: true
|
||||||
layoutdata {
|
layoutdata {
|
||||||
sector_size: 1024
|
sector_size: 1024
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ public:
|
|||||||
[this]()
|
[this]()
|
||||||
{
|
{
|
||||||
auto image =
|
auto image =
|
||||||
GetContext().GetImageReader()->readMappedImage();
|
GetContext().GetImageReader()->readImage();
|
||||||
auto* encoder = GetContext().GetEncoder();
|
auto* encoder = GetContext().GetEncoder();
|
||||||
auto* fluxSink = GetContext().GetFluxSink();
|
auto* fluxSink = GetContext().GetFluxSink();
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ public:
|
|||||||
QueueJob(
|
QueueJob(
|
||||||
[image, this]()
|
[image, this]()
|
||||||
{
|
{
|
||||||
GetContext().GetImageWriter()->writeMappedImage(*image);
|
GetContext().GetImageWriter()->writeImage(*image);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (const ErrorException& e)
|
catch (const ErrorException& e)
|
||||||
|
|||||||
Reference in New Issue
Block a user