Convert from LayoutData to Layout.

This commit is contained in:
David Given
2022-09-10 19:53:05 +02:00
parent 1a4caccd07
commit a6db36e7b3
13 changed files with 180 additions and 145 deletions

View File

@@ -206,9 +206,8 @@ public:
std::set<unsigned> requiredSectors(const Location& location) const override
{
auto layoutdata = Layout::getLayoutOfTrack(location.logicalTrack, location.head);
auto sectors = Layout::getSectorsInTrack(layoutdata);
return std::set<unsigned>(sectors.begin(), sectors.end());
auto trackLayout = Layout::getLayoutOfTrack(location.logicalTrack, location.head);
return std::set<unsigned>(trackLayout.logicalSectors.begin(), trackLayout.logicalSectors.end());
}
private:

View File

@@ -115,14 +115,15 @@ public:
IbmEncoderProto::TrackdataProto trackdata;
getEncoderTrackData(trackdata, location.logicalTrack, location.head);
auto layoutdata =
auto trackLayout =
Layout::getLayoutOfTrack(location.logicalTrack, location.head);
int logicalSide = location.head ^ trackdata.swap_sides();
for (int sectorId : Layout::getSectorsInTrack(layoutdata))
for (unsigned physicalSectorId : trackLayout.physicalSectors)
{
unsigned logicalSectorId = trackLayout.physicalSectorToLogical(physicalSectorId);
const auto& sector =
image.get(location.logicalTrack, logicalSide, sectorId);
image.get(location.logicalTrack, logicalSide, logicalSectorId);
if (sector)
sectors.push_back(sector);
}
@@ -137,7 +138,7 @@ public:
IbmEncoderProto::TrackdataProto trackdata;
getEncoderTrackData(trackdata, location.logicalTrack, location.head);
auto layoutdata =
auto trackLayout =
Layout::getLayoutOfTrack(location.logicalTrack, location.head);
auto writeBytes = [&](const Bytes& bytes)
@@ -174,7 +175,7 @@ public:
uint8_t sectorSize = 0;
{
int s = layoutdata.sector_size() >> 7;
int s = trackLayout.sectorSize >> 7;
while (s > 1)
{
s >>= 1;
@@ -259,7 +260,7 @@ public:
bw.write_8(damUnencoded);
Bytes truncatedData =
sectorData->data.slice(0, layoutdata.sector_size());
sectorData->data.slice(0, trackLayout.sectorSize);
bw += truncatedData;
uint16_t crc = crc16(CCITT_POLY, data);
bw.write_be16(crc);

View File

@@ -29,9 +29,9 @@ void Image::createBlankImage()
{
unsigned track = trackAndHead.first;
unsigned side = trackAndHead.second;
auto layout = Layout::getLayoutOfTrack(track, side);
Bytes blank(layout.sector_size());
for (unsigned sectorId : Layout::getSectorsInTrack(layout))
auto trackLayout = Layout::getLayoutOfTrack(track, side);
Bytes blank(trackLayout.sectorSize);
for (unsigned sectorId : trackLayout.logicalSectors)
put(track, side, sectorId)->data = blank;
}
}

View File

@@ -40,10 +40,10 @@ public:
if (inputFile.eof())
break;
auto layoutdata = Layout::getLayoutOfTrack(track, side);
for (int sectorId : Layout::getSectorsInTrack(layoutdata))
auto trackLayout = Layout::getLayoutOfTrack(track, side);
for (int sectorId : trackLayout.logicalSectors)
{
Bytes data(layoutdata.sector_size());
Bytes data(trackLayout.sectorSize);
inputFile.read((char*)data.begin(), data.size());
const auto& sector = image->put(track, side, sectorId);

View File

@@ -36,26 +36,14 @@ public:
int track = p.first;
int side = p.second;
auto layoutdata = Layout::getLayoutOfTrack(track, side);
auto sectors = Layout::getSectorsInTrack(layoutdata, geometry.numSectors);
if (sectors.empty())
{
int maxSector = geometry.firstSector + geometry.numSectors - 1;
for (int i = geometry.firstSector; i <= maxSector; i++)
sectors.push_back(i);
}
int sectorSize = layoutdata.has_sector_size()
? layoutdata.sector_size()
: geometry.sectorSize;
for (int sectorId : sectors)
auto trackLayout = Layout::getLayoutOfTrack(track, side);
for (int sectorId : trackLayout.logicalSectors)
{
const auto& sector = image.get(track, side, sectorId);
if (sector)
sector->data.slice(0, sectorSize).writeTo(outputFile);
sector->data.slice(0, trackLayout.sectorSize).writeTo(outputFile);
else
outputFile.seekp(sectorSize, std::ios::cur);
outputFile.seekp(trackLayout.sectorSize, std::ios::cur);
}
}

View File

@@ -1,6 +1,9 @@
#include "lib/globals.h"
#include "lib/layout.h"
#include "lib/proto.h"
#include <fmt/format.h>
static std::map<std::pair<int, int>, std::unique_ptr<Layout>> layoutCache;
std::vector<std::pair<int, int>> Layout::getTrackOrdering(
unsigned guessedTracks, unsigned guessedSides)
@@ -39,58 +42,83 @@ std::vector<std::pair<int, int>> Layout::getTrackOrdering(
return ordering;
}
LayoutProto::LayoutdataProto Layout::getLayoutOfTrack(
unsigned track, unsigned side)
static void expandSectors(const LayoutProto::SectorsProto& sectorsProto,
std::vector<unsigned>& sectors)
{
LayoutProto::LayoutdataProto layoutdata;
for (const auto& f : config.layout().layoutdata())
if (sectorsProto.has_count())
{
if (f.has_track() && f.has_up_to_track() &&
((track < f.track()) || (track > f.up_to_track())))
continue;
if (f.has_track() && !f.has_up_to_track() && (track != f.track()))
continue;
if (f.has_side() && (f.side() != side))
continue;
layoutdata.MergeFrom(f);
}
return layoutdata;
}
std::vector<unsigned> Layout::getSectorsInTrack(
const LayoutProto::LayoutdataProto& trackdata, unsigned guessedSectors)
{
auto& physical = trackdata.physical();
std::vector<unsigned> sectors;
if (physical.has_count())
{
if (physical.sector_size() != 1)
if (sectorsProto.sector_size() != 1)
Error() << "LAYOUT: if you use a sector count, you must specify "
"exactly one start sector";
int startSector = physical.sector(0);
for (int i = 0; i < physical.count(); i++)
int startSector = sectorsProto.sector(0);
for (int i = 0; i < sectorsProto.count(); i++)
sectors.push_back(startSector + i);
}
else if (physical.guess_count())
else if (sectorsProto.sector_size() > 0)
{
if (physical.sector_size() != 1)
Error() << "LAYOUT: if you are guessing the number of sectors, you "
"must specify exactly one start sector";
int startSector = physical.sector(0);
for (int i = 0; i < guessedSectors; i++)
sectors.push_back(startSector + i);
}
else if (trackdata.sector_size() > 0)
{
for (int sectorId : physical.sector())
for (int sectorId : sectorsProto.sector())
sectors.push_back(sectorId);
}
return sectors;
else
Error() << "LAYOUT: no sectors in track!";
}
const Layout& Layout::getLayoutOfTrack(unsigned track, unsigned side)
{
auto& layout = layoutCache[std::make_pair(track, side)];
if (!layout)
{
layout.reset(new Layout);
LayoutProto::LayoutdataProto layoutdata;
for (const auto& f : config.layout().layoutdata())
{
if (f.has_track() && f.has_up_to_track() &&
((track < f.track()) || (track > f.up_to_track())))
continue;
if (f.has_track() && !f.has_up_to_track() && (track != f.track()))
continue;
if (f.has_side() && (f.side() != side))
continue;
layoutdata.MergeFrom(f);
}
layout->numTracks = config.layout().tracks();
layout->numSides = config.layout().sides();
layout->sectorSize = layoutdata.sector_size();
expandSectors(layoutdata.physical(), layout->physicalSectors);
if (layoutdata.has_logical())
expandSectors(layoutdata.logical(), layout->logicalSectors);
else
layout->logicalSectors = layout->physicalSectors;
if (layout->logicalSectors.size() != layout->physicalSectors.size())
Error() << fmt::format(
"LAYOUT: physical and logical sectors lists are different "
"sizes in {}.{}",
track,
side);
}
return *layout;
}
unsigned Layout::physicalSectorToLogical(unsigned physicalSectorId)
{
for (int i=0; i<physicalSectors.size(); i++)
if (physicalSectors[i] == physicalSectorId)
return logicalSectors[i];
Error() << fmt::format("LAYOUT: physical sector {} not recognised", physicalSectorId);
}
unsigned Layout::logicalSectorToPhysical(unsigned logicalSectorId)
{
for (int i=0; i<logicalSectors.size(); i++)
if (logicalSectors[i] == logicalSectorId)
return physicalSectors[i];
Error() << fmt::format("LAYOUT: logical sector {} not recognised", logicalSectorId);
}

View File

@@ -9,12 +9,18 @@ public:
static std::vector<std::pair<int, int>> getTrackOrdering(
unsigned guessedTracks = 0, unsigned guessedSides = 0);
static LayoutProto::LayoutdataProto getLayoutOfTrack(
static const Layout& getLayoutOfTrack(
unsigned logicalTrack, unsigned logicalHead);
static std::vector<unsigned> getSectorsInTrack(
const LayoutProto::LayoutdataProto& trackdata,
unsigned guessedSectors = 0);
public:
unsigned numTracks;
unsigned numSides;
unsigned sectorSize;
std::vector<unsigned> physicalSectors;
std::vector<unsigned> logicalSectors;
unsigned physicalSectorToLogical(unsigned sectorId);
unsigned logicalSectorToPhysical(unsigned sectorId);
};
#endif

View File

@@ -2,35 +2,51 @@ syntax = "proto2";
import "lib/common.proto";
message LayoutProto {
enum Order {
UNDEFINED = 0;
CHS = 1;
HCS = 2;
}
message LayoutProto
{
enum Order
{
UNDEFINED = 0;
CHS = 1;
HCS = 2;
}
message SectorsProto {
repeated int32 sector = 1 [(help) = "sector ID"];
oneof count_oneof {
int32 count = 2 [(help) = "if present, add this many consecutive sectors"];
bool guess_count = 3 [(help) = "if present, guess the number of sectors"];
}
}
message SectorsProto
{
repeated int32 sector = 1 [ (help) = "sector ID" ];
oneof count_oneof
{
int32 count = 2
[ (help) = "if present, add this many consecutive sectors" ];
bool guess_count = 3
[ (help) = "if present, guess the number of sectors" ];
}
}
message LayoutdataProto {
optional int32 track = 1 [(help) = "if present, this format only applies to this track"];
optional int32 up_to_track = 5 [(help) = "if present, forms a range with track"];
optional int32 side = 2 [(help) = "if present, this format only applies to this side"];
message LayoutdataProto
{
optional int32 track = 1
[ (help) = "if present, this format only applies to this track" ];
optional int32 up_to_track = 5
[ (help) = "if present, forms a range with track" ];
optional int32 side = 2
[ (help) = "if present, this format only applies to this side" ];
optional int32 sector_size = 3 [default=512, (help) = "number of bytes per sector"];
optional int32 sector_size = 3
[ default = 512, (help) = "number of bytes per sector" ];
optional SectorsProto physical = 4 [(help) = "physical order of sectors on disk"];
optional SectorsProto logical = 6 [(help) = "logical order of sectors in filesystem"];
}
optional SectorsProto physical = 4
[ (help) = "physical order of sectors on disk" ];
optional SectorsProto logical = 6
[ (help) = "logical order of sectors in filesystem" ];
}
repeated LayoutdataProto layoutdata = 1 [(help) = "per-track layout information (repeatable)"];
optional int32 tracks = 2 [default=0, (help) = "number of tracks in image"];
optional int32 sides = 3 [default=0, (help) = "number of sides in image"];
optional Order order = 4 [default=CHS, (help) = "the order of sectors in the filesystem"];
repeated LayoutdataProto layoutdata = 1
[ (help) = "per-track layout information (repeatable)" ];
optional int32 tracks = 2
[ default = 0, (help) = "number of tracks in image" ];
optional int32 sides = 3
[ default = 0, (help) = "number of sides in image" ];
optional Order order = 4
[ default = CHS, (help) = "the order of sectors in the filesystem" ];
}

View File

@@ -38,9 +38,10 @@ public:
nanoseconds_t dataEndTime = 0;
unsigned physicalTrack = 0;
unsigned physicalHead = 0;
unsigned physicalSector = 0;
unsigned logicalTrack = 0;
unsigned logicalSide = 0;
unsigned physicalSector = 0;
unsigned logicalSector = 0;
Bytes data;
std::vector<std::shared_ptr<Record>> records;
@@ -51,7 +52,7 @@ public:
std::tuple<int, int, int, Status> key() const
{
return std::make_tuple(
logicalTrack, logicalSide, physicalSector, status);
logicalTrack, logicalSide, logicalSector, status);
}
bool operator==(const Sector& rhs) const

View File

@@ -91,8 +91,7 @@ public:
dev.devType = DEVTYPE_FLOPDD;
dev.cylinders = config.layout().tracks();
dev.heads = config.layout().sides();
dev.sectors =
Layout::getSectorsInTrack(Layout::getLayoutOfTrack(0, 0)).size();
dev.sectors = Layout::getLayoutOfTrack(0, 0).logicalSectors.size();
adfInitDevice(&dev, nullptr, false);
int res = adfCreateFlop(&dev, (char*)volumeName.c_str(), 0);
if (res != RC_OK)

View File

@@ -63,8 +63,7 @@ public:
{
unsigned track = trackid.first;
unsigned side = trackid.second;
auto layoutdata = Layout::getLayoutOfTrack(track, side);
auto sectors = Layout::getSectorsInTrack(layoutdata);
auto trackLayout = Layout::getLayoutOfTrack(track, side);
locations.insert(Mapper::computeLocationFor(track, side));
/* If we don't have all the sectors of this track, we may need to
@@ -72,7 +71,7 @@ public:
* a time. */
if (!imageContainsAllSectorsOf(
_changedSectors, track, side, sectors))
_changedSectors, track, side, trackLayout.logicalSectors))
{
/* If we don't have any loaded sectors for this track, pre-read
* it. */
@@ -83,11 +82,11 @@ public:
/* Now merge the loaded track with the changed one, and write
* the result back. */
for (const unsigned sector : sectors)
for (unsigned sectorId : trackLayout.logicalSectors)
{
if (!_changedSectors.contains(track, side, sector))
_changedSectors.put(track, side, sector)->data =
_loadedSectors.get(track, side, sector)->data;
if (!_changedSectors.contains(track, side, sectorId))
_changedSectors.put(track, side, sectorId)->data =
_loadedSectors.get(track, side, sectorId)->data;
}
}
}

View File

@@ -164,13 +164,12 @@ Filesystem::Filesystem(std::shared_ptr<SectorInterface> sectors):
int track = p.first;
int side = p.second;
auto layoutdata = Layout::getLayoutOfTrack(track, side);
auto sectors = Layout::getSectorsInTrack(layoutdata);
if (sectors.empty())
auto trackLayout = Layout::getLayoutOfTrack(track, side);
if (trackLayout.logicalSectors.empty())
Error() << "FS: filesystem support cannot be used without concrete "
"layout information";
for (int sectorId : sectors)
for (int sectorId : trackLayout.logicalSectors)
_locations.push_back(std::make_tuple(track, side, sectorId));
}
}
@@ -269,9 +268,9 @@ Bytes Filesystem::getLogicalSector(uint32_t number, uint32_t count)
int track = std::get<0>(it);
int side = std::get<1>(it);
int sector = std::get<2>(it);
auto layoutdata = Layout::getLayoutOfTrack(track, side);
auto trackLayout = Layout::getLayoutOfTrack(track, side);
bw += _sectors->get(track, side, sector)
->data.slice(0, layoutdata.sector_size());
->data.slice(0, trackLayout.sectorSize);
}
return data;
}
@@ -288,7 +287,7 @@ void Filesystem::putLogicalSector(uint32_t number, const Bytes& data)
int track = std::get<0>(it);
int side = std::get<1>(it);
int sector = std::get<2>(it);
int sectorSize = Layout::getLayoutOfTrack(track, side).sector_size();
int sectorSize = Layout::getLayoutOfTrack(track, side).sectorSize;
_sectors->put(track, side, sector)->data = data.slice(pos, sectorSize);
pos += sectorSize;
@@ -317,8 +316,7 @@ unsigned Filesystem::getLogicalSectorCount()
unsigned Filesystem::getLogicalSectorSize(unsigned track, unsigned side)
{
auto trackdata = Layout::getLayoutOfTrack(track, side);
return trackdata.sector_size();
return Layout::getLayoutOfTrack(track, side).sectorSize;
}
void Filesystem::eraseEverythingOnDisk()

View File

@@ -62,9 +62,9 @@ public:
_dndFormat(wxDF_UNICODETEXT),
_config("FluxEngine")
{
wxIcon icon;
icon.CopyFromBitmap(applicationBitmap->GetBitmap());
SetIcon(icon);
wxIcon icon;
icon.CopyFromBitmap(applicationBitmap->GetBitmap());
SetIcon(icon);
Logger::setLogger(
[&](std::shared_ptr<const AnyLogMessage> message)
@@ -924,25 +924,25 @@ public:
if (event.GetDataFormat() != _dndFormat)
throw CancelException();
#if defined __WXGTK__
/* wxWidgets 3.0 data view DnD on GTK is borked. See
* https://forums.wxwidgets.org/viewtopic.php?t=44752. The hit
* detection is done against the wrong object, resulting in the
* header size not being taken into account, so we have to manually
* do hit detection correctly. */
#if defined __WXGTK__
/* wxWidgets 3.0 data view DnD on GTK is borked. See
* https://forums.wxwidgets.org/viewtopic.php?t=44752. The hit
* detection is done against the wrong object, resulting in the
* header size not being taken into account, so we have to manually
* do hit detection correctly. */
auto* window = browserTree->GetMainWindow();
auto screenPos = wxGetMousePosition();
auto relPos = screenPos - window->GetScreenPosition();
auto* window = browserTree->GetMainWindow();
auto screenPos = wxGetMousePosition();
auto relPos = screenPos - window->GetScreenPosition();
wxDataViewItem item;
wxDataViewColumn* column;
browserTree->HitTest(relPos, item, column);
if (!item.IsOk())
throw CancelException();
#else
auto item = event.GetItem();
#endif
wxDataViewItem item;
wxDataViewColumn* column;
browserTree->HitTest(relPos, item, column);
if (!item.IsOk())
throw CancelException();
#else
auto item = event.GetItem();
#endif
auto destDirNode = GetTargetDirectoryNode(item);
if (!destDirNode)