Another massive overhaul to rip out the last remaining bits of Layout.

This commit is contained in:
David Given
2025-10-10 00:21:47 +02:00
parent 8f047f842e
commit 97bb563ba0
46 changed files with 508 additions and 694 deletions

View File

@@ -107,7 +107,8 @@ public:
Sector::DATA_MISSING; /* unintuitive but correct */
if (_sector->logicalHead == 1)
_sector->logicalCylinder -= _config.apple2().side_one_track_offset();
_sector->logicalCylinder -=
_config.apple2().side_one_track_offset();
/* Sanity check. */

View File

@@ -207,16 +207,14 @@ public:
_sector->status =
(wantCrc == gotCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
auto layout = Layout::getLayoutOfTrack(
_sector->logicalCylinder, _sector->logicalHead);
if (_currentSectorSize != layout->sectorSize)
if (_currentSectorSize != _ltl->sectorSize)
std::cerr << fmt::format(
"Warning: configured sector size for t{}.h{}.s{} is {} bytes "
"but that seen on disk is {} bytes\n",
_sector->logicalCylinder,
_sector->logicalHead,
_sector->logicalSector,
layout->sectorSize,
_ltl->sectorSize,
_currentSectorSize);
}

View File

@@ -359,7 +359,7 @@ static ReadGroupResult readGroup(const DiskLayout& diskLayout,
ReadGroupResult rgr = {BAD_AND_CAN_NOT_RETRY};
for (unsigned offset = 0; offset < ltl->groupSize;
offset += Layout::getHeadWidth())
offset += diskLayout.headWidth)
{
unsigned physicalCylinder = ltl->physicalCylinder + offset;
unsigned physicalHead = ltl->physicalHead;
@@ -578,7 +578,6 @@ void writeDiskCommand(const DiskLayout& diskLayout,
{
auto chs = std::ranges::views::keys(diskLayout.layoutByLogicalLocation) |
std::ranges::to<std::vector>();
auto trackinfos = Layout::getLayoutOfTracksPhysical(physicalLocations);
if (fluxSource && decoder)
writeTracksAndVerify(
diskLayout, fluxSink, encoder, *fluxSource, *decoder, image, chs);

View File

@@ -22,21 +22,6 @@ void Image::clear()
_geometry = {0, 0, 0};
}
void Image::createBlankImage()
{
clear();
for (const auto& trackAndHead : Layout::getTrackOrdering(
globalConfig()->layout().filesystem_track_order()))
{
unsigned track = trackAndHead.first;
unsigned side = trackAndHead.second;
auto trackLayout = Layout::getLayoutOfTrack(track, side);
Bytes blank(trackLayout->sectorSize);
for (unsigned sectorId : trackLayout->naturalSectorOrder)
put(track, side, sectorId)->data = blank;
}
}
bool Image::empty() const
{
return _sectors.empty();
@@ -67,7 +52,7 @@ void Image::erase(const LogicalLocation& location)
_sectors.erase(location);
}
void Image::addMissingSectors(const DiskLayout& diskLayout)
void Image::addMissingSectors(const DiskLayout& diskLayout, bool populated)
{
for (auto& location : diskLayout.logicalSectorLocationsInFilesystemOrder)
if (!_sectors.contains(location))
@@ -75,7 +60,12 @@ void Image::addMissingSectors(const DiskLayout& diskLayout)
auto& ltl = diskLayout.layoutByLogicalLocation.at(
{location.logicalCylinder, location.logicalHead});
auto sector = std::make_shared<Sector>(location);
sector->status = Sector::MISSING;
if (populated)
sector->data = Bytes(ltl->sectorSize);
else
sector->status = Sector::MISSING;
_sectors[location] = sector;
}
calculateSize();

View File

@@ -105,7 +105,7 @@ public:
erase({cylinder, head, sector});
}
void addMissingSectors(const DiskLayout& layout);
void addMissingSectors(const DiskLayout& layout, bool populated = false);
const_iterator begin() const
{

View File

@@ -56,88 +56,10 @@ static unsigned getTrackStep(const ConfigProto& config = globalConfig())
return 1;
}
unsigned Layout::remapCylinderPhysicalToLogical(unsigned ptrack)
static std::vector<CylinderHead> getTrackOrdering(
LayoutProto::Order ordering, unsigned tracks, unsigned sides)
{
return (ptrack - globalConfig()->drive().head_bias()) / getTrackStep();
}
unsigned Layout::remapCylinderLogicalToPhysical(unsigned ltrack)
{
return globalConfig()->drive().head_bias() + ltrack * getTrackStep();
}
unsigned Layout::remapHeadPhysicalToLogical(unsigned pside)
{
return pside ^ globalConfig()->layout().swap_sides();
}
unsigned Layout::remapHeadLogicalToPhysical(unsigned lside)
{
return lside ^ globalConfig()->layout().swap_sides();
}
std::vector<CylinderHead> Layout::computePhysicalLocations()
{
if (!globalConfig()->tracks().empty())
return parseCylinderHeadsString(globalConfig()->tracks());
std::set<unsigned> tracks = iterate(0, globalConfig()->layout().tracks());
std::set<unsigned> heads = iterate(0, globalConfig()->layout().sides());
std::vector<CylinderHead> locations;
for (unsigned logicalCylinder : tracks)
for (unsigned logicalHead : heads)
locations.push_back(
CylinderHead{remapCylinderLogicalToPhysical(logicalCylinder),
remapHeadLogicalToPhysical(logicalHead)});
return locations;
}
std::vector<CylinderHead> Layout::computeLogicalLocations()
{
if (!globalConfig()->tracks().empty())
return parseCylinderHeadsString(globalConfig()->tracks());
std::set<unsigned> tracks = iterate(0, globalConfig()->layout().tracks());
std::set<unsigned> heads = iterate(0, globalConfig()->layout().sides());
std::vector<CylinderHead> locations;
for (unsigned logicalCylinder : tracks)
for (unsigned logicalHead : heads)
locations.push_back(CylinderHead{logicalCylinder, logicalHead});
return locations;
}
Layout::LayoutBounds Layout::getBounds(
const std::vector<CylinderHead>& locations)
{
LayoutBounds r{.minCylinder = INT_MAX,
.maxCylinder = INT_MIN,
.minHead = INT_MAX,
.maxHead = INT_MIN};
for (const auto& ti : locations)
{
r.minCylinder = std::min<int>(r.minCylinder, ti.cylinder);
r.maxCylinder = std::max<int>(r.maxCylinder, ti.cylinder);
r.minHead = std::min<int>(r.minHead, ti.head);
r.maxHead = std::max<int>(r.maxHead, ti.head);
}
return r;
}
std::vector<std::pair<unsigned, unsigned>> getTrackOrdering(
const ConfigProto& config,
LayoutProto::Order ordering,
unsigned tracks,
unsigned sides)
{
auto layout = config.layout();
std::vector<std::pair<unsigned, unsigned>> trackList;
std::vector<CylinderHead> trackList;
switch (ordering)
{
case LayoutProto::CHS:
@@ -145,7 +67,7 @@ std::vector<std::pair<unsigned, unsigned>> getTrackOrdering(
for (unsigned track = 0; track < tracks; track++)
{
for (unsigned side = 0; side < sides; side++)
trackList.push_back(std::make_pair(track, side));
trackList.push_back({track, side});
}
break;
}
@@ -155,7 +77,7 @@ std::vector<std::pair<unsigned, unsigned>> getTrackOrdering(
for (unsigned side = 0; side < sides; side++)
{
for (unsigned track = 0; track < tracks; track++)
trackList.push_back(std::make_pair(track, side));
trackList.push_back({track, side});
}
break;
}
@@ -166,10 +88,10 @@ std::vector<std::pair<unsigned, unsigned>> getTrackOrdering(
{
if (side == 0)
for (unsigned track = 0; track < tracks; track++)
trackList.push_back(std::make_pair(track, side));
trackList.push_back({track, side});
if (side == 1)
for (unsigned track = tracks; track >= 0; track--)
trackList.push_back(std::make_pair(track - 1, side));
trackList.push_back({track - 1, side});
}
break;
}
@@ -181,19 +103,7 @@ std::vector<std::pair<unsigned, unsigned>> getTrackOrdering(
return trackList;
}
std::vector<std::pair<unsigned, unsigned>> Layout::getTrackOrdering(
LayoutProto::Order ordering,
unsigned guessedCylinders,
unsigned guessedHeads)
{
auto& layout = globalConfig()->layout();
return ::getTrackOrdering(globalConfig(),
ordering,
layout.has_tracks() ? layout.tracks() : guessedCylinders,
layout.has_sides() ? layout.sides() : guessedHeads);
}
std::vector<unsigned> Layout::expandSectorList(
static std::vector<unsigned> expandSectorList(
const SectorListProto& sectorsProto)
{
std::vector<unsigned> sectors;
@@ -239,7 +149,7 @@ static const LayoutProto::LayoutdataProto getLayoutData(
unsigned logicalCylinder, unsigned logicalHead, const ConfigProto& config)
{
LayoutProto::LayoutdataProto layoutData;
for (const auto& f : globalConfig()->layout().layoutdata())
for (const auto& f : config.layout().layoutdata())
{
if (f.has_track() && f.has_up_to_track() &&
((logicalCylinder < f.track()) ||
@@ -256,113 +166,6 @@ static const LayoutProto::LayoutdataProto getLayoutData(
return layoutData;
}
std::shared_ptr<const TrackInfo> Layout::getLayoutOfTrack(
unsigned logicalCylinder, unsigned logicalHead)
{
auto trackInfo = std::make_shared<TrackInfo>();
auto layoutdata =
getLayoutData(logicalCylinder, logicalHead, globalConfig());
trackInfo->numCylinders = globalConfig()->layout().tracks();
trackInfo->numHeads = globalConfig()->layout().sides();
trackInfo->sectorSize = layoutdata.sector_size();
trackInfo->logicalCylinder = logicalCylinder;
trackInfo->logicalHead = logicalHead;
trackInfo->physicalCylinder =
remapCylinderLogicalToPhysical(logicalCylinder);
trackInfo->physicalHead =
logicalHead ^ globalConfig()->layout().swap_sides();
trackInfo->groupSize = getTrackStep();
trackInfo->diskSectorOrder = expandSectorList(layoutdata.physical());
trackInfo->naturalSectorOrder = trackInfo->diskSectorOrder;
std::sort(trackInfo->naturalSectorOrder.begin(),
trackInfo->naturalSectorOrder.end());
trackInfo->numSectors = trackInfo->naturalSectorOrder.size();
if (layoutdata.has_filesystem())
{
trackInfo->filesystemSectorOrder =
expandSectorList(layoutdata.filesystem());
if (trackInfo->filesystemSectorOrder.size() != trackInfo->numSectors)
error(
"filesystem sector order list doesn't contain the right "
"number of sectors");
}
else
trackInfo->filesystemSectorOrder = trackInfo->naturalSectorOrder;
for (int i = 0; i < trackInfo->numSectors; i++)
{
unsigned fid = trackInfo->naturalSectorOrder[i];
unsigned lid = trackInfo->filesystemSectorOrder[i];
trackInfo->filesystemToNaturalSectorMap[fid] = lid;
trackInfo->naturalToFilesystemSectorMap[lid] = fid;
}
return trackInfo;
}
std::shared_ptr<const TrackInfo> Layout::getLayoutOfTrackPhysical(
unsigned physicalCylinder, unsigned physicalHead)
{
return getLayoutOfTrack(remapCylinderPhysicalToLogical(physicalCylinder),
remapHeadPhysicalToLogical(physicalHead));
}
std::shared_ptr<const TrackInfo> Layout::getLayoutOfTrackPhysical(
const CylinderHead& physicalLocation)
{
return getLayoutOfTrackPhysical(
physicalLocation.cylinder, physicalLocation.head);
}
std::vector<std::shared_ptr<const TrackInfo>> Layout::getLayoutOfTracksPhysical(
const std::vector<CylinderHead>& physicalLocations)
{
std::vector<std::shared_ptr<const TrackInfo>> results;
for (const auto& physicalLocation : physicalLocations)
results.push_back(getLayoutOfTrackPhysical(physicalLocation));
return results;
}
int Layout::getHeadWidth()
{
switch (globalConfig()->drive().drive_type())
{
case DRIVETYPE_APPLE2:
return 4;
default:
return 1;
}
}
std::vector<LogicalLocation> Layout::computeFilesystemLogicalOrdering()
{
std::vector<LogicalLocation> result;
auto& layout = globalConfig()->layout();
if (layout.has_tracks() && layout.has_sides())
{
unsigned block = 0;
for (const auto& p :
Layout::getTrackOrdering(layout.filesystem_track_order(),
layout.tracks(),
layout.sides()))
{
unsigned track = p.first;
unsigned side = p.second;
auto trackLayout = Layout::getLayoutOfTrack(track, side);
if (trackLayout->numSectors == 0)
continue;
for (unsigned sectorId : trackLayout->filesystemSectorOrder)
result.push_back({track, side, sectorId});
}
}
return result;
}
DiskLayout::DiskLayout(const ConfigProto& config)
{
minPhysicalCylinder = minPhysicalHead = UINT_MAX;
@@ -375,7 +178,7 @@ DiskLayout::DiskLayout(const ConfigProto& config)
headBias = config.drive().head_bias();
swapSides = config.layout().swap_sides();
switch (globalConfig()->drive().drive_type())
switch (config.drive().drive_type())
{
case DRIVETYPE_APPLE2:
headWidth = 4;
@@ -411,10 +214,9 @@ DiskLayout::DiskLayout(const ConfigProto& config)
maxPhysicalHead = std::max(maxPhysicalHead, ltl->physicalHead);
auto layoutdata =
getLayoutData(logicalCylinder, logicalHead, globalConfig());
getLayoutData(logicalCylinder, logicalHead, config);
ltl->sectorSize = layoutdata.sector_size();
ltl->diskSectorOrder =
Layout::expandSectorList(layoutdata.physical());
ltl->diskSectorOrder = expandSectorList(layoutdata.physical());
ltl->naturalSectorOrder = ltl->diskSectorOrder;
std::sort(
ltl->naturalSectorOrder.begin(), ltl->naturalSectorOrder.end());
@@ -423,7 +225,7 @@ DiskLayout::DiskLayout(const ConfigProto& config)
if (layoutdata.has_filesystem())
{
ltl->filesystemSectorOrder =
Layout::expandSectorList(layoutdata.filesystem());
expandSectorList(layoutdata.filesystem());
if (ltl->filesystemSectorOrder.size() != ltl->numSectors)
error(
"filesystem sector order list doesn't contain the "
@@ -436,8 +238,8 @@ DiskLayout::DiskLayout(const ConfigProto& config)
{
unsigned fid = ltl->naturalSectorOrder[i];
unsigned lid = ltl->filesystemSectorOrder[i];
ltl->filesystemToNaturalSectorMap[fid] = lid;
ltl->naturalToFilesystemSectorMap[lid] = fid;
ltl->sectorIdToNaturalOrdering[i] = fid;
ltl->sectorIdToFilesystemOrdering[i] = fid;
}
};
@@ -449,7 +251,9 @@ DiskLayout::DiskLayout(const ConfigProto& config)
physicalHead++)
{
auto ptl = std::make_shared<PhysicalTrackLayout>();
layoutByPhysicalLocation[{physicalCylinder, physicalHead}] = ptl;
CylinderHead ch(physicalCylinder, physicalHead);
layoutByPhysicalLocation[ch] = ptl;
physicalLocations.push_back(ch);
ptl->physicalCylinder = physicalCylinder;
ptl->physicalHead = physicalHead;
@@ -464,31 +268,54 @@ DiskLayout::DiskLayout(const ConfigProto& config)
unsigned sectorOffset = 0;
unsigned blockId = 0;
for (auto [logicalCylinder, logicalHead] : getTrackOrdering(config,
config.layout().filesystem_track_order(),
for (auto& ch : getTrackOrdering(config.layout().filesystem_track_order(),
numLogicalCylinders,
numLogicalHeads))
{
const auto& ltl =
layoutByLogicalLocation[{logicalCylinder, logicalHead}];
const auto& ltl = layoutByLogicalLocation[ch];
logicalLocationsInFilesystemOrder.push_back(ch);
for (unsigned lid : ltl->filesystemSectorOrder)
{
LogicalLocation logicalLocation = {
logicalCylinder, logicalHead, lid};
logicalLocationBySectorOffset[sectorOffset] = logicalLocation;
sectorOffsetByLogicalLocation[logicalLocation] = sectorOffset;
LogicalLocation logicalLocation = {ch.cylinder, ch.head, lid};
logicalSectorLocationBySectorOffset[sectorOffset] = logicalLocation;
sectorOffsetByLogicalSectorLocation[logicalLocation] = sectorOffset;
logicalSectorLocationsInFilesystemOrder.push_back(logicalLocation);
sectorOffset += ltl->sectorSize;
logicalLocationByBlockId[blockId] = logicalLocation;
blockIdByLogicalLocation[logicalLocation] = blockId;
blockIdByLogicalSectorLocation[logicalLocation] = blockId;
blockId++;
}
}
}
static Layout::LayoutBounds getBounds(std::ranges::view auto keys)
static ConfigProto createTestConfig(unsigned numCylinders,
unsigned numHeads,
unsigned numSectors,
unsigned sectorSize)
{
Layout::LayoutBounds r{.minCylinder = INT_MAX,
ConfigProto config;
auto* layout = config.mutable_layout();
layout->set_tracks(numCylinders);
layout->set_sides(numHeads);
auto* layoutData = layout->add_layoutdata();
layoutData->set_sector_size(sectorSize);
layoutData->mutable_physical()->set_count(numSectors);
return config;
}
DiskLayout::DiskLayout(unsigned numCylinders,
unsigned numHeads,
unsigned numSectors,
unsigned sectorSize):
DiskLayout(createTestConfig(numCylinders, numHeads, numSectors, sectorSize))
{
}
static DiskLayout::LayoutBounds getBounds(std::ranges::view auto keys)
{
DiskLayout::LayoutBounds r{.minCylinder = INT_MAX,
.maxCylinder = INT_MIN,
.minHead = INT_MAX,
.maxHead = INT_MIN};
@@ -504,12 +331,12 @@ static Layout::LayoutBounds getBounds(std::ranges::view auto keys)
return r;
}
Layout::LayoutBounds DiskLayout::getPhysicalBounds() const
DiskLayout::LayoutBounds DiskLayout::getPhysicalBounds() const
{
return getBounds(std::views::keys(layoutByPhysicalLocation));
}
Layout::LayoutBounds DiskLayout::getLogicalBounds() const
DiskLayout::LayoutBounds DiskLayout::getLogicalBounds() const
{
return getBounds(std::views::keys(layoutByLogicalLocation));
}

View File

@@ -7,76 +7,6 @@
#include "lib/data/locations.h"
class ConfigProto;
class SectorListProto;
class TrackInfo;
class Layout
{
public:
/* Translates logical track numbering (the numbers actually written in the
* sector headers) to the track numbering on the actual drive, taking into
* account tpi settings.
*/
static unsigned remapCylinderPhysicalToLogical(unsigned physicalCylinder);
static unsigned remapCylinderLogicalToPhysical(unsigned logicalCylinder);
/* Translates logical side numbering (the numbers actually written in the
* sector headers) to the sides used on the actual drive.
*/
static unsigned remapHeadPhysicalToLogical(unsigned physicalHead);
static unsigned remapHeadLogicalToPhysical(unsigned logicalHead);
/* Uses the layout and current track and heads settings to determine
* which physical/logical tracks are going to be read from or written to.
*/
static std::vector<CylinderHead> computePhysicalLocations();
static std::vector<CylinderHead> computeLogicalLocations();
/* Uses the current layout to compute the filesystem's block order, in
* _logical_ tracks. */
static std::vector<LogicalLocation> computeFilesystemLogicalOrdering();
/* Given a list of CylinderHead locations, determines the minimum and
* maximum track and side settings. */
struct LayoutBounds
{
std::strong_ordering operator<=>(
const LayoutBounds& other) const = default;
int minCylinder, maxCylinder, minHead, maxHead;
};
static LayoutBounds getBounds(const std::vector<CylinderHead>& locations);
/* Returns a series of logical <track, side> pairs representing the
* filesystem ordering of the disk, in logical numbers. */
static std::vector<std::pair<unsigned, unsigned>> getTrackOrdering(
LayoutProto::Order ordering,
unsigned guessedCylinders = 0,
unsigned guessedHeads = 0);
/* Returns the layout of a given track. */
static std::shared_ptr<const TrackInfo> getLayoutOfTrack(
unsigned logicalCylinder, unsigned logicalHead);
/* Returns the layout of a given track via physical location. */
static std::shared_ptr<const TrackInfo> getLayoutOfTrackPhysical(
unsigned physicalCylinder, unsigned physicalHead);
/* Returns the layout of a given track via physical location. */
static std::shared_ptr<const TrackInfo> getLayoutOfTrackPhysical(
const CylinderHead& physicalLocation);
/* Returns the layouts of a multiple tracks via physical location. */
static std::vector<std::shared_ptr<const TrackInfo>>
getLayoutOfTracksPhysical(const std::vector<CylinderHead>& locations);
/* Expand a SectorList into the actual sector IDs. */
static std::vector<unsigned> expandSectorList(
const SectorListProto& sectorsProto);
/* Return the head width of the current drive. */
static int getHeadWidth();
};
struct LogicalTrackLayout
{
@@ -113,11 +43,11 @@ struct LogicalTrackLayout
* uses them. */
std::vector<unsigned> filesystemSectorOrder;
/* Mapping of filesystem order to natural order. */
std::map<unsigned, unsigned> filesystemToNaturalSectorMap;
/* Mapping of sector ID to filesystem ordering. */
std::map<unsigned, unsigned> sectorIdToFilesystemOrdering;
/* Mapping of natural order to filesystem order. */
std::map<unsigned, unsigned> naturalToFilesystemSectorMap;
/* Mapping of sector ID to natural ordering. */
std::map<unsigned, unsigned> sectorIdToNaturalOrdering;
};
struct PhysicalTrackLayout
@@ -140,29 +70,51 @@ class DiskLayout
public:
DiskLayout(const ConfigProto& config = globalConfig());
public:
unsigned headBias;
unsigned headWidth;
bool swapSides;
/* Makes a simplified layout for testing. */
unsigned minPhysicalCylinder, maxPhysicalCylinder;
unsigned minPhysicalHead, maxPhysicalHead;
unsigned groupSize;
DiskLayout(unsigned numCylinders,
unsigned numHeads,
unsigned numSectors,
unsigned sectorSize);
public:
/* Logical size. */
unsigned numLogicalCylinders;
unsigned numLogicalHeads;
/* Physical size and properties. */
unsigned minPhysicalCylinder, maxPhysicalCylinder;
unsigned minPhysicalHead, maxPhysicalHead;
unsigned groupSize; /* Number of physical cylinders per logical cylinder */
unsigned headBias; /* Physical cylinder offset */
unsigned headWidth; /* Width of the physical head */
bool swapSides; /* Whether sides need to be swapped */
/* Physical and logical layouts by location. */
std::map<CylinderHead, std::shared_ptr<const PhysicalTrackLayout>>
layoutByPhysicalLocation;
std::map<CylinderHead, std::shared_ptr<const LogicalTrackLayout>>
layoutByLogicalLocation;
/* Ordered lists of physical and logical locations. */
std::vector<CylinderHead> logicalLocations;
std::vector<CylinderHeadSector> physicalSectorLocationsInFilesystemOrder;
std::vector<CylinderHead> logicalLocationsInFilesystemOrder;
std::vector<CylinderHead> physicalLocations;
/* Ordered lists of sector locations, plus the reverse mapping. */
std::vector<LogicalLocation> logicalSectorLocationsInFilesystemOrder;
std::map<unsigned, LogicalLocation> logicalLocationBySectorOffset;
std::map<LogicalLocation, unsigned> sectorOffsetByLogicalLocation;
std::map<unsigned, LogicalLocation> logicalLocationByBlockId;
std::map<LogicalLocation, unsigned> blockIdByLogicalLocation;
std::map<LogicalLocation, unsigned> blockIdByLogicalSectorLocation;
std::vector<CylinderHeadSector> physicalSectorLocationsInFilesystemOrder;
/* Mapping from logical location to sector offset and back again. */
std::map<unsigned, LogicalLocation> logicalSectorLocationBySectorOffset;
std::map<LogicalLocation, unsigned> sectorOffsetByLogicalSectorLocation;
public:
unsigned remapCylinderPhysicalToLogical(unsigned physicalCylinder) const
@@ -185,8 +137,18 @@ public:
return logicalHead ^ swapSides;
}
Layout::LayoutBounds getPhysicalBounds() const;
Layout::LayoutBounds getLogicalBounds() const;
/* Given a list of CylinderHead locations, determines the minimum and
* maximum track and side settings. */
struct LayoutBounds
{
std::strong_ordering operator<=>(
const LayoutBounds& other) const = default;
int minCylinder, maxCylinder, minHead, maxHead;
};
LayoutBounds getPhysicalBounds() const;
LayoutBounds getLogicalBounds() const;
};
static std::shared_ptr<DiskLayout> createDiskLayout(

View File

@@ -89,11 +89,7 @@ std::shared_ptr<DecodedTrack> Decoder::decodeToSectors(
}
if (_sector->status != Sector::MISSING)
{
auto trackLayout = Layout::getLayoutOfTrack(
_sector->logicalCylinder, _sector->logicalHead);
_trackdata->sectors.push_back(_sector);
}
}
return _trackdata;

View File

@@ -36,8 +36,8 @@ std::vector<std::shared_ptr<const Sector>> Encoder::collectSectors(
for (unsigned sectorId : ltl.diskSectorOrder)
{
const auto& sector = getSector(
{ltl.logicalCylinder, ltl.logicalHead}, image, sectorId);
const auto& sector =
getSector({ltl.logicalCylinder, ltl.logicalHead}, image, sectorId);
if (!sector)
error("sector {}.{}.{} is missing from the image",
ltl.logicalCylinder,

View File

@@ -39,9 +39,11 @@ namespace
~A2RFluxSink()
{
auto physicalLocations = Layout::computePhysicalLocations();
// FIXME: should use a passed-in DiskLayout object.
auto diskLayout = createDiskLayout();
auto [minCylinder, maxCylinder, minHead, maxHead] =
Layout::getBounds(physicalLocations);
diskLayout->getPhysicalBounds();
_minCylinder = minCylinder;
_maxCylinder = maxCylinder;
_minHead = minHead;

View File

@@ -41,8 +41,10 @@ class ScpFluxSink : public FluxSink
public:
ScpFluxSink(const ScpFluxSinkProto& lconfig): _config(lconfig)
{
// FIXME: should use a passed-in DiskLayout object.
auto diskLayout = createDiskLayout();
auto [minCylinder, maxCylinder, minHead, maxHead] =
Layout::getBounds(Layout::computePhysicalLocations());
diskLayout->getPhysicalBounds();
_fileheader.file_id[0] = 'S';
_fileheader.file_id[1] = 'C';

View File

@@ -119,8 +119,14 @@ public:
auto keys = std::views::keys(_v2data);
std::vector<CylinderHead> chs{keys.begin(), keys.end()};
auto [minCylinder, maxCylinder, minHead, maxHead] =
Layout::getBounds(chs);
unsigned minCylinder = std::ranges::min(
chs | std::views::transform(&CylinderHead::cylinder));
unsigned maxCylinder = std::ranges::min(
chs | std::views::transform(&CylinderHead::cylinder));
unsigned minHead = std::ranges::min(
chs | std::views::transform(&CylinderHead::head));
unsigned maxHead = std::ranges::min(
chs | std::views::transform(&CylinderHead::head));
log("A2R: reading A2R {} file with {} cylinders and {} head{}",
(disktype == 1) ? "Apple II"
: (disktype == 2) ? "normal"

View File

@@ -62,7 +62,4 @@ std::unique_ptr<ImageReader> ImageReader::create(const ImageReaderProto& config)
}
}
ImageReader::ImageReader(const ImageReaderProto& config):
_config(config)
{
}
ImageReader::ImageReader(const ImageReaderProto& config): _config(config) {}

View File

@@ -31,28 +31,28 @@ public:
"IMG: bad configuration; did you remember to set the "
"tracks, sides and trackdata fields in the layout?");
const auto diskLayout = createDiskLayout();
bool in_filesystem_order = _config.img().filesystem_sector_order();
std::unique_ptr<Image> image(new Image);
for (const auto& p : Layout::getTrackOrdering(
in_filesystem_order ? layout.filesystem_track_order()
: layout.image_track_order()))
for (auto& logicalLocation :
in_filesystem_order ? diskLayout->logicalLocationsInFilesystemOrder
: diskLayout->logicalLocations)
{
int track = p.first;
int side = p.second;
auto& ltl = diskLayout->layoutByLogicalLocation.at(logicalLocation);
if (inputFile.eof())
break;
auto trackLayout = Layout::getLayoutOfTrack(track, side);
for (int sectorId : trackLayout->naturalSectorOrder)
for (unsigned sectorId : in_filesystem_order
? ltl->filesystemSectorOrder
: ltl->naturalSectorOrder)
{
Bytes data(trackLayout->sectorSize);
if (inputFile.eof())
break;
Bytes data(ltl->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);
const auto& sector = image->put(
logicalLocation.cylinder, logicalLocation.head, sectorId);
sector->status = Sector::OK;
sector->data = data;
}

View File

@@ -32,29 +32,25 @@ public:
if (!outputFile.is_open())
error("cannot open output file");
const auto diskLayout = createDiskLayout();
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))
for (auto& logicalLocation :
in_filesystem_order ? diskLayout->logicalLocationsInFilesystemOrder
: diskLayout->logicalLocations)
{
int track = p.first;
int side = p.second;
auto& ltl = diskLayout->layoutByLogicalLocation.at(logicalLocation);
auto trackLayout = Layout::getLayoutOfTrack(track, side);
for (int sectorId : trackLayout->naturalSectorOrder)
for (unsigned sectorId : in_filesystem_order
? ltl->filesystemSectorOrder
: ltl->naturalSectorOrder)
{
if (in_filesystem_order)
sectorId =
trackLayout->filesystemToNaturalSectorMap.at(sectorId);
const auto& sector = image.get(track, side, sectorId);
const auto& sector = image.get(
logicalLocation.cylinder, logicalLocation.head, sectorId);
if (sector)
sector->data.slice(0, trackLayout->sectorSize)
.writeTo(outputFile);
sector->data.slice(0, ltl->sectorSize).writeTo(outputFile);
else
outputFile.seekp(trackLayout->sectorSize, std::ios::cur);
outputFile.seekp(ltl->sectorSize, std::ios::cur);
}
}

View File

@@ -106,9 +106,10 @@ public:
class AcornDfsFilesystem : public Filesystem
{
public:
AcornDfsFilesystem(
const AcornDfsProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
AcornDfsFilesystem(const AcornDfsProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -178,7 +179,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createAcornDfsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<AcornDfsFilesystem>(config.acorndfs(), sectors);
return std::make_unique<AcornDfsFilesystem>(
config.acorndfs(), diskLayout, sectors);
}

View File

@@ -50,9 +50,10 @@ static std::string modeToString(long access)
class AmigaFfsFilesystem : public Filesystem
{
public:
AmigaFfsFilesystem(
const AmigaFfsProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
AmigaFfsFilesystem(const AmigaFfsProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -91,7 +92,8 @@ public:
dev.devType = DEVTYPE_FLOPDD;
dev.cylinders = globalConfig()->layout().tracks();
dev.heads = globalConfig()->layout().sides();
dev.sectors = Layout::getLayoutOfTrack(0, 0)->numSectors;
dev.sectors =
_diskLayout->layoutByLogicalLocation.at({0, 0})->numSectors;
adfInitDevice(&dev, nullptr, false);
int res = adfCreateFlop(&dev, (char*)volumeName.c_str(), 0);
if (res != RC_OK)
@@ -469,7 +471,10 @@ static BOOL adfIsDevNative(char*)
}
std::unique_ptr<Filesystem> Filesystem::createAmigaFfsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<AmigaFfsFilesystem>(config.amigaffs(), sectors);
return std::make_unique<AmigaFfsFilesystem>(
config.amigaffs(), diskLayout, sectors);
}

View File

@@ -43,9 +43,10 @@ class AppledosFilesystem : public Filesystem
};
public:
AppledosFilesystem(
const AppledosProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
AppledosFilesystem(const AppledosProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -175,7 +176,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createAppledosFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<AppledosFilesystem>(config.appledos(), sectors);
return std::make_unique<AppledosFilesystem>(
config.appledos(), diskLayout, sectors);
}

View File

@@ -226,8 +226,9 @@ class Brother120Filesystem : public Filesystem
{
public:
Brother120Filesystem(const Brother120FsProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -348,7 +349,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createBrother120Filesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<Brother120Filesystem>(config.brother120(), sectors);
return std::make_unique<Brother120Filesystem>(
config.brother120(), diskLayout, sectors);
}

View File

@@ -189,9 +189,10 @@ class CbmfsFilesystem : public Filesystem
};
public:
CbmfsFilesystem(
const CbmfsProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
CbmfsFilesystem(const CbmfsProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -281,7 +282,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createCbmfsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<CbmfsFilesystem>(config.cbmfs(), sectors);
return std::make_unique<CbmfsFilesystem>(
config.cbmfs(), diskLayout, sectors);
}

View File

@@ -183,9 +183,10 @@ class CpmFsFilesystem : public Filesystem, public HasBitmap, public HasMount
};
public:
CpmFsFilesystem(
const CpmFsProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
CpmFsFilesystem(const CpmFsProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -661,7 +662,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createCpmFsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<CpmFsFilesystem>(config.cpmfs(), sectors);
return std::make_unique<CpmFsFilesystem>(
config.cpmfs(), diskLayout, sectors);
}

View File

@@ -29,9 +29,10 @@ static std::string modeToString(BYTE attrib)
class FatFsFilesystem : public Filesystem
{
public:
FatFsFilesystem(
const FatFsProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
FatFsFilesystem(const FatFsProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -336,7 +337,10 @@ DWORD get_fattime(void)
}
std::unique_ptr<Filesystem> Filesystem::createFatFsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<FatFsFilesystem>(config.fatfs(), sectors);
return std::make_unique<FatFsFilesystem>(
config.fatfs(), diskLayout, sectors);
}

View File

@@ -132,8 +132,8 @@ private:
{
CylinderHead logicalLocation = {logicalCylinder, logicalSide};
auto& ltl = _diskLayout->layoutByLogicalLocation.at(logicalLocation);
auto trackdata = readAndDecodeTrack(
*_diskLayout, *_fluxSource, *_decoder, ltl);
auto trackdata =
readAndDecodeTrack(*_diskLayout, *_fluxSource, *_decoder, ltl);
for (const auto& sector : trackdata.sectors)
*_loadedSectors.put(logicalLocation, sector->logicalSector) =

View File

@@ -10,8 +10,10 @@
class ImageSectorInterface : public SectorInterface
{
public:
ImageSectorInterface(std::shared_ptr<ImageReader> reader,
std::shared_ptr<ImageWriter> writer):
ImageSectorInterface(const std::shared_ptr<const DiskLayout>& diskLayout,
const std::shared_ptr<ImageReader>& reader,
const std::shared_ptr<ImageWriter>& writer):
_diskLayout(diskLayout),
_reader(reader),
_writer(writer)
{
@@ -55,20 +57,23 @@ public:
else
{
_image = std::make_shared<Image>();
_image->createBlankImage();
_image->addMissingSectors(*_diskLayout);
}
_changed = false;
}
private:
std::shared_ptr<Image> _image;
std::shared_ptr<const DiskLayout> _diskLayout;
std::shared_ptr<ImageReader> _reader;
std::shared_ptr<ImageWriter> _writer;
bool _changed = false;
};
std::unique_ptr<SectorInterface> SectorInterface::createImageSectorInterface(
std::shared_ptr<ImageReader> reader, std::shared_ptr<ImageWriter> writer)
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<ImageReader> reader,
std::shared_ptr<ImageWriter> writer)
{
return std::make_unique<ImageSectorInterface>(reader, writer);
return std::make_unique<ImageSectorInterface>(diskLayout, reader, writer);
}

View File

@@ -134,9 +134,10 @@ class LifFilesystem : public Filesystem
};
public:
LifFilesystem(
const LifProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
LifFilesystem(const LifProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -288,7 +289,9 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createLifFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<LifFilesystem>(config.lif(), sectors);
return std::make_unique<LifFilesystem>(config.lif(), diskLayout, sectors);
}

View File

@@ -16,9 +16,10 @@ static MacHfsFilesystem* currentMacHfs;
class MacHfsFilesystem : public Filesystem
{
public:
MacHfsFilesystem(
const MacHfsProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
MacHfsFilesystem(const MacHfsProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -459,7 +460,10 @@ unsigned long os_write(void** priv, const void* buffer, unsigned long len)
}
std::unique_ptr<Filesystem> Filesystem::createMacHfsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<MacHfsFilesystem>(config.machfs(), sectors);
return std::make_unique<MacHfsFilesystem>(
config.machfs(), diskLayout, sectors);
}

View File

@@ -94,9 +94,10 @@ class MicrodosFilesystem : public Filesystem
};
public:
MicrodosFilesystem(
const MicrodosProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
MicrodosFilesystem(const MicrodosProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -217,7 +218,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createMicrodosFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<MicrodosFilesystem>(config.microdos(), sectors);
return std::make_unique<MicrodosFilesystem>(
config.microdos(), diskLayout, sectors);
}

View File

@@ -157,9 +157,10 @@ class PhileFilesystem : public Filesystem
};
public:
PhileFilesystem(
const PhileProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
PhileFilesystem(const PhileProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -293,7 +294,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createPhileFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<PhileFilesystem>(config.phile(), sectors);
return std::make_unique<PhileFilesystem>(
config.phile(), diskLayout, sectors);
}

View File

@@ -133,9 +133,10 @@ class ProdosFilesystem : public Filesystem
};
public:
ProdosFilesystem(
const ProdosProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
ProdosFilesystem(const ProdosProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -302,7 +303,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createProdosFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<ProdosFilesystem>(config.prodos(), sectors);
return std::make_unique<ProdosFilesystem>(
config.prodos(), diskLayout, sectors);
}

View File

@@ -93,9 +93,10 @@ private:
};
public:
RolandFsFilesystem(
const RolandFsProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
RolandFsFilesystem(const RolandFsProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -421,7 +422,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createRolandFsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<RolandFsFilesystem>(config.roland(), sectors);
return std::make_unique<RolandFsFilesystem>(
config.roland(), diskLayout, sectors);
}

View File

@@ -40,6 +40,7 @@ public:
static std::unique_ptr<SectorInterface> createMemorySectorInterface(
std::shared_ptr<Image> image);
static std::unique_ptr<SectorInterface> createImageSectorInterface(
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<ImageReader> reader,
std::shared_ptr<ImageWriter> writer);
static std::unique_ptr<SectorInterface> createFluxSectorInterface(

View File

@@ -132,9 +132,10 @@ class Smaky6Filesystem : public Filesystem
};
public:
Smaky6Filesystem(
const Smaky6FsProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
Smaky6Filesystem(const Smaky6FsProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -204,7 +205,10 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createSmaky6Filesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<Smaky6Filesystem>(config.smaky6(), sectors);
return std::make_unique<Smaky6Filesystem>(
config.smaky6(), diskLayout, sectors);
}

View File

@@ -151,82 +151,74 @@ void Filesystem::discardChanges()
_sectors->discardChanges();
}
Filesystem::Filesystem(std::shared_ptr<SectorInterface> sectors):
Filesystem::Filesystem(const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
_diskLayout(diskLayout),
_blockCount(diskLayout->logicalSectorLocationsInFilesystemOrder.size()),
_sectors(sectors)
{
auto& layout = globalConfig()->layout();
if (!layout.has_tracks() || !layout.has_sides())
error(
"FS: filesystem support cannot be used without concrete layout "
"information");
unsigned block = 0;
for (const auto& p : Layout::getTrackOrdering(
layout.filesystem_track_order(), layout.tracks(), layout.sides()))
{
int track = p.first;
int side = p.second;
auto trackLayout = Layout::getLayoutOfTrack(track, side);
if (trackLayout->numSectors == 0)
error(
"FS: filesystem support cannot be used without concrete "
"layout information");
for (int sectorId : trackLayout->filesystemSectorOrder)
_locations.push_back(std::make_tuple(track, side, sectorId));
}
}
std::unique_ptr<Filesystem> Filesystem::createFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image)
{
switch (config.type())
{
case FilesystemProto::BROTHER120:
return Filesystem::createBrother120Filesystem(config, image);
return Filesystem::createBrother120Filesystem(
config, diskLayout, image);
case FilesystemProto::ACORNDFS:
return Filesystem::createAcornDfsFilesystem(config, image);
return Filesystem::createAcornDfsFilesystem(
config, diskLayout, image);
case FilesystemProto::FATFS:
return Filesystem::createFatFsFilesystem(config, image);
return Filesystem::createFatFsFilesystem(config, diskLayout, image);
case FilesystemProto::CPMFS:
return Filesystem::createCpmFsFilesystem(config, image);
return Filesystem::createCpmFsFilesystem(config, diskLayout, image);
case FilesystemProto::AMIGAFFS:
return Filesystem::createAmigaFfsFilesystem(config, image);
return Filesystem::createAmigaFfsFilesystem(
config, diskLayout, image);
case FilesystemProto::MACHFS:
return Filesystem::createMacHfsFilesystem(config, image);
return Filesystem::createMacHfsFilesystem(
config, diskLayout, image);
case FilesystemProto::CBMFS:
return Filesystem::createCbmfsFilesystem(config, image);
return Filesystem::createCbmfsFilesystem(config, diskLayout, image);
case FilesystemProto::PRODOS:
return Filesystem::createProdosFilesystem(config, image);
return Filesystem::createProdosFilesystem(
config, diskLayout, image);
case FilesystemProto::APPLEDOS:
return Filesystem::createAppledosFilesystem(config, image);
return Filesystem::createAppledosFilesystem(
config, diskLayout, image);
case FilesystemProto::SMAKY6:
return Filesystem::createSmaky6Filesystem(config, image);
return Filesystem::createSmaky6Filesystem(
config, diskLayout, image);
case FilesystemProto::PHILE:
return Filesystem::createPhileFilesystem(config, image);
return Filesystem::createPhileFilesystem(config, diskLayout, image);
case FilesystemProto::LIF:
return Filesystem::createLifFilesystem(config, image);
return Filesystem::createLifFilesystem(config, diskLayout, image);
case FilesystemProto::MICRODOS:
return Filesystem::createMicrodosFilesystem(config, image);
return Filesystem::createMicrodosFilesystem(
config, diskLayout, image);
case FilesystemProto::ZDOS:
return Filesystem::createZDosFilesystem(config, image);
return Filesystem::createZDosFilesystem(config, diskLayout, image);
case FilesystemProto::ROLAND:
return Filesystem::createRolandFsFilesystem(config, image);
return Filesystem::createRolandFsFilesystem(
config, diskLayout, image);
default:
error("no filesystem configured");
@@ -237,6 +229,7 @@ std::unique_ptr<Filesystem> Filesystem::createFilesystem(
std::unique_ptr<Filesystem> Filesystem::createFilesystemFromConfig()
{
std::shared_ptr<SectorInterface> sectorInterface;
auto diskLayout = createDiskLayout(globalConfig());
if (globalConfig().hasFluxSource() || globalConfig().hasFluxSink())
{
std::shared_ptr<FluxSource> fluxSource;
@@ -253,7 +246,6 @@ std::unique_ptr<Filesystem> Filesystem::createFilesystemFromConfig()
fluxSink = FluxSink::create(globalConfig());
encoder = Arch::createEncoder(globalConfig());
}
auto diskLayout = createDiskLayout(globalConfig());
sectorInterface = SectorInterface::createFluxSectorInterface(
diskLayout, fluxSource, fluxSink, encoder, decoder);
}
@@ -267,11 +259,12 @@ std::unique_ptr<Filesystem> Filesystem::createFilesystemFromConfig()
if (globalConfig().hasImageWriter())
writer = ImageWriter::create(globalConfig());
sectorInterface =
SectorInterface::createImageSectorInterface(reader, writer);
sectorInterface = SectorInterface::createImageSectorInterface(
diskLayout, reader, writer);
}
return createFilesystem(globalConfig()->filesystem(), sectorInterface);
return createFilesystem(
globalConfig()->filesystem(), diskLayout, sectorInterface);
}
Bytes Filesystem::getSector(unsigned track, unsigned side, unsigned sector)
@@ -284,44 +277,40 @@ Bytes Filesystem::getSector(unsigned track, unsigned side, unsigned sector)
Bytes Filesystem::getLogicalSector(uint32_t number, uint32_t count)
{
if ((number + count) > _locations.size())
if ((number + count) > _blockCount)
throw BadFilesystemException(fmt::format(
"invalid filesystem: sector {} is out of bounds ({} maximum)",
number + count - 1,
_locations.size()));
_diskLayout->logicalSectorLocationsInFilesystemOrder.size()));
Bytes data;
ByteWriter bw(data);
for (int i = 0; i < count; i++)
{
auto& it = _locations[number + i];
int track = std::get<0>(it);
int side = std::get<1>(it);
int sector = std::get<2>(it);
auto trackLayout = Layout::getLayoutOfTrack(track, side);
bw += _sectors->get(track, side, sector)
->data.slice(0, trackLayout->sectorSize);
auto& [cylinder, head, sectorId] =
_diskLayout->logicalSectorLocationsInFilesystemOrder.at(number + i);
auto& ltl = _diskLayout->layoutByLogicalLocation.at({cylinder, head});
bw += _sectors->get(cylinder, head, sectorId)
->data.slice(0, ltl->sectorSize);
}
return data;
}
void Filesystem::putLogicalSector(uint32_t number, const Bytes& data)
{
if (number >= _locations.size())
if (number >= _blockCount)
throw BadFilesystemException(fmt::format(
"invalid filesystem: sector {} is out of bounds", number));
unsigned pos = 0;
while (pos < data.size())
{
auto& it = _locations[number];
int track = std::get<0>(it);
int side = std::get<1>(it);
int sector = std::get<2>(it);
int sectorSize = Layout::getLayoutOfTrack(track, side)->sectorSize;
_sectors->put(track, side, sector)->data = data.slice(pos, sectorSize);
pos += sectorSize;
auto& [cylinder, head, sectorId] =
_diskLayout->logicalSectorLocationsInFilesystemOrder.at(number);
auto& ltl = _diskLayout->layoutByLogicalLocation.at({cylinder, head});
_sectors->put(cylinder, head, sectorId)->data =
data.slice(pos, ltl->sectorSize);
pos += ltl->sectorSize;
number++;
}
}
@@ -329,25 +318,23 @@ void Filesystem::putLogicalSector(uint32_t number, const Bytes& data)
unsigned Filesystem::getOffsetOfSector(
unsigned track, unsigned side, unsigned sector)
{
location_t key = {track, side, sector};
for (int i = 0; i < _locations.size(); i++)
{
if (_locations[i] >= key)
return i;
}
throw BadFilesystemException();
unsigned offset = findOrDefault(_diskLayout->sectorOffsetByLogicalSectorLocation,
{track, side, sector},
UINT_MAX);
if (offset == UINT_MAX)
throw BadFilesystemException();
return offset;
}
unsigned Filesystem::getLogicalSectorCount()
{
return _locations.size();
return _blockCount;
}
unsigned Filesystem::getLogicalSectorSize(unsigned track, unsigned side)
unsigned Filesystem::getLogicalSectorSize(unsigned cylinder, unsigned head)
{
return Layout::getLayoutOfTrack(track, side)->sectorSize;
auto& ltl = _diskLayout->layoutByLogicalLocation.at({cylinder, head});
return ltl->sectorSize;
}
void Filesystem::eraseEverythingOnDisk()

View File

@@ -4,11 +4,12 @@
#include "lib/core/bytes.h"
#include "fmt/format.h"
class Sector;
class Image;
class Brother120Proto;
class DfsProto;
class DiskLayout;
class FilesystemProto;
class Image;
class Sector;
class SectorInterface;
class Path : public std::vector<std::string>
@@ -222,7 +223,8 @@ public:
void discardChanges();
public:
Filesystem(std::shared_ptr<SectorInterface> sectors);
Filesystem(const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors);
Bytes getSector(unsigned track, unsigned side, unsigned sector);
@@ -235,45 +237,79 @@ public:
void eraseEverythingOnDisk();
protected:
const std::shared_ptr<const DiskLayout>& _diskLayout;
unsigned _blockCount;
private:
typedef std::tuple<unsigned, unsigned, unsigned> location_t;
std::vector<location_t> _locations;
std::shared_ptr<SectorInterface> _sectors;
public:
static std::unique_ptr<Filesystem> createBrother120Filesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createAcornDfsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createFatFsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createCpmFsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createAmigaFfsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createMacHfsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createCbmfsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createProdosFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createAppledosFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createSmaky6Filesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createPhileFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createLifFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createMicrodosFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createZDosFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createRolandFsFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> image);
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> image);
static std::unique_ptr<Filesystem> createFilesystemFromConfig();
};

View File

@@ -182,9 +182,10 @@ class ZDosFilesystem : public Filesystem
};
public:
ZDosFilesystem(
const ZDosProto& config, std::shared_ptr<SectorInterface> sectors):
Filesystem(sectors),
ZDosFilesystem(const ZDosProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors):
Filesystem(diskLayout, sectors),
_config(config)
{
}
@@ -255,7 +256,8 @@ public:
private:
void mount()
{
_sectorsPerTrack = Layout::getLayoutOfTrack(0, 0)->numSectors;
_sectorsPerTrack =
_diskLayout->layoutByLogicalLocation.at({0, 0})->numSectors;
int rootBlock = toBlockNumber(_config.filesystem_start().sector(),
_config.filesystem_start().track());
@@ -319,7 +321,9 @@ private:
};
std::unique_ptr<Filesystem> Filesystem::createZDosFilesystem(
const FilesystemProto& config, std::shared_ptr<SectorInterface> sectors)
const FilesystemProto& config,
const std::shared_ptr<const DiskLayout>& diskLayout,
std::shared_ptr<SectorInterface> sectors)
{
return std::make_unique<ZDosFilesystem>(config.zdos(), sectors);
return std::make_unique<ZDosFilesystem>(config.zdos(), diskLayout, sectors);
}

View File

@@ -44,9 +44,9 @@ int mainConvert(int argc, const char* argv[])
auto locations = globalConfig()->drive().tracks();
globalConfig().overrides()->set_tracks(locations);
auto physicalLocations = Layout::computePhysicalLocations();
auto diskLayout = createDiskLayout(globalConfig());
auto [minCylinder, maxCylinder, minHead, maxHead] =
Layout::getBounds(physicalLocations);
diskLayout->getPhysicalBounds();
log("CONVERT: seen cylinders {}..{}, heads {}..{}",
minCylinder,
maxCylinder,
@@ -55,7 +55,7 @@ int mainConvert(int argc, const char* argv[])
auto fluxSink = FluxSink::create(globalConfig());
for (const auto& physicalLocation : physicalLocations)
for (const auto& physicalLocation : diskLayout->physicalLocations)
{
auto fi = fluxSource->readFlux(physicalLocation);
while (fi->hasNext())

View File

@@ -143,7 +143,7 @@ void AbstractSectorView::drawContent()
};
auto block = findOptionally(
diskFlux->layout->blockIdByLogicalLocation,
diskFlux->layout->blockIdByLogicalSectorLocation,
{sector->logicalCylinder,
sector->logicalHead,
sector->logicalSector});

View File

@@ -25,5 +25,5 @@ public:
protected:
virtual std::shared_ptr<const Sector> getSector(
unsigned cylinder, unsigned head, unsigned sectorId) = 0;
virtual Layout::LayoutBounds getBounds() = 0;
virtual DiskLayout::LayoutBounds getBounds() = 0;
};

View File

@@ -44,14 +44,12 @@ static std::atomic<bool> failed;
static bool formattingSupported;
static std::map<std::string, Datastore::Device> devices;
static std::shared_ptr<const DiskLayout> diskLayout;
static std::map<CylinderHead, std::shared_ptr<const TrackInfo>>
physicalCylinderLayouts;
static std::map<CylinderHeadSector, std::shared_ptr<const Sector>>
sectorByPhysicalLocation;
static std::map<LogicalLocation, std::shared_ptr<const Sector>>
sectorByLogicalLocation;
static Layout::LayoutBounds diskPhysicalBounds;
static Layout::LayoutBounds diskLogicalBounds;
static DiskLayout::LayoutBounds diskPhysicalBounds;
static DiskLayout::LayoutBounds diskLogicalBounds;
static void wtRebuildConfiguration();
@@ -200,7 +198,7 @@ void Datastore::init()
{
auto sector = it->second;
unsigned offset =
diskFlux->layout->sectorOffsetByLogicalLocation.at(
diskFlux->layout->sectorOffsetByLogicalSectorLocation.at(
{sector->logicalCylinder,
sector->logicalHead,
sector->logicalSector});
@@ -226,10 +224,10 @@ void Datastore::init()
unsigned lastSectorId = ltl->filesystemSectorOrder.back();
unsigned startOffset =
diskFlux->layout->sectorOffsetByLogicalLocation.at(
diskFlux->layout->sectorOffsetByLogicalSectorLocation.at(
{ltl->logicalCylinder, ltl->logicalHead, firstSectorId});
unsigned endOffset =
diskFlux->layout->sectorOffsetByLogicalLocation.at(
diskFlux->layout->sectorOffsetByLogicalSectorLocation.at(
{ltl->logicalCylinder, ltl->logicalHead, lastSectorId}) +
ltl->sectorSize;
@@ -393,8 +391,8 @@ void wtRebuildConfiguration()
bool formattingSupported = false;
try
{
auto filesystem =
Filesystem::createFilesystem(globalConfig()->filesystem(), nullptr);
auto filesystem = Filesystem::createFilesystem(
globalConfig()->filesystem(), diskLayout, nullptr);
uint32_t flags = filesystem->capabilities();
formattingSupported = flags & Filesystem::OP_CREATE;
}
@@ -404,14 +402,8 @@ void wtRebuildConfiguration()
}
auto diskLayout = createDiskLayout();
auto locations = Layout::computePhysicalLocations();
auto diskPhysicalBounds = Layout::getBounds(locations);
auto diskLogicalBounds =
Layout::getBounds(Layout::computeLogicalLocations());
decltype(::physicalCylinderLayouts) physicalCylinderLayouts;
for (auto& it : locations)
physicalCylinderLayouts[it] = Layout::getLayoutOfTrackPhysical(it);
auto diskPhysicalBounds = diskLayout->getPhysicalBounds();
auto diskLogicalBounds = diskLayout->getLogicalBounds();
hex::TaskManager::doLater(
[=]
@@ -420,7 +412,6 @@ void wtRebuildConfiguration()
::diskLayout = diskLayout;
::diskPhysicalBounds = diskPhysicalBounds;
::diskLogicalBounds = diskLogicalBounds;
::physicalCylinderLayouts = physicalCylinderLayouts;
rebuildDecodedDiskIndices();
});
}

View File

@@ -66,17 +66,17 @@ void DiskProvider::readRaw(u64 offset, void* buffer, size_t size)
while (size != 0)
{
auto it =
diskFlux->layout->logicalLocationBySectorOffset.upper_bound(
diskFlux->layout->logicalSectorLocationBySectorOffset.upper_bound(
offset);
if (it != diskFlux->layout->logicalLocationBySectorOffset.begin())
if (it != diskFlux->layout->logicalSectorLocationBySectorOffset.begin())
it--;
unsigned realOffset = it->first;
auto logicalLocation = it->second;
auto sector = diskFlux->image->get(logicalLocation);
unsigned blockOffset = realOffset - offset;
unsigned bytesRemaining = std::min(
(unsigned)size, sector->data.size() - blockOffset);
unsigned bytesRemaining =
std::min((unsigned)size, sector->data.size() - blockOffset);
auto bytes = sector->data.slice(blockOffset, bytesRemaining);
memcpy(buffer, bytes.cbegin(), bytes.size());

View File

@@ -12,7 +12,7 @@ using namespace hex;
ImageView::ImageView(): AbstractSectorView("fluxengine.view.image.name") {}
Layout::LayoutBounds ImageView::getBounds()
DiskLayout::LayoutBounds ImageView::getBounds()
{
return Datastore::getDiskLayout()->getLogicalBounds();
}

View File

@@ -10,5 +10,5 @@ public:
std::shared_ptr<const Sector> getSector(
unsigned cylinder, unsigned head, unsigned sectorId) override;
Layout::LayoutBounds getBounds() override;
DiskLayout::LayoutBounds getBounds() override;
};

View File

@@ -17,7 +17,7 @@ PhysicalView::PhysicalView():
PhysicalView::~PhysicalView() {}
Layout::LayoutBounds PhysicalView::getBounds()
DiskLayout::LayoutBounds PhysicalView::getBounds()
{
return Datastore::getDiskLayout()->getPhysicalBounds();
}

View File

@@ -11,5 +11,5 @@ public:
std::shared_ptr<const Sector> getSector(
unsigned cylinder, unsigned head, unsigned sectorId) override;
Layout::LayoutBounds getBounds() override;
DiskLayout::LayoutBounds getBounds() override;
};

View File

@@ -6,6 +6,7 @@
#include "lib/data/image.h"
#include "lib/config/proto.h"
#include "lib/data/sector.h"
#include "lib/data/layout.h"
#include "snowhouse/snowhouse.h"
#include <google/protobuf/text_format.h>
@@ -13,11 +14,21 @@ using namespace snowhouse;
static Bytes blank_dirent = Bytes{0xe5} * 32;
/* The layout must use one cylinder per CP/M block (eight sectors). */
static std::shared_ptr<const DiskLayout> diskLayout =
std::make_shared<DiskLayout>(10, 1, 8, 256);
namespace
{
class TestSectorInterface : public SectorInterface
{
public:
TestSectorInterface()
{
_image.addMissingSectors(*diskLayout, true);
}
std::shared_ptr<const Sector> get(
unsigned track, unsigned side, unsigned sectorId) override
{
@@ -125,7 +136,7 @@ static void testPartialExtent()
{
auto sectors = std::make_shared<TestSectorInterface>();
auto fs = Filesystem::createCpmFsFilesystem(
globalConfig()->filesystem(), sectors);
globalConfig()->filesystem(), diskLayout, sectors);
setBlock(sectors,
0,
@@ -145,7 +156,7 @@ static void testLogicalExtents()
{
auto sectors = std::make_shared<TestSectorInterface>();
auto fs = Filesystem::createCpmFsFilesystem(
globalConfig()->filesystem(), sectors);
globalConfig()->filesystem(), diskLayout, sectors);
setBlock(sectors,
0,
@@ -169,7 +180,7 @@ static void testBitmap()
{
auto sectors = std::make_shared<TestSectorInterface>();
auto fs = Filesystem::createCpmFsFilesystem(
globalConfig()->filesystem(), sectors);
globalConfig()->filesystem(), diskLayout, sectors);
setBlock(sectors,
0,

View File

@@ -54,29 +54,16 @@ static void test_physical_sectors()
}
)M");
{
auto layout = Layout::getLayoutOfTrack(0, 0);
AssertThat(layout->naturalSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(
layout->diskSectorOrder, Equals(std::vector<unsigned>{0, 2, 1, 3}));
AssertThat(layout->filesystemSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3}));
}
{
auto diskLayout = createDiskLayout();
auto physicalLayout = diskLayout->layoutByPhysicalLocation.at({0, 0});
auto layout = physicalLayout->logicalTrackLayout;
AssertThat(
diskLayout->layoutByLogicalLocation.at({0, 0}), Equals(layout));
AssertThat(layout->naturalSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(
layout->diskSectorOrder, Equals(std::vector<unsigned>{0, 2, 1, 3}));
AssertThat(layout->filesystemSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3}));
}
auto diskLayout = createDiskLayout();
auto physicalLayout = diskLayout->layoutByPhysicalLocation.at({0, 0});
auto layout = physicalLayout->logicalTrackLayout;
AssertThat(diskLayout->layoutByLogicalLocation.at({0, 0}), Equals(layout));
AssertThat(
layout->naturalSectorOrder, Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(
layout->diskSectorOrder, Equals(std::vector<unsigned>{0, 2, 1, 3}));
AssertThat(layout->filesystemSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3}));
}
static void test_logical_sectors()
@@ -109,29 +96,16 @@ static void test_logical_sectors()
}
)M");
{
auto layout = Layout::getLayoutOfTrack(0, 0);
AssertThat(layout->naturalSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(
layout->diskSectorOrder, Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(layout->filesystemSectorOrder,
Equals(std::vector<unsigned>{0, 2, 1, 3}));
}
{
auto diskLayout = createDiskLayout();
auto physicalLayout = diskLayout->layoutByPhysicalLocation.at({0, 0});
auto layout = physicalLayout->logicalTrackLayout;
AssertThat(
diskLayout->layoutByLogicalLocation.at({0, 0}), Equals(layout));
AssertThat(layout->naturalSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(
layout->diskSectorOrder, Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(layout->filesystemSectorOrder,
Equals(std::vector<unsigned>{0, 2, 1, 3}));
}
auto diskLayout = createDiskLayout();
auto physicalLayout = diskLayout->layoutByPhysicalLocation.at({0, 0});
auto layout = physicalLayout->logicalTrackLayout;
AssertThat(diskLayout->layoutByLogicalLocation.at({0, 0}), Equals(layout));
AssertThat(
layout->naturalSectorOrder, Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(
layout->diskSectorOrder, Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(layout->filesystemSectorOrder,
Equals(std::vector<unsigned>{0, 2, 1, 3}));
}
static void test_both_sectors()
@@ -164,29 +138,16 @@ static void test_both_sectors()
}
)M");
{
auto layout = Layout::getLayoutOfTrack(0, 0);
AssertThat(layout->naturalSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(
layout->diskSectorOrder, Equals(std::vector<unsigned>{3, 2, 1, 0}));
AssertThat(layout->filesystemSectorOrder,
Equals(std::vector<unsigned>{0, 2, 1, 3}));
}
{
auto diskLayout = createDiskLayout();
auto physicalLayout = diskLayout->layoutByPhysicalLocation.at({0, 0});
auto layout = physicalLayout->logicalTrackLayout;
AssertThat(
diskLayout->layoutByLogicalLocation.at({0, 0}), Equals(layout));
AssertThat(layout->naturalSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(
layout->diskSectorOrder, Equals(std::vector<unsigned>{3, 2, 1, 0}));
AssertThat(layout->filesystemSectorOrder,
Equals(std::vector<unsigned>{0, 2, 1, 3}));
}
auto diskLayout = createDiskLayout();
auto physicalLayout = diskLayout->layoutByPhysicalLocation.at({0, 0});
auto layout = physicalLayout->logicalTrackLayout;
AssertThat(diskLayout->layoutByLogicalLocation.at({0, 0}), Equals(layout));
AssertThat(
layout->naturalSectorOrder, Equals(std::vector<unsigned>{0, 1, 2, 3}));
AssertThat(
layout->diskSectorOrder, Equals(std::vector<unsigned>{3, 2, 1, 0}));
AssertThat(layout->filesystemSectorOrder,
Equals(std::vector<unsigned>{0, 2, 1, 3}));
}
static void test_skew()
@@ -212,27 +173,13 @@ static void test_skew()
}
)M");
{
auto layout = Layout::getLayoutOfTrack(0, 0);
AssertThat(layout->naturalSectorOrder,
Equals(
std::vector<unsigned>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}));
AssertThat(layout->diskSectorOrder,
Equals(
std::vector<unsigned>{0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11}));
}
{
auto diskLayout = createDiskLayout();
auto physicalLayout = diskLayout->layoutByPhysicalLocation.at({0, 0});
auto layout = physicalLayout->logicalTrackLayout;
AssertThat(layout->naturalSectorOrder,
Equals(
std::vector<unsigned>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}));
AssertThat(layout->diskSectorOrder,
Equals(
std::vector<unsigned>{0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11}));
}
auto diskLayout = createDiskLayout();
auto physicalLayout = diskLayout->layoutByPhysicalLocation.at({0, 0});
auto layout = physicalLayout->logicalTrackLayout;
AssertThat(layout->naturalSectorOrder,
Equals(std::vector<unsigned>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}));
AssertThat(layout->diskSectorOrder,
Equals(std::vector<unsigned>{0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11}));
}
static void test_bounds()
@@ -261,9 +208,9 @@ static void test_bounds()
auto diskLayout = createDiskLayout();
AssertThat(diskLayout->groupSize, Equals(2));
AssertThat(diskLayout->getLogicalBounds(),
Equals(Layout::LayoutBounds{0, 1, 0, 1}));
Equals(DiskLayout::LayoutBounds{0, 1, 0, 1}));
AssertThat(diskLayout->getPhysicalBounds(),
Equals(Layout::LayoutBounds{0, 3, 0, 1}));
Equals(DiskLayout::LayoutBounds{0, 3, 0, 1}));
}
template <typename K, typename V>
@@ -301,8 +248,8 @@ static void test_sectoroffsets()
auto diskLayout = createDiskLayout();
AssertThat(diskLayout->groupSize, Equals(1));
AssertThat(diskLayout->logicalLocationBySectorOffset,
EqualsContainer(decltype(diskLayout->logicalLocationBySectorOffset){
AssertThat(diskLayout->logicalSectorLocationBySectorOffset,
EqualsContainer(decltype(diskLayout->logicalSectorLocationBySectorOffset){
{0, {0, 0, 0}},
{256, {0, 0, 2}},
{512, {0, 0, 1}},
@@ -320,8 +267,8 @@ static void test_sectoroffsets()
{3584, {1, 1, 1}},
{3840, {1, 1, 3}}
}));
AssertThat(diskLayout->sectorOffsetByLogicalLocation,
EqualsContainer(decltype(diskLayout->sectorOffsetByLogicalLocation){
AssertThat(diskLayout->sectorOffsetByLogicalSectorLocation,
EqualsContainer(decltype(diskLayout->sectorOffsetByLogicalSectorLocation){
{{0, 0, 0}, 0 },
{{0, 0, 1}, 512 },
{{0, 0, 2}, 256 },