mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-24 11:11:02 -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;
|
||||
|
||||
for (unsigned offset = 0; offset < trackInfo->groupSize;
|
||||
offset += Layout::getHeadWidth())
|
||||
offset += Layout::getHeadWidth())
|
||||
{
|
||||
log(BeginReadOperationLogMessage{
|
||||
trackInfo->physicalTrack + offset, trackInfo->physicalSide});
|
||||
@@ -404,7 +404,7 @@ void writeTracks(FluxSink& fluxSink,
|
||||
for (;;)
|
||||
{
|
||||
for (int offset = 0; offset < trackInfo->groupSize;
|
||||
offset += Layout::getHeadWidth())
|
||||
offset += Layout::getHeadWidth())
|
||||
{
|
||||
unsigned physicalTrack = trackInfo->physicalTrack + offset;
|
||||
|
||||
@@ -734,7 +734,7 @@ void readDiskCommand(
|
||||
if (globalConfig()->decoder().has_write_csv_to())
|
||||
writer.writeCsv(
|
||||
*diskflux->image, globalConfig()->decoder().write_csv_to());
|
||||
writer.writeMappedImage(*diskflux->image);
|
||||
writer.writeImage(*diskflux->image);
|
||||
}
|
||||
|
||||
void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink)
|
||||
|
||||
@@ -46,7 +46,7 @@ class Flag
|
||||
{
|
||||
public:
|
||||
Flag(const std::vector<std::string>& names, const std::string helptext);
|
||||
virtual ~Flag(){};
|
||||
virtual ~Flag() {};
|
||||
|
||||
void checkInitialised() const
|
||||
{
|
||||
|
||||
@@ -22,8 +22,9 @@ message LayoutProto
|
||||
enum Order
|
||||
{
|
||||
UNDEFINED = 0;
|
||||
CHS = 1;
|
||||
HCS = 2;
|
||||
CHS = 1; // sort by cylinder, then head, then sector -- libdsk 'alt'
|
||||
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
|
||||
@@ -54,10 +55,12 @@ message LayoutProto
|
||||
[ default = 0, (help) = "number of tracks in image" ];
|
||||
optional int32 sides = 3
|
||||
[ 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" ];
|
||||
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" ];
|
||||
optional FormatType format_type = 6
|
||||
optional FormatType format_type = 7
|
||||
[ default = FORMATTYPE_UNKNOWN, (help) = "Format type of image" ];
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "lib/data/sector.h"
|
||||
#include "lib/data/image.h"
|
||||
#include "lib/data/layout.h"
|
||||
#include "lib/config/config.h"
|
||||
|
||||
Image::Image() {}
|
||||
|
||||
@@ -25,7 +26,8 @@ void Image::clear()
|
||||
void Image::createBlankImage()
|
||||
{
|
||||
clear();
|
||||
for (const auto& trackAndHead : Layout::getTrackOrdering())
|
||||
for (const auto& trackAndHead : Layout::getTrackOrdering(
|
||||
globalConfig()->layout().filesystem_track_order()))
|
||||
{
|
||||
unsigned track = trackAndHead.first;
|
||||
unsigned side = trackAndHead.second;
|
||||
|
||||
@@ -108,21 +108,21 @@ void Layout::getBounds(
|
||||
}
|
||||
|
||||
std::vector<std::pair<int, int>> Layout::getTrackOrdering(
|
||||
unsigned guessedTracks, unsigned guessedSides)
|
||||
LayoutProto::Order ordering, unsigned guessedTracks, unsigned guessedSides)
|
||||
{
|
||||
auto layout = globalConfig()->layout();
|
||||
int tracks = layout.has_tracks() ? layout.tracks() : guessedTracks;
|
||||
int sides = layout.has_sides() ? layout.sides() : guessedSides;
|
||||
|
||||
std::vector<std::pair<int, int>> ordering;
|
||||
switch (layout.order())
|
||||
std::vector<std::pair<int, int>> trackList;
|
||||
switch (ordering)
|
||||
{
|
||||
case LayoutProto::CHS:
|
||||
{
|
||||
for (int track = 0; track < tracks; track++)
|
||||
{
|
||||
for (int side = 0; side < sides; side++)
|
||||
ordering.push_back(std::make_pair(track, side));
|
||||
trackList.push_back(std::make_pair(track, side));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -132,16 +132,30 @@ std::vector<std::pair<int, int>> Layout::getTrackOrdering(
|
||||
for (int side = 0; side < sides; side++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
default:
|
||||
error("LAYOUT: invalid track ordering");
|
||||
error("LAYOUT: invalid track trackList");
|
||||
}
|
||||
|
||||
return ordering;
|
||||
return trackList;
|
||||
}
|
||||
|
||||
std::vector<unsigned> Layout::expandSectorList(
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define LAYOUT_H
|
||||
|
||||
#include "lib/data/flux.h"
|
||||
#include "lib/config/layout.pb.h"
|
||||
|
||||
class SectorListProto;
|
||||
class TrackInfo;
|
||||
@@ -39,7 +40,9 @@ public:
|
||||
/* Returns a series of <track, side> pairs representing the filesystem
|
||||
* ordering of the disk, in logical numbers. */
|
||||
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. */
|
||||
static std::shared_ptr<const TrackInfo> getLayoutOfTrack(
|
||||
|
||||
@@ -98,10 +98,10 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void beginTrack(){};
|
||||
virtual void beginTrack() {};
|
||||
virtual nanoseconds_t advanceToNextRecord() = 0;
|
||||
virtual void decodeSectorRecord() = 0;
|
||||
virtual void decodeDataRecord(){};
|
||||
virtual void decodeDataRecord() {};
|
||||
|
||||
const DecoderProto& _config;
|
||||
std::shared_ptr<TrackDataFlux> _trackdata;
|
||||
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
auto physical = layoutdata->mutable_physical();
|
||||
|
||||
for (int sectorInTrack = 0; sectorInTrack < currentSectorsInTrack;
|
||||
sectorInTrack++)
|
||||
sectorInTrack++)
|
||||
{
|
||||
Bytes sectorHeader(0x10);
|
||||
inputFile.read(
|
||||
|
||||
@@ -63,26 +63,3 @@ std::unique_ptr<ImageReader> ImageReader::create(const ImageReaderProto& 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:
|
||||
ImageReader(const ImageReaderProto& config);
|
||||
virtual ~ImageReader(){};
|
||||
virtual ~ImageReader() {};
|
||||
|
||||
public:
|
||||
static std::unique_ptr<ImageReader> create(Config& config);
|
||||
@@ -51,15 +51,10 @@ public:
|
||||
return _extraConfig;
|
||||
}
|
||||
|
||||
/* Directly reads the image. */
|
||||
/* Reads the image. */
|
||||
|
||||
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:
|
||||
const ImageReaderProto& _config;
|
||||
ConfigProto _extraConfig;
|
||||
|
||||
@@ -2,7 +2,12 @@ syntax = "proto2";
|
||||
|
||||
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 ImdInputProto {}
|
||||
@@ -15,16 +20,12 @@ message FdiInputProto {}
|
||||
message D88InputProto {}
|
||||
message NfdInputProto {}
|
||||
|
||||
// NEXT_TAG: 15
|
||||
// NEXT_TAG: 14
|
||||
message ImageReaderProto
|
||||
{
|
||||
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"];
|
||||
|
||||
optional ImgInputOutputProto img = 2;
|
||||
|
||||
@@ -301,7 +301,7 @@ public:
|
||||
|
||||
switch (Status_Sector)
|
||||
{
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
/* 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:
|
||||
* Statussen fluxengine | Status IMD
|
||||
|
||||
@@ -31,8 +31,11 @@ public:
|
||||
"IMG: bad configuration; did you remember to set the "
|
||||
"tracks, sides and trackdata fields in the layout?");
|
||||
|
||||
bool in_filesystem_order = _config.img().filesystem_sector_order();
|
||||
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 side = p.second;
|
||||
@@ -46,6 +49,9 @@ public:
|
||||
Bytes data(trackLayout->sectorSize);
|
||||
inputFile.read((char*)data.begin(), data.size());
|
||||
|
||||
if (in_filesystem_order)
|
||||
sectorId =
|
||||
trackLayout->filesystemToNaturalSectorMap.at(sectorId);
|
||||
const auto& sector = image->put(track, side, sectorId);
|
||||
sector->status = Sector::OK;
|
||||
sector->data = data;
|
||||
|
||||
@@ -65,15 +65,15 @@ public:
|
||||
uint32_t trackOffset = 688;
|
||||
|
||||
for (int track = 0; track < geometry.numTracks * geometry.numSides;
|
||||
track++)
|
||||
track++)
|
||||
{
|
||||
headerWriter.seek(0x20 + 4 * track);
|
||||
headerWriter.write_le32(trackOffset);
|
||||
int side = track & 1;
|
||||
std::vector<std::shared_ptr<const Sector>> sectors;
|
||||
for (int sectorId = geometry.firstSector;
|
||||
sectorId <= geometry.numSectors;
|
||||
sectorId++)
|
||||
sectorId <= geometry.numSectors;
|
||||
sectorId++)
|
||||
{
|
||||
const auto& sector = image.get(track >> 1, side, sectorId);
|
||||
if (sector)
|
||||
|
||||
@@ -173,27 +173,3 @@ void ImageWriter::printMap(const Image& image)
|
||||
<< 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:
|
||||
ImageWriter(const ImageWriterProto& config);
|
||||
virtual ~ImageWriter(){};
|
||||
virtual ~ImageWriter() {};
|
||||
|
||||
public:
|
||||
static std::unique_ptr<ImageWriter> create(Config& config);
|
||||
@@ -37,11 +37,8 @@ public:
|
||||
void writeCsv(const Image& sectors, const std::string& filename);
|
||||
|
||||
/* Writes a raw image. */
|
||||
virtual void writeImage(const Image& sectors) = 0;
|
||||
|
||||
/* Writes an image applying any optional mapping from disk sector numbering
|
||||
* to filesystem sector numbering. */
|
||||
void writeMappedImage(const Image& sectors);
|
||||
virtual void writeImage(const Image& sectors) = 0;
|
||||
|
||||
protected:
|
||||
const ImageWriterProto& _config;
|
||||
|
||||
@@ -67,12 +67,8 @@ message ImdOutputProto
|
||||
message ImageWriterProto
|
||||
{
|
||||
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" ];
|
||||
|
||||
optional ImgInputOutputProto img = 2;
|
||||
|
||||
@@ -354,7 +354,7 @@ public:
|
||||
// determine how the optional cylinder map looks like
|
||||
// write the corresponding logical ID
|
||||
for (int sectorId = 0; sectorId < numSectorsinTrack;
|
||||
sectorId++)
|
||||
sectorId++)
|
||||
{
|
||||
// const auto& sector = sectors.get(track, head,
|
||||
// sectorId);
|
||||
@@ -372,7 +372,7 @@ public:
|
||||
// determine how the optional head map looks like
|
||||
// write the corresponding logical ID
|
||||
for (int sectorId = 0; sectorId < numSectorsinTrack;
|
||||
sectorId++)
|
||||
sectorId++)
|
||||
{
|
||||
// const auto& sector = sectors.get(track, head,
|
||||
// sectorId);
|
||||
@@ -440,7 +440,7 @@ public:
|
||||
}
|
||||
switch (sector->status)
|
||||
{
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
/* 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:
|
||||
* Statussen fluxengine | Status IMD
|
||||
|
||||
@@ -31,7 +31,12 @@ public:
|
||||
if (!outputFile.is_open())
|
||||
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 side = p.second;
|
||||
@@ -39,6 +44,10 @@ public:
|
||||
auto trackLayout = Layout::getLayoutOfTrack(track, side);
|
||||
for (int sectorId : trackLayout->naturalSectorOrder)
|
||||
{
|
||||
if (in_filesystem_order)
|
||||
sectorId =
|
||||
trackLayout->filesystemToNaturalSectorMap.at(sectorId);
|
||||
|
||||
const auto& sector = image.get(track, side, sectorId);
|
||||
if (sector)
|
||||
sector->data.slice(0, trackLayout->sectorSize)
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
|
||||
int actualSectors = 0;
|
||||
for (int sectorId = 0; sectorId < geometry.numSectors;
|
||||
sectorId++)
|
||||
sectorId++)
|
||||
{
|
||||
const auto& sector = image.get(track, side, sectorId);
|
||||
if (sector)
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
trackHeaderWriter.write_le16(0); /* approximate track length */
|
||||
|
||||
for (int sectorId = 0; sectorId < geometry.numSectors;
|
||||
sectorId++)
|
||||
sectorId++)
|
||||
{
|
||||
const auto& sector = image.get(track, side, sectorId);
|
||||
if (sector)
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
unsigned sectorFileOffset;
|
||||
for (int track = 0; track < geometry.numTracks * geometry.numSides;
|
||||
track++)
|
||||
track++)
|
||||
{
|
||||
int side = (track < geometry.numTracks) ? 0 : 1;
|
||||
for (int sectorId = 0; sectorId < geometry.numSectors; sectorId++)
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
|
||||
unsigned sectorFileOffset;
|
||||
for (int track = 0; track < geometry.numTracks * geometry.numSides;
|
||||
track++)
|
||||
track++)
|
||||
{
|
||||
int side = (track < geometry.numTracks) ? 0 : 1;
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ class CbmfsFilesystem : public Filesystem
|
||||
usedBlocks = 0;
|
||||
unsigned block = 0;
|
||||
for (int track = 0; track < globalConfig()->layout().tracks();
|
||||
track++)
|
||||
track++)
|
||||
{
|
||||
uint8_t blocks = br.read_8();
|
||||
uint32_t bitmap = br.read_le24();
|
||||
|
||||
@@ -44,14 +44,14 @@ public:
|
||||
|
||||
void flushChanges() override
|
||||
{
|
||||
_writer->writeMappedImage(*_image);
|
||||
_writer->writeImage(*_image);
|
||||
_changed = false;
|
||||
}
|
||||
|
||||
void discardChanges() override
|
||||
{
|
||||
if (_reader)
|
||||
_image = _reader->readMappedImage();
|
||||
_image = _reader->readImage();
|
||||
else
|
||||
{
|
||||
_image = std::make_shared<Image>();
|
||||
|
||||
@@ -160,8 +160,8 @@ Filesystem::Filesystem(std::shared_ptr<SectorInterface> sectors):
|
||||
"information");
|
||||
|
||||
unsigned block = 0;
|
||||
for (const auto& p :
|
||||
Layout::getTrackOrdering(layout.tracks(), layout.sides()))
|
||||
for (const auto& p : Layout::getTrackOrdering(
|
||||
layout.filesystem_track_order(), layout.tracks(), layout.sides()))
|
||||
{
|
||||
int track = p.first;
|
||||
int side = p.second;
|
||||
|
||||
@@ -154,7 +154,4 @@ message FilesystemProto
|
||||
optional MicrodosProto microdos = 15;
|
||||
optional ZDosProto zdos = 16;
|
||||
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);
|
||||
|
||||
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 fluxSink = FluxSink::create(globalConfig());
|
||||
|
||||
@@ -96,7 +96,8 @@ option_group {
|
||||
format_type: FORMATTYPE_80TRACK
|
||||
tracks: 80
|
||||
sides: 2
|
||||
order: HCS
|
||||
image_track_order: HCS
|
||||
filesystem_track_order: HCS
|
||||
layoutdata {
|
||||
sector_size: 256
|
||||
physical {
|
||||
@@ -136,11 +137,15 @@ option_group {
|
||||
|
||||
config {
|
||||
image_reader {
|
||||
filesystem_sector_order: true
|
||||
img {
|
||||
filesystem_sector_order: true
|
||||
}
|
||||
}
|
||||
|
||||
image_writer {
|
||||
filesystem_sector_order: true
|
||||
img {
|
||||
filesystem_sector_order: true
|
||||
}
|
||||
}
|
||||
|
||||
filesystem {
|
||||
@@ -179,11 +184,15 @@ option_group {
|
||||
|
||||
config {
|
||||
image_reader {
|
||||
filesystem_sector_order: true
|
||||
img {
|
||||
filesystem_sector_order: true
|
||||
}
|
||||
}
|
||||
|
||||
image_writer {
|
||||
filesystem_sector_order: true
|
||||
img {
|
||||
filesystem_sector_order: true
|
||||
}
|
||||
}
|
||||
|
||||
filesystem {
|
||||
@@ -221,11 +230,15 @@ option_group {
|
||||
|
||||
config {
|
||||
image_reader {
|
||||
filesystem_sector_order: true
|
||||
img {
|
||||
filesystem_sector_order: true
|
||||
}
|
||||
}
|
||||
|
||||
image_writer {
|
||||
filesystem_sector_order: true
|
||||
img {
|
||||
filesystem_sector_order: true
|
||||
}
|
||||
}
|
||||
|
||||
filesystem {
|
||||
|
||||
@@ -23,6 +23,7 @@ formats = [
|
||||
"hplif",
|
||||
"ibm",
|
||||
"icl30",
|
||||
"juku",
|
||||
"mac",
|
||||
"micropolis",
|
||||
"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 {
|
||||
sector_size: 275
|
||||
}
|
||||
order: HCS
|
||||
filesystem_track_order: HCS
|
||||
image_track_order: HCS
|
||||
}
|
||||
|
||||
decoder {
|
||||
|
||||
@@ -38,7 +38,8 @@ layout {
|
||||
format_type: FORMATTYPE_80TRACK
|
||||
tracks: 80
|
||||
sides: 2
|
||||
order: HCS
|
||||
image_track_order: HCS
|
||||
filesystem_track_order: HCS
|
||||
swap_sides: true
|
||||
layoutdata {
|
||||
sector_size: 1024
|
||||
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
[this]()
|
||||
{
|
||||
auto image =
|
||||
GetContext().GetImageReader()->readMappedImage();
|
||||
GetContext().GetImageReader()->readImage();
|
||||
auto* encoder = GetContext().GetEncoder();
|
||||
auto* fluxSink = GetContext().GetFluxSink();
|
||||
|
||||
@@ -260,7 +260,7 @@ public:
|
||||
QueueJob(
|
||||
[image, this]()
|
||||
{
|
||||
GetContext().GetImageWriter()->writeMappedImage(*image);
|
||||
GetContext().GetImageWriter()->writeImage(*image);
|
||||
});
|
||||
}
|
||||
catch (const ErrorException& e)
|
||||
|
||||
Reference in New Issue
Block a user