mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Added functionality for faking the necessary data in a DecodedDisk to
make the visualiser work. Blank images can now be created in memory.
This commit is contained in:
@@ -409,6 +409,7 @@ static ReadGroupResult readGroup(const DiskLayout& diskLayout,
|
||||
}
|
||||
|
||||
void writeTracks(const DiskLayout& diskLayout,
|
||||
|
||||
FluxSink& fluxSink,
|
||||
std::function<std::unique_ptr<const Fluxmap>(
|
||||
const std::shared_ptr<const LogicalTrackLayout>&)> producer,
|
||||
@@ -666,31 +667,28 @@ TracksAndSectors readAndDecodeTrack(const DiskLayout& diskLayout,
|
||||
return fas;
|
||||
}
|
||||
|
||||
void readDiskCommand(
|
||||
FluxSource& fluxSource, Decoder& decoder, DecodedDisk& decodedDisk)
|
||||
void readDiskCommand(const DiskLayout& diskLayout,
|
||||
FluxSource& fluxSource,
|
||||
Decoder& decoder,
|
||||
DecodedDisk& decodedDisk)
|
||||
{
|
||||
std::unique_ptr<FluxSink> outputFluxSink;
|
||||
if (globalConfig()->decoder().has_copy_flux_to())
|
||||
outputFluxSink =
|
||||
FluxSink::create(globalConfig()->decoder().copy_flux_to());
|
||||
|
||||
if (!decodedDisk.layout)
|
||||
decodedDisk.layout = createDiskLayout();
|
||||
|
||||
log(BeginOperationLogMessage{"Reading and decoding disk"});
|
||||
unsigned index = 0;
|
||||
for (auto& [logicalLocation, ltl] :
|
||||
decodedDisk.layout->layoutByLogicalLocation)
|
||||
for (auto& [logicalLocation, ltl] : diskLayout.layoutByLogicalLocation)
|
||||
{
|
||||
log(OperationProgressLogMessage{
|
||||
index * 100 /
|
||||
(unsigned)decodedDisk.layout->layoutByLogicalLocation.size()});
|
||||
index * 100 / (unsigned)diskLayout.layoutByLogicalLocation.size()});
|
||||
index++;
|
||||
|
||||
testForEmergencyStop();
|
||||
|
||||
auto [trackFluxes, trackSectors] =
|
||||
readAndDecodeTrack(*decodedDisk.layout, fluxSource, decoder, ltl);
|
||||
readAndDecodeTrack(diskLayout, fluxSource, decoder, ltl);
|
||||
for (const auto& flux : trackFluxes)
|
||||
decodedDisk.tracksByPhysicalLocation.emplace(
|
||||
CylinderHead{
|
||||
@@ -781,11 +779,13 @@ void readDiskCommand(
|
||||
log(EndOperationLogMessage{"Read complete"});
|
||||
}
|
||||
|
||||
void readDiskCommand(
|
||||
FluxSource& fluxsource, Decoder& decoder, ImageWriter& writer)
|
||||
void readDiskCommand(const DiskLayout& diskLayout,
|
||||
FluxSource& fluxsource,
|
||||
Decoder& decoder,
|
||||
ImageWriter& writer)
|
||||
{
|
||||
DecodedDisk decodedDisk;
|
||||
readDiskCommand(fluxsource, decoder, decodedDisk);
|
||||
readDiskCommand(diskLayout, fluxsource, decoder, decodedDisk);
|
||||
|
||||
writer.printMap(*decodedDisk.image);
|
||||
if (globalConfig()->decoder().has_write_csv_to())
|
||||
|
||||
@@ -121,9 +121,13 @@ extern TracksAndSectors readAndDecodeTrack(const DiskLayout& diskLayout,
|
||||
Decoder& decoder,
|
||||
const std::shared_ptr<const LogicalTrackLayout>& ltl);
|
||||
|
||||
extern void readDiskCommand(
|
||||
FluxSource& fluxsource, Decoder& decoder, DecodedDisk& diskflux);
|
||||
extern void readDiskCommand(
|
||||
FluxSource& source, Decoder& decoder, ImageWriter& writer);
|
||||
extern void readDiskCommand(const DiskLayout& diskLayout,
|
||||
FluxSource& fluxsource,
|
||||
Decoder& decoder,
|
||||
DecodedDisk& diskflux);
|
||||
extern void readDiskCommand(const DiskLayout& diskLayout,
|
||||
FluxSource& source,
|
||||
Decoder& decoder,
|
||||
ImageWriter& writer);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,7 @@ from build.c import cxxlibrary
|
||||
cxxlibrary(
|
||||
name="data",
|
||||
srcs=[
|
||||
"./decoded.cc",
|
||||
"./fluxmap.cc",
|
||||
"./fluxmapreader.cc",
|
||||
"./fluxpattern.cc",
|
||||
|
||||
@@ -38,7 +38,8 @@ struct DecodedDisk
|
||||
std::multimap<CylinderHead, std::shared_ptr<const Sector>>
|
||||
sectorsByPhysicalLocation;
|
||||
std::shared_ptr<const Image> image;
|
||||
std::shared_ptr<const DiskLayout> layout;
|
||||
|
||||
void populateTrackDataFromImage(const DiskLayout& diskLayout);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -94,3 +94,25 @@ void Image::calculateSize()
|
||||
}
|
||||
_geometry.numSectors = maxSector - _geometry.firstSector + 1;
|
||||
}
|
||||
|
||||
void Image::populateSectorPhysicalLocationsFromLogicalLocations(
|
||||
const DiskLayout& diskLayout)
|
||||
{
|
||||
Image tempImage;
|
||||
for (const auto& sector : *this)
|
||||
{
|
||||
const auto& ltl = diskLayout.layoutByLogicalLocation.at(
|
||||
{sector->logicalCylinder, sector->logicalHead});
|
||||
auto newSector = tempImage.put(sector->logicalCylinder,
|
||||
sector->logicalHead,
|
||||
sector->logicalSector);
|
||||
*newSector = *sector;
|
||||
newSector->physicalLocation = std::make_optional<CylinderHead>(
|
||||
ltl->physicalCylinder, ltl->physicalHead);
|
||||
}
|
||||
|
||||
for (const auto& sector : tempImage)
|
||||
_sectors[{sector->logicalCylinder,
|
||||
sector->logicalHead,
|
||||
sector->logicalSector}] = sector;
|
||||
}
|
||||
|
||||
@@ -106,6 +106,8 @@ public:
|
||||
}
|
||||
|
||||
void addMissingSectors(const DiskLayout& layout, bool populated = false);
|
||||
void populateSectorPhysicalLocationsFromLogicalLocations(
|
||||
const DiskLayout& diskLayout);
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ std::string Sector::statusToString(Status status)
|
||||
case Status::CONFLICT:
|
||||
return "conflicting data";
|
||||
default:
|
||||
return fmt::format("unknown error {}", status);
|
||||
return fmt::format("unknown error {}", (int)status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ cxxlibrary(
|
||||
"./fl2fluxsink.cc",
|
||||
"./fluxsink.cc",
|
||||
"./hardwarefluxsink.cc",
|
||||
"./memoryfluxsink.cc",
|
||||
"./scpfluxsink.cc",
|
||||
"./vcdfluxsink.cc",
|
||||
],
|
||||
|
||||
@@ -14,6 +14,7 @@ class VcdFluxSinkProto;
|
||||
class ScpFluxSinkProto;
|
||||
class Fl2FluxSinkProto;
|
||||
class Config;
|
||||
class DecodedDisk;
|
||||
|
||||
class FluxSink
|
||||
{
|
||||
@@ -32,6 +33,8 @@ public:
|
||||
const ScpFluxSinkProto& config);
|
||||
static std::unique_ptr<FluxSink> createFl2FluxSink(
|
||||
const Fl2FluxSinkProto& config);
|
||||
static std::unique_ptr<FluxSink> createMemoryFluxSink(
|
||||
DecodedDisk& decodedDisk);
|
||||
|
||||
static std::unique_ptr<FluxSink> createFl2FluxSink(
|
||||
const std::string& filename);
|
||||
|
||||
@@ -99,8 +99,8 @@ public:
|
||||
_changedSectors,
|
||||
*_encoder,
|
||||
*_fluxSink,
|
||||
&*_decoder,
|
||||
&*_fluxSource,
|
||||
_decoder.get(),
|
||||
_fluxSource.get(),
|
||||
locations);
|
||||
|
||||
discardChanges();
|
||||
|
||||
@@ -41,7 +41,13 @@ public:
|
||||
|
||||
void flushChanges() override
|
||||
{
|
||||
// _writer->writeImage(*_image);
|
||||
for (const auto& sector : *_liveImage)
|
||||
{
|
||||
const auto& s = _backupImage->put(sector->logicalCylinder,
|
||||
sector->logicalHead,
|
||||
sector->logicalSector);
|
||||
*s = *sector;
|
||||
}
|
||||
_changed = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -305,11 +305,13 @@ void Filesystem::putLogicalSector(uint32_t number, const Bytes& data)
|
||||
unsigned pos = 0;
|
||||
while (pos < data.size())
|
||||
{
|
||||
auto& [cylinder, head, sectorId] =
|
||||
const 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);
|
||||
const auto& ltl =
|
||||
_diskLayout->layoutByLogicalLocation.at({cylinder, head});
|
||||
const auto& sector = _sectors->put(cylinder, head, sectorId);
|
||||
sector->status = Sector::OK;
|
||||
sector->data = data.slice(pos, ltl->sectorSize);
|
||||
pos += ltl->sectorSize;
|
||||
number++;
|
||||
}
|
||||
|
||||
@@ -225,6 +225,7 @@ public:
|
||||
public:
|
||||
Filesystem(const std::shared_ptr<const DiskLayout>& diskLayout,
|
||||
std::shared_ptr<SectorInterface> sectors);
|
||||
virtual ~Filesystem() {};
|
||||
|
||||
Bytes getSector(unsigned track, unsigned side, unsigned sector);
|
||||
|
||||
@@ -238,7 +239,7 @@ public:
|
||||
void eraseEverythingOnDisk();
|
||||
|
||||
protected:
|
||||
const std::shared_ptr<const DiskLayout>& _diskLayout;
|
||||
const std::shared_ptr<const DiskLayout> _diskLayout;
|
||||
unsigned _blockCount;
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "lib/data/fluxmap.h"
|
||||
#include "lib/decoders/decoders.h"
|
||||
#include "lib/data/sector.h"
|
||||
#include "lib/data/layout.h"
|
||||
#include "lib/config/proto.h"
|
||||
#include "lib/fluxsource/fluxsource.h"
|
||||
#include "lib/fluxsink/fluxsink.h"
|
||||
@@ -50,11 +51,12 @@ int mainRead(int argc, const char* argv[])
|
||||
if (globalConfig()->decoder().copy_flux_to().type() == FLUXTYPE_DRIVE)
|
||||
error("you cannot copy flux to a hardware device");
|
||||
|
||||
auto diskLayout = createDiskLayout(globalConfig());
|
||||
auto fluxSource = FluxSource::create(globalConfig());
|
||||
auto decoder = Arch::createDecoder(globalConfig());
|
||||
auto writer = ImageWriter::create(globalConfig());
|
||||
|
||||
readDiskCommand(*fluxSource, *decoder, *writer);
|
||||
readDiskCommand(*diskLayout, *fluxSource, *decoder, *writer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ static void emitOptions(DynamicSetting<std::string>& setting,
|
||||
if (value)
|
||||
options[it.name()] = "true";
|
||||
setting = optionsToString(options);
|
||||
Datastore::reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,6 +147,7 @@ static void emitOptions(DynamicSetting<std::string>& setting,
|
||||
options[it.name()] = ot.name();
|
||||
}
|
||||
setting = optionsToString(options);
|
||||
Datastore::reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +185,10 @@ static void formatProperties()
|
||||
label = name;
|
||||
if (ImGui::Selectable(
|
||||
fmt::format("{}##{}", label, name).c_str(), false))
|
||||
{
|
||||
formatSetting = name;
|
||||
Datastore::reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -130,10 +130,11 @@ void ControlPanelView::drawContent()
|
||||
"fluxengine.view.controlpanel.rereadBad"_lang,
|
||||
nullptr,
|
||||
busy || !diskFlux);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::TableNextRow();
|
||||
button(ICON_VS_NEW_FILE,
|
||||
"fluxengine.view.controlpanel.createBlank"_lang,
|
||||
nullptr,
|
||||
Datastore::createBlankImage,
|
||||
busy || !Datastore::canFormat());
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
#include "lib/fluxsource/fluxsource.h"
|
||||
#include "lib/fluxsink/fluxsink.h"
|
||||
#include "lib/decoders/decoders.h"
|
||||
#include "lib/encoders/encoders.h"
|
||||
#include "lib/imagewriter/imagewriter.h"
|
||||
#include "lib/algorithms/readerwriter.h"
|
||||
#include "lib/usb/usbfinder.h"
|
||||
#include "lib/vfs/vfs.h"
|
||||
#include "lib/vfs/sectorinterface.h"
|
||||
#include "arch/arch.h"
|
||||
#include "logview.h"
|
||||
#include "globals.h"
|
||||
@@ -208,34 +210,31 @@ void Datastore::init()
|
||||
Events::SeekToSectorViaPhysicalLocation::subscribe(
|
||||
[](CylinderHeadSector physicalLocation)
|
||||
{
|
||||
if (diskLayout)
|
||||
if (!diskLayout)
|
||||
return;
|
||||
auto& ptlo = findOptionally(diskLayout->layoutByPhysicalLocation,
|
||||
{physicalLocation.cylinder, physicalLocation.head});
|
||||
if (ptlo.has_value())
|
||||
{
|
||||
auto& ptlo =
|
||||
findOptionally(diskLayout->layoutByPhysicalLocation,
|
||||
{physicalLocation.cylinder, physicalLocation.head});
|
||||
if (ptlo.has_value())
|
||||
{
|
||||
auto& ptl = *ptlo;
|
||||
auto offseto = findOptionally(
|
||||
diskLayout->sectorOffsetByLogicalSectorLocation,
|
||||
{ptl->logicalTrackLayout->logicalCylinder,
|
||||
ptl->logicalTrackLayout->logicalHead,
|
||||
physicalLocation.sector});
|
||||
if (offseto.has_value())
|
||||
hex::ImHexApi::HexEditor::setSelection(hex::Region(
|
||||
*offseto, ptl->logicalTrackLayout->sectorSize));
|
||||
}
|
||||
auto& ptl = *ptlo;
|
||||
auto offseto = findOptionally(
|
||||
diskLayout->sectorOffsetByLogicalSectorLocation,
|
||||
{ptl->logicalTrackLayout->logicalCylinder,
|
||||
ptl->logicalTrackLayout->logicalHead,
|
||||
physicalLocation.sector});
|
||||
if (offseto.has_value())
|
||||
hex::ImHexApi::HexEditor::setSelection(hex::Region(
|
||||
*offseto, ptl->logicalTrackLayout->sectorSize));
|
||||
}
|
||||
});
|
||||
|
||||
Events::SeekToTrackViaPhysicalLocation::subscribe(
|
||||
[](CylinderHead physicalLocation)
|
||||
{
|
||||
if (!diskFlux)
|
||||
if (!diskFlux || !diskLayout)
|
||||
return;
|
||||
auto ptlo =
|
||||
findOptionally(diskFlux->layout->layoutByPhysicalLocation,
|
||||
{physicalLocation.cylinder, physicalLocation.head});
|
||||
auto ptlo = findOptionally(diskLayout->layoutByPhysicalLocation,
|
||||
{physicalLocation.cylinder, physicalLocation.head});
|
||||
if (!ptlo.has_value())
|
||||
return;
|
||||
auto ptl = *ptlo;
|
||||
@@ -244,10 +243,10 @@ void Datastore::init()
|
||||
unsigned lastSectorId = ltl->filesystemSectorOrder.back();
|
||||
|
||||
unsigned startOffset =
|
||||
diskFlux->layout->sectorOffsetByLogicalSectorLocation.at(
|
||||
diskLayout->sectorOffsetByLogicalSectorLocation.at(
|
||||
{ltl->logicalCylinder, ltl->logicalHead, firstSectorId});
|
||||
unsigned endOffset =
|
||||
diskFlux->layout->sectorOffsetByLogicalSectorLocation.at(
|
||||
diskLayout->sectorOffsetByLogicalSectorLocation.at(
|
||||
{ltl->logicalCylinder, ltl->logicalHead, lastSectorId}) +
|
||||
ltl->sectorSize;
|
||||
|
||||
@@ -521,7 +520,20 @@ void Datastore::beginRead(void)
|
||||
auto decoder = Arch::createDecoder(globalConfig());
|
||||
|
||||
auto diskflux = std::make_shared<DecodedDisk>();
|
||||
readDiskCommand(*fluxSource, *decoder, *diskflux);
|
||||
readDiskCommand(*diskLayout, *fluxSource, *decoder, *diskflux);
|
||||
});
|
||||
}
|
||||
|
||||
void Datastore::reset()
|
||||
{
|
||||
Datastore::runOnWorkerThread(
|
||||
[]
|
||||
{
|
||||
busy = true;
|
||||
DEFER(busy = false);
|
||||
|
||||
wtRebuildConfiguration();
|
||||
wtWaitForUiThreadToCatchUp();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -576,7 +588,28 @@ void Datastore::createBlankImage()
|
||||
ON_SCOPE_EXIT
|
||||
{
|
||||
busy = false;
|
||||
wtRebuildConfiguration();
|
||||
};
|
||||
|
||||
wtRebuildConfiguration();
|
||||
auto diskflux = std::make_shared<DecodedDisk>();
|
||||
auto image = std::make_shared<Image>();
|
||||
std::shared_ptr<SectorInterface> sectorInterface =
|
||||
SectorInterface::createMemorySectorInterface(image);
|
||||
auto filesystem = Filesystem::createFilesystem(
|
||||
globalConfig()->filesystem(), diskLayout, sectorInterface);
|
||||
|
||||
filesystem->create(false, "FLUXENGINE");
|
||||
filesystem->flushChanges();
|
||||
|
||||
image->calculateSize();
|
||||
image->populateSectorPhysicalLocationsFromLogicalLocations(
|
||||
*diskLayout);
|
||||
diskflux->image = image;
|
||||
diskflux->populateTrackDataFromImage(*diskLayout);
|
||||
hex::TaskManager::doLater(
|
||||
[=]
|
||||
{
|
||||
::diskFlux = diskflux;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,20 +61,21 @@ void DiskProvider::close() {}
|
||||
void DiskProvider::readRaw(u64 offset, void* buffer, size_t size)
|
||||
{
|
||||
const auto& diskFlux = Datastore::getDecodedDisk();
|
||||
if (diskFlux && diskFlux->image)
|
||||
const auto& diskLayout = Datastore::getDiskLayout();
|
||||
if (diskFlux && diskFlux->image && diskLayout)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
auto it = diskFlux->layout->logicalSectorLocationBySectorOffset
|
||||
.upper_bound(offset);
|
||||
if (it !=
|
||||
diskFlux->layout->logicalSectorLocationBySectorOffset.begin())
|
||||
auto it =
|
||||
diskLayout->logicalSectorLocationBySectorOffset.upper_bound(
|
||||
offset);
|
||||
if (it != diskLayout->logicalSectorLocationBySectorOffset.begin())
|
||||
it--;
|
||||
|
||||
unsigned realOffset = it->first;
|
||||
auto logicalLocation = it->second;
|
||||
auto sector = diskFlux->image->get(logicalLocation);
|
||||
auto& ltl = diskFlux->layout->layoutByLogicalLocation.at(
|
||||
auto& ltl = diskLayout->layoutByLogicalLocation.at(
|
||||
logicalLocation.trackLocation());
|
||||
unsigned blockOffset = realOffset - offset;
|
||||
unsigned bytesRemaining =
|
||||
|
||||
@@ -25,12 +25,13 @@ DiskLayout::LayoutBounds PhysicalView::getBounds()
|
||||
std::shared_ptr<const Sector> PhysicalView::getSector(
|
||||
unsigned physicalCylinder, unsigned physicalHead, unsigned sectorId)
|
||||
{
|
||||
auto diskFlux = Datastore::getDecodedDisk();
|
||||
auto& ptl = findOrDefault(diskFlux->layout->layoutByPhysicalLocation,
|
||||
{physicalCylinder, physicalHead});
|
||||
const auto& diskFlux = Datastore::getDecodedDisk();
|
||||
const auto& diskLayout = Datastore::getDiskLayout();
|
||||
const auto& ptl = findOrDefault(
|
||||
diskLayout->layoutByPhysicalLocation, {physicalCylinder, physicalHead});
|
||||
if (!ptl)
|
||||
return nullptr;
|
||||
auto& ltl = ptl->logicalTrackLayout;
|
||||
const auto& ltl = ptl->logicalTrackLayout;
|
||||
return diskFlux->image->get(
|
||||
{ltl->logicalCylinder, ltl->logicalHead, sectorId});
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"fluxengine.view.controlpanel.readImage": "Load disk image",
|
||||
"fluxengine.view.controlpanel.writeImage": "Save disk image",
|
||||
"fluxengine.view.controlpanel.rereadBad": "Re-read bad tracks",
|
||||
"fluxengine.view.controlpanel.createBlank": "Format disk",
|
||||
"fluxengine.view.controlpanel.createBlank": "Empty filesystem",
|
||||
"fluxengine.view.controlpanel.stop": "Stop",
|
||||
|
||||
"fluxengine.view.log.name": "FluxEngine log viewer"
|
||||
|
||||
Reference in New Issue
Block a user