diff --git a/Analyser/Static/Acorn/Disk.cpp b/Analyser/Static/Acorn/Disk.cpp index 220f6d5c96..9b1516381f 100644 --- a/Analyser/Static/Acorn/Disk.cpp +++ b/Analyser/Static/Acorn/Disk.cpp @@ -19,10 +19,10 @@ using namespace Analyser::Static::Acorn; std::unique_ptr Analyser::Static::Acorn::GetDFSCatalogue(const std::shared_ptr &disk) { // c.f. http://beebwiki.mdfs.net/Acorn_DFS_disc_format auto catalogue = std::make_unique(); - Storage::Encodings::MFM::Parser parser(false, disk); + Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Single, disk); - const Storage::Encodings::MFM::Sector *const names = parser.get_sector(0, 0, 0); - const Storage::Encodings::MFM::Sector *const details = parser.get_sector(0, 0, 1); + const Storage::Encodings::MFM::Sector *const names = parser.sector(0, 0, 0); + const Storage::Encodings::MFM::Sector *const details = parser.sector(0, 0, 1); if(!names || !details) return nullptr; if(names->samples.empty() || details->samples.empty()) return nullptr; @@ -65,7 +65,7 @@ std::unique_ptr Analyser::Static::Acorn::GetDFSCatalogue(const std::s uint8_t track = uint8_t(start_sector / 10); start_sector++; - Storage::Encodings::MFM::Sector *next_sector = parser.get_sector(0, track, sector); + const Storage::Encodings::MFM::Sector *next_sector = parser.sector(0, track, sector); if(!next_sector) break; long length_from_sector = std::min(data_length, 256l); @@ -84,15 +84,15 @@ std::unique_ptr Analyser::Static::Acorn::GetDFSCatalogue(const std::s */ std::unique_ptr Analyser::Static::Acorn::GetADFSCatalogue(const std::shared_ptr &disk) { auto catalogue = std::make_unique(); - Storage::Encodings::MFM::Parser parser(true, disk); + Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk); - Storage::Encodings::MFM::Sector *free_space_map_second_half = parser.get_sector(0, 0, 1); + const Storage::Encodings::MFM::Sector *free_space_map_second_half = parser.sector(0, 0, 1); if(!free_space_map_second_half) return nullptr; std::vector root_directory; root_directory.reserve(5 * 256); for(uint8_t c = 2; c < 7; c++) { - const Storage::Encodings::MFM::Sector *const sector = parser.get_sector(0, 0, c); + const Storage::Encodings::MFM::Sector *const sector = parser.sector(0, 0, c); if(!sector) return nullptr; root_directory.insert(root_directory.end(), sector->samples[0].begin(), sector->samples[0].end()); } @@ -166,7 +166,7 @@ std::unique_ptr Analyser::Static::Acorn::GetADFSCatalogue(const std:: new_file.data.reserve(size); while(new_file.data.size() < size) { - const Storage::Encodings::MFM::Sector *const sector = parser.get_sector(start_sector / (80 * 16), (start_sector / 16) % 80, start_sector % 16); + const Storage::Encodings::MFM::Sector *const sector = parser.sector(start_sector / (80 * 16), (start_sector / 16) % 80, start_sector % 16); if(!sector) break; const auto length_from_sector = std::min(size - new_file.data.size(), sector->samples[0].size()); diff --git a/Analyser/Static/AmstradCPC/StaticAnalyser.cpp b/Analyser/Static/AmstradCPC/StaticAnalyser.cpp index 2ca6924b6b..842371fe2d 100644 --- a/Analyser/Static/AmstradCPC/StaticAnalyser.cpp +++ b/Analyser/Static/AmstradCPC/StaticAnalyser.cpp @@ -159,8 +159,8 @@ void InspectCatalogue( } bool CheckBootSector(const std::shared_ptr &disk, const std::unique_ptr &target) { - Storage::Encodings::MFM::Parser parser(true, disk); - Storage::Encodings::MFM::Sector *boot_sector = parser.get_sector(0, 0, 0x41); + Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk); + const Storage::Encodings::MFM::Sector *boot_sector = parser.sector(0, 0, 0x41); if(boot_sector != nullptr && !boot_sector->samples.empty() && boot_sector->samples[0].size() == 512) { // Check that the first 64 bytes of the sector aren't identical; if they are then probably // this disk was formatted and the filler byte never replaced. diff --git a/Analyser/Static/Commodore/Disk.cpp b/Analyser/Static/Commodore/Disk.cpp index d83d2a54ce..e759a636f6 100644 --- a/Analyser/Static/Commodore/Disk.cpp +++ b/Analyser/Static/Commodore/Disk.cpp @@ -37,7 +37,7 @@ class CommodoreGCRParser: public Storage::Disk::Controller { @returns a sector if one was found; @c nullptr otherwise. */ - std::shared_ptr get_sector(uint8_t track, uint8_t sector) { + std::shared_ptr sector(uint8_t track, uint8_t sector) { int difference = int(track) - int(track_); track_ = track; @@ -182,7 +182,7 @@ std::vector Analyser::Static::Commodore::GetFiles(const std::shared_ptrdata.begin(), sector->data.end()); next_track = sector->data[0]; @@ -221,7 +221,7 @@ std::vector Analyser::Static::Commodore::GetFiles(const std::shared_ptrdata[0]; diff --git a/Analyser/Static/FAT12/StaticAnalyser.cpp b/Analyser/Static/FAT12/StaticAnalyser.cpp index 241705e334..dfca8053e1 100644 --- a/Analyser/Static/FAT12/StaticAnalyser.cpp +++ b/Analyser/Static/FAT12/StaticAnalyser.cpp @@ -44,7 +44,7 @@ Analyser::Static::TargetList Analyser::Static::FAT12::GetTargets(const Media &me Storage::Disk::track_serialisation( *track_zero, Storage::Encodings::MFM::MFMBitLength - ), true); + ), Storage::Encodings::MFM::Density::Double); // If no sectors were found, assume this disk was either single density or high density, which both imply the PC. if(sector_map.empty() || sector_map.size() > 10) { diff --git a/Analyser/Static/Oric/StaticAnalyser.cpp b/Analyser/Static/Oric/StaticAnalyser.cpp index 2077ec2658..273c01e9f6 100644 --- a/Analyser/Static/Oric/StaticAnalyser.cpp +++ b/Analyser/Static/Oric/StaticAnalyser.cpp @@ -85,7 +85,7 @@ bool is_microdisc(Storage::Encodings::MFM::Parser &parser) { /* The Microdisc boot sector is sector 2 of track 0 and contains a 23-byte signature. */ - Storage::Encodings::MFM::Sector *sector = parser.get_sector(0, 0, 2); + const Storage::Encodings::MFM::Sector *sector = parser.sector(0, 0, 2); if(!sector) return false; if(sector->samples.empty()) return false; @@ -108,7 +108,7 @@ bool is_400_loader(Storage::Encodings::MFM::Parser &parser, uint16_t range_start use disassembly to test for likely matches. */ - Storage::Encodings::MFM::Sector *sector = parser.get_sector(0, 0, 1); + const Storage::Encodings::MFM::Sector *sector = parser.sector(0, 0, 1); if(!sector) return false; if(sector->samples.empty()) return false; @@ -175,7 +175,7 @@ Analyser::Static::TargetList Analyser::Static::Oric::GetTargets(const Media &med // 8-DOS is recognised by a dedicated Disk II analyser, so check only for Microdisc, // Jasmin and BD-DOS formats here. for(auto &disk: media.disks) { - Storage::Encodings::MFM::Parser parser(true, disk); + Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk); if(is_microdisc(parser)) { target->disk_interface = Target::DiskInterface::Microdisc; diff --git a/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp b/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp index 0c21161e89..396c67f238 100644 --- a/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp +++ b/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp @@ -33,14 +33,14 @@ bool IsSpectrumTape(const std::shared_ptr &tape) { } bool IsSpectrumDisk(const std::shared_ptr &disk) { - Storage::Encodings::MFM::Parser parser(true, disk); + Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk); // Get logical sector 1; the Spectrum appears to support various physical // sectors as sector 1. - Storage::Encodings::MFM::Sector *boot_sector = nullptr; + const Storage::Encodings::MFM::Sector *boot_sector = nullptr; uint8_t sector_mask = 0; while(!boot_sector) { - boot_sector = parser.get_sector(0, 0, sector_mask + 1); + boot_sector = parser.sector(0, 0, sector_mask + 1); sector_mask += 0x40; if(!sector_mask) break; } diff --git a/Machines/PCCompatible/PCCompatible.cpp b/Machines/PCCompatible/PCCompatible.cpp index 76db9c97ae..dd0cb875e2 100644 --- a/Machines/PCCompatible/PCCompatible.cpp +++ b/Machines/PCCompatible/PCCompatible.cpp @@ -34,8 +34,7 @@ #include "../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp" #include "../../Storage/Disk/Track/TrackSerialiser.hpp" -#include "../../Storage/Disk/Encodings/MFM/Constants.hpp" -#include "../../Storage/Disk/Encodings/MFM/SegmentParser.hpp" +#include "../../Storage/Disk/Encodings/MFM/Parser.hpp" #include "../AudioProducer.hpp" #include "../KeyboardMachine.hpp" @@ -150,50 +149,32 @@ class FloppyController { auto target = decoder_.geometry(); bool complete = false; while(!complete) { - bool found_sector = false; - - for(auto &pair: drives_[decoder_.target().drive].sectors(decoder_.target().head)) { - // TODO: I suspect that not all these fields are tested for equality. - if( - (pair.second.address.track == target.cylinder) && - (pair.second.address.sector == target.sector) && - (pair.second.address.side == target.head) && - (pair.second.size == target.size) && - (pair.second.is_deleted == (decoder_.command() == Command::ReadDeletedData)) - ) { - found_sector = true; - bool wrote_in_full = true; - - for(int c = 0; c < 128 << target.size; c++) { - const auto access_result = dma_.write(2, pair.second.samples[0].data()[c]); - switch(access_result) { - default: break; - case AccessResult::NotAccepted: - complete = true; - wrote_in_full = false; - break; - case AccessResult::AcceptedWithEOP: - complete = true; - break; - } - if(access_result != AccessResult::Accepted) { - break; - } - } - - if(!wrote_in_full) { - status_.set(Intel::i8272::Status1::OverRun); - status_.set(Intel::i8272::Status0::AbnormalTermination); + const auto sector = drives_[decoder_.target().drive].sector(target.head, target.sector); + + if(sector) { + // TODO: I _think_ I'm supposed to validate the rest of the address here? + + for(int c = 0; c < 128 << target.size; c++) { + const auto access_result = dma_.write(2, sector->samples[0].data()[c]); + switch(access_result) { + // Default: keep going. + default: continue; + + // Anything else: update flags and exit. + case AccessResult::NotAccepted: + complete = true; + status_.set(Intel::i8272::Status1::OverRun); + status_.set(Intel::i8272::Status0::AbnormalTermination); + break; + case AccessResult::AcceptedWithEOP: + complete = true; break; } - - ++target.sector; // TODO: multitrack? - break; } - } - if(!found_sector) { + ++target.sector; // TODO: multitrack? + } else { status_.set(Intel::i8272::Status1::EndOfCylinder); status_.set(Intel::i8272::Status0::AbnormalTermination); break; @@ -342,58 +323,19 @@ class FloppyController { bool exists = true; bool has_disk() const { - return bool(disk); + return static_cast(parser_); } void set_disk(std::shared_ptr image) { - disk = image; - cached.clear(); + parser_ = std::make_unique(image); } - Storage::Encodings::MFM::SectorMap §ors(bool side) { - if(cached.track == track && cached.side == side) { - return cached.sectors; - } - - cached.track = track; - cached.side = side; - cached.sectors.clear(); - - if(!disk) { - return cached.sectors; - } - - auto raw_track = disk->get_track_at_position( - Storage::Disk::Track::Address( - side, - Storage::Disk::HeadPosition(track) - ) - ); - if(!raw_track) { - return cached.sectors; - } - - const bool is_double_density = true; // TODO: use MFM flag here. - auto serialisation = Storage::Disk::track_serialisation( - *raw_track, - is_double_density ? Storage::Encodings::MFM::MFMBitLength : Storage::Encodings::MFM::FMBitLength - ); - cached.sectors = Storage::Encodings::MFM::sectors_from_segment(std::move(serialisation), is_double_density); - return cached.sectors; + const Storage::Encodings::MFM::Sector *sector(int head, uint8_t sector) { + return parser_ ? parser_->sector(head, track, sector) : nullptr; } private: - struct { - uint8_t track = 0xff; - bool side; - Storage::Encodings::MFM::SectorMap sectors; - - void clear() { - track = 0xff; - sectors.clear(); - } - } cached; - std::shared_ptr disk; + std::unique_ptr parser_; } drives_[4]; diff --git a/Storage/Disk/Controller/MFMDiskController.cpp b/Storage/Disk/Controller/MFMDiskController.cpp index ef3122291f..c6d57a8c0c 100644 --- a/Storage/Disk/Controller/MFMDiskController.cpp +++ b/Storage/Disk/Controller/MFMDiskController.cpp @@ -32,7 +32,7 @@ void MFMController::set_is_double_density(bool is_double_density) { bit_length.clock_rate = is_double_density ? 500000 : 250000; set_expected_bit_length(bit_length); - shifter_.set_is_double_density(is_double_density); + shifter_.set_is_mfm(is_double_density); } bool MFMController::get_is_double_density() { diff --git a/Storage/Disk/DiskImage/Formats/AcornADF.cpp b/Storage/Disk/DiskImage/Formats/AcornADF.cpp index b7c4fd2d39..57e333c199 100644 --- a/Storage/Disk/DiskImage/Formats/AcornADF.cpp +++ b/Storage/Disk/DiskImage/Formats/AcornADF.cpp @@ -39,7 +39,7 @@ AcornADF::AcornADF(const std::string &file_name) : MFMSectorDump(file_name) { head_count_ = 1 + (file_.stats().st_size > sectors_per_track * sizeT(128 << sector_size) * 80); // Announce disk geometry. - set_geometry(sectors_per_track, sector_size, 0, true); + set_geometry(sectors_per_track, sector_size, 0, Encodings::MFM::Density::Double); } HeadPosition AcornADF::get_maximum_head_position() { diff --git a/Storage/Disk/DiskImage/Formats/CPCDSK.cpp b/Storage/Disk/DiskImage/Formats/CPCDSK.cpp index ac81e5556f..28a0b9c416 100644 --- a/Storage/Disk/DiskImage/Formats/CPCDSK.cpp +++ b/Storage/Disk/DiskImage/Formats/CPCDSK.cpp @@ -214,7 +214,11 @@ std::shared_ptr CPCDSK::get_track_at_position(::Storage::Disk::Track::Add } // TODO: FM encoding, data rate? - return Storage::Encodings::MFM::GetMFMTrackWithSectors(sectors, track->gap3_length, track->filler_byte); + return Storage::Encodings::MFM::TrackWithSectors( + Storage::Encodings::MFM::Density::Double, + sectors, + track->gap3_length, + track->filler_byte); } void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::shared_ptr<::Storage::Disk::Track>> &tracks) { @@ -225,7 +229,7 @@ void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::sha std::map sectors = Storage::Encodings::MFM::sectors_from_segment( Storage::Disk::track_serialisation(*pair.second, is_double_density ? Storage::Encodings::MFM::MFMBitLength : Storage::Encodings::MFM::FMBitLength), - is_double_density); + Storage::Encodings::MFM::Density::Double); // Find slot for track, making it if neccessary. const std::size_t chronological_track = index_for_track(pair.first); diff --git a/Storage/Disk/DiskImage/Formats/FAT12.cpp b/Storage/Disk/DiskImage/Formats/FAT12.cpp index 574e61c961..fc2d8b6dbb 100644 --- a/Storage/Disk/DiskImage/Formats/FAT12.cpp +++ b/Storage/Disk/DiskImage/Formats/FAT12.cpp @@ -41,7 +41,12 @@ FAT12::FAT12(const std::string &file_name) : } if(log_sector_size >= 5) throw Error::InvalidFormat; - set_geometry(sector_count_, log_sector_size, 1, true); + set_geometry( + sector_count_, + log_sector_size, + 1, + sector_count_ > 10 ? Encodings::MFM::Density::High : Encodings::MFM::Density::Double + ); } HeadPosition FAT12::get_maximum_head_position() { diff --git a/Storage/Disk/DiskImage/Formats/IMD.cpp b/Storage/Disk/DiskImage/Formats/IMD.cpp index 379fddaf5d..b94435a9a9 100644 --- a/Storage/Disk/DiskImage/Formats/IMD.cpp +++ b/Storage/Disk/DiskImage/Formats/IMD.cpp @@ -157,7 +157,13 @@ std::shared_ptr<::Storage::Disk::Track> IMD::get_track_at_position(::Storage::Di // Mode also indicates data density, but I don't have a good strategy for reconciling that if // it were to disagree with the density implied by the quantity of sectors. So a broad 'is it MFM' test is // applied only. - return (mode >= 3) ? - Storage::Encodings::MFM::GetMFMTrackWithSectors(sectors) : - Storage::Encodings::MFM::GetFMTrackWithSectors(sectors); + using namespace Storage::Encodings::MFM; + if(mode < 3) { + return TrackWithSectors(Density::Single, sectors); + } + if(sector_size * sector_count >= 6912) { + return TrackWithSectors(Density::High, sectors); + } else { + return TrackWithSectors(Density::Double, sectors); + } } diff --git a/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp b/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp index 9f629b9869..f0ce69d279 100644 --- a/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp +++ b/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp @@ -14,10 +14,10 @@ using namespace Storage::Disk; MFMSectorDump::MFMSectorDump(const std::string &file_name) : file_(file_name) {} -void MFMSectorDump::set_geometry(int sectors_per_track, uint8_t sector_size, uint8_t first_sector, bool is_double_density) { +void MFMSectorDump::set_geometry(int sectors_per_track, uint8_t sector_size, uint8_t first_sector, Encodings::MFM::Density density) { sectors_per_track_ = sectors_per_track; sector_size_ = sector_size; - is_double_density_ = is_double_density; + density_ = density; first_sector_ = first_sector; } @@ -34,7 +34,14 @@ std::shared_ptr MFMSectorDump::get_track_at_position(Track::Address addre file_.read(sectors, sizeof(sectors)); } - return track_for_sectors(sectors, sectors_per_track_, uint8_t(address.position.as_int()), uint8_t(address.head), first_sector_, sector_size_, is_double_density_); + return track_for_sectors( + sectors, + sectors_per_track_, + uint8_t(address.position.as_int()), + uint8_t(address.head), + first_sector_, + sector_size_, + density_); } void MFMSectorDump::set_tracks(const std::map> &tracks) { @@ -44,7 +51,13 @@ void MFMSectorDump::set_tracks(const std::map @@ -29,14 +30,14 @@ class MFMSectorDump: public DiskImage { protected: Storage::FileHolder file_; - void set_geometry(int sectors_per_track, uint8_t sector_size, uint8_t first_sector, bool is_double_density); + void set_geometry(int sectors_per_track, uint8_t sector_size, uint8_t first_sector, Encodings::MFM::Density density); private: virtual long get_file_offset_for_position(Track::Address address) = 0; int sectors_per_track_ = 0; uint8_t sector_size_ = 0; - bool is_double_density_ = true; + Encodings::MFM::Density density_ = Encodings::MFM::Density::Single; uint8_t first_sector_ = 0; }; diff --git a/Storage/Disk/DiskImage/Formats/MSA.cpp b/Storage/Disk/DiskImage/Formats/MSA.cpp index 2da6976052..a2917d4710 100644 --- a/Storage/Disk/DiskImage/Formats/MSA.cpp +++ b/Storage/Disk/DiskImage/Formats/MSA.cpp @@ -84,7 +84,7 @@ std::shared_ptr<::Storage::Disk::Track> MSA::get_track_at_position(::Storage::Di const auto &track = uncompressed_tracks_[size_t(position - starting_track_) * size_t(sides_) + size_t(address.head)]; assert(!track.empty()); - return track_for_sectors(track.data(), sectors_per_track_, uint8_t(position), uint8_t(address.head), 1, 2, true); + return track_for_sectors(track.data(), sectors_per_track_, uint8_t(position), uint8_t(address.head), 1, 2, Storage::Encodings::MFM::Density::Double); } HeadPosition MSA::get_maximum_head_position() { diff --git a/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp b/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp index f7bd337446..9e4ec60603 100644 --- a/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp +++ b/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp @@ -119,7 +119,7 @@ void OricMFMDSK::set_tracks(const std::map parsed_track; int size = 0; diff --git a/Storage/Disk/DiskImage/Formats/PCBooter.cpp b/Storage/Disk/DiskImage/Formats/PCBooter.cpp index 54e14a8ea9..20701f572a 100644 --- a/Storage/Disk/DiskImage/Formats/PCBooter.cpp +++ b/Storage/Disk/DiskImage/Formats/PCBooter.cpp @@ -47,7 +47,8 @@ PCBooter::PCBooter(const std::string &file_name) : break; } - set_geometry(sector_count_, 2, 1, true); + // TODO: probably single density, actually? + set_geometry(sector_count_, 2, 1, Encodings::MFM::Density::Double); // TODO: check that an appropriate INT or similar is in the boot sector? // Should probably factor out the "does this look like a PC boot sector?" test, diff --git a/Storage/Disk/DiskImage/Formats/SSD.cpp b/Storage/Disk/DiskImage/Formats/SSD.cpp index 455fddc4a7..b312e6ac44 100644 --- a/Storage/Disk/DiskImage/Formats/SSD.cpp +++ b/Storage/Disk/DiskImage/Formats/SSD.cpp @@ -29,7 +29,7 @@ SSD::SSD(const std::string &file_name) : MFMSectorDump(file_name) { if(track_count_ < 40) track_count_ = 40; else if(track_count_ < 80) track_count_ = 80; - set_geometry(sectors_per_track, sector_size, 0, false); + set_geometry(sectors_per_track, sector_size, 0, Encodings::MFM::Density::Single); } HeadPosition SSD::get_maximum_head_position() { diff --git a/Storage/Disk/DiskImage/Formats/STX.cpp b/Storage/Disk/DiskImage/Formats/STX.cpp index 6aafc04fd8..4c26038edc 100644 --- a/Storage/Disk/DiskImage/Formats/STX.cpp +++ b/Storage/Disk/DiskImage/Formats/STX.cpp @@ -136,7 +136,7 @@ class TrackConstructor { using Shifter = Storage::Encodings::MFM::Shifter; Shifter shifter; shifter.set_should_obey_syncs(true); - shifter.set_is_double_density(true); + shifter.set_is_mfm(true); result.emplace_back(); @@ -469,7 +469,7 @@ std::shared_ptr<::Storage::Disk::Track> STX::get_track_at_position(::Storage::Di // If this is a trivial .ST-style sector dump, life is easy. if(!(flags & 1)) { const auto sector_contents = file_.read(sector_count * 512); - return track_for_sectors(sector_contents.data(), sector_count, uint8_t(address.position.as_int()), uint8_t(address.head), 1, 2, true); + return track_for_sectors(sector_contents.data(), sector_count, uint8_t(address.position.as_int()), uint8_t(address.head), 1, 2, Storage::Encodings::MFM::Density::Double); } // Grab sector records, if provided. diff --git a/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp b/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp index fa6993e747..b18242a5b6 100644 --- a/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp +++ b/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.cpp @@ -18,7 +18,15 @@ using namespace Storage::Disk; -std::shared_ptr Storage::Disk::track_for_sectors(const uint8_t *const source, int number_of_sectors, uint8_t track, uint8_t side, uint8_t first_sector, uint8_t size, bool is_double_density) { +std::shared_ptr Storage::Disk::track_for_sectors( + const uint8_t *const source, + int number_of_sectors, + uint8_t track, + uint8_t side, + uint8_t first_sector, + uint8_t size, + Storage::Encodings::MFM::Density density +) { std::vector sectors; size_t byte_size = size_t(128 << size); @@ -39,17 +47,27 @@ std::shared_ptr Storage::Disk::track_for_sectors(const uint8_t *const sou } if(!sectors.empty()) { - return is_double_density ? Storage::Encodings::MFM::GetMFMTrackWithSectors(sectors) : Storage::Encodings::MFM::GetFMTrackWithSectors(sectors); + return TrackWithSectors(density, sectors); } return nullptr; } -void Storage::Disk::decode_sectors(Track &track, uint8_t *const destination, uint8_t first_sector, uint8_t last_sector, uint8_t sector_size, bool is_double_density) { +void Storage::Disk::decode_sectors( + const Track &track, + uint8_t *const destination, + uint8_t first_sector, + uint8_t last_sector, + uint8_t sector_size, + Storage::Encodings::MFM::Density density +) { std::map sectors = Storage::Encodings::MFM::sectors_from_segment( - Storage::Disk::track_serialisation(track, is_double_density ? Storage::Encodings::MFM::MFMBitLength : Storage::Encodings::MFM::FMBitLength), - is_double_density); + Storage::Disk::track_serialisation( + track, + Storage::Encodings::MFM::bit_length(density) + ), + density); std::size_t byte_size = size_t(128 << sector_size); for(const auto &pair : sectors) { diff --git a/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp b/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp index 3714837d8e..d6db555c5a 100644 --- a/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp +++ b/Storage/Disk/DiskImage/Formats/Utility/ImplicitSectors.hpp @@ -13,10 +13,13 @@ #include #include +#include "../../../Encodings/MFM/Encoder.hpp" + + namespace Storage::Disk { -std::shared_ptr track_for_sectors(const uint8_t *source, int number_of_sectors, uint8_t track, uint8_t side, uint8_t first_sector, uint8_t size, bool is_double_density); -void decode_sectors(Track &track, uint8_t *destination, uint8_t first_sector, uint8_t last_sector, uint8_t sector_size, bool is_double_density); +std::shared_ptr track_for_sectors(const uint8_t *source, int number_of_sectors, uint8_t track, uint8_t side, uint8_t first_sector, uint8_t size, Storage::Encodings::MFM::Density density); +void decode_sectors(const Track &track, uint8_t *destination, uint8_t first_sector, uint8_t last_sector, uint8_t sector_size, Storage::Encodings::MFM::Density density); } diff --git a/Storage/Disk/Encodings/MFM/Constants.hpp b/Storage/Disk/Encodings/MFM/Constants.hpp index 011af4dc9c..838e7d34e4 100644 --- a/Storage/Disk/Encodings/MFM/Constants.hpp +++ b/Storage/Disk/Encodings/MFM/Constants.hpp @@ -13,6 +13,14 @@ namespace Storage::Encodings::MFM { +enum class Density { + Single, Double, High +}; + +constexpr bool is_mfm(Density density) { + return density != Density::Single; +} + const uint8_t IndexAddressByte = 0xfc; const uint8_t IDAddressByte = 0xfe; const uint8_t DataAddressByte = 0xfb; @@ -30,9 +38,18 @@ const uint16_t MFMPostSyncCRCValue = 0xcdb4; // the value the CRC generator sho const uint8_t MFMIndexSyncByteValue = 0xc2; const uint8_t MFMSyncByteValue = 0xa1; +const Time HDMFMBitLength = Time(1, 200000); const Time MFMBitLength = Time(1, 100000); const Time FMBitLength = Time(1, 50000); +constexpr Time bit_length(Density density) { + switch(density) { + case Density::Single: return FMBitLength; + case Density::Double: return MFMBitLength; + case Density::High: return HDMFMBitLength; + } +} + } #endif /* Constants_h */ diff --git a/Storage/Disk/Encodings/MFM/Encoder.cpp b/Storage/Disk/Encodings/MFM/Encoder.cpp index fbd5bbf410..0379fadab5 100644 --- a/Storage/Disk/Encodings/MFM/Encoder.cpp +++ b/Storage/Disk/Encodings/MFM/Encoder.cpp @@ -18,6 +18,62 @@ using namespace Storage::Encodings::MFM; +namespace { + +std::vector sector_pointers(const std::vector §ors) { + std::vector pointers; + for(const Sector §or: sectors) { + pointers.push_back(§or); + } + return pointers; +} + +template struct Defaults; +template <> struct Defaults { + static constexpr size_t expected_track_bytes = 6250; + + static constexpr size_t post_index_address_mark_bytes = 26; + static constexpr uint8_t post_index_address_mark_value = 0xff; + + static constexpr size_t pre_address_mark_bytes = 6; + static constexpr size_t post_address_address_mark_bytes = 11; + static constexpr uint8_t post_address_address_mark_value = 0xff; + + static constexpr size_t pre_data_mark_bytes = 6; + static constexpr size_t post_data_bytes = 27; + static constexpr uint8_t post_data_value = 0xff; +}; +template <> struct Defaults { + static constexpr size_t expected_track_bytes = 12500; + + static constexpr size_t post_index_address_mark_bytes = 50; + static constexpr uint8_t post_index_address_mark_value = 0x4e; + + static constexpr size_t pre_address_mark_bytes = 12; + static constexpr size_t post_address_address_mark_bytes = 22; + static constexpr uint8_t post_address_address_mark_value = 0x4e; + + static constexpr size_t pre_data_mark_bytes = 12; + static constexpr size_t post_data_bytes = 54; + static constexpr uint8_t post_data_value = 0xff; +}; +template <> struct Defaults { + static constexpr size_t expected_track_bytes = 25000; + + static constexpr size_t post_index_address_mark_bytes = 50; + static constexpr uint8_t post_index_address_mark_value = 0x4e; + + static constexpr size_t pre_address_mark_bytes = 12; + static constexpr size_t post_address_address_mark_bytes = 22; + static constexpr uint8_t post_address_address_mark_value = 0x4e; + + static constexpr size_t pre_data_mark_bytes = 12; + static constexpr size_t post_data_bytes = 54; + static constexpr uint8_t post_data_value = 0xff; +}; + +} + enum class SurfaceItem { Mark, Data @@ -124,7 +180,7 @@ class FMEncoder: public Encoder { }; template std::shared_ptr - GetTrackWithSectors( + GTrackWithSectors( const std::vector §ors, std::size_t post_index_address_mark_bytes, uint8_t post_index_address_mark_value, std::size_t pre_address_mark_bytes, @@ -281,58 +337,55 @@ void Encoder::add_crc(bool incorrectly) { add_byte((crc_value & 0xff) ^ (incorrectly ? 1 : 0)); } -const std::size_t Storage::Encodings::MFM::DefaultSectorGapLength = std::numeric_limits::max(); - -static std::vector sector_pointers(const std::vector §ors) { - std::vector pointers; - for(const Sector §or: sectors) { - pointers.push_back(§or); - } - return pointers; -} - -std::shared_ptr Storage::Encodings::MFM::GetFMTrackWithSectors(const std::vector §ors, std::size_t sector_gap_length, uint8_t sector_gap_filler_byte) { - return GetTrackWithSectors( - sector_pointers(sectors), - 26, 0xff, - 6, - 11, sector_gap_filler_byte, - 6, - (sector_gap_length != DefaultSectorGapLength) ? sector_gap_length : 27, 0xff, - 6250); // i.e. 250kbps (including clocks) * 60 = 15000kpm, at 300 rpm => 50 kbits/rotation => 6250 bytes/rotation +namespace { +template +std::shared_ptr TTrackWithSectors( + const std::vector §ors, + std::optional sector_gap_length, + std::optional sector_gap_filler_byte +) { + using EncoderT = std::conditional_t; + return GTrackWithSectors( + sectors, + Defaults::post_index_address_mark_bytes, + Defaults::post_index_address_mark_value, + Defaults::pre_address_mark_bytes, + Defaults::post_address_address_mark_bytes, + sector_gap_filler_byte ? *sector_gap_filler_byte : Defaults::post_address_address_mark_value, + Defaults::pre_data_mark_bytes, + sector_gap_length ? *sector_gap_length : Defaults::post_data_bytes, + Defaults::post_data_value, + Defaults::expected_track_bytes + ); } -std::shared_ptr Storage::Encodings::MFM::GetFMTrackWithSectors(const std::vector §ors, std::size_t sector_gap_length, uint8_t sector_gap_filler_byte) { - return GetTrackWithSectors( - sectors, - 26, 0xff, - 6, - 11, sector_gap_filler_byte, - 6, - (sector_gap_length != DefaultSectorGapLength) ? sector_gap_length : 27, 0xff, - 6250); // i.e. 250kbps (including clocks) * 60 = 15000kpm, at 300 rpm => 50 kbits/rotation => 6250 bytes/rotation } -std::shared_ptr Storage::Encodings::MFM::GetMFMTrackWithSectors(const std::vector §ors, std::size_t sector_gap_length, uint8_t sector_gap_filler_byte) { - return GetTrackWithSectors( +std::shared_ptr Storage::Encodings::MFM::TrackWithSectors( + Density density, + const std::vector §ors, + std::optional sector_gap_length, + std::optional sector_gap_filler_byte +) { + return TrackWithSectors( + density, sector_pointers(sectors), - 50, 0x4e, - 12, - 22, sector_gap_filler_byte, - 12, - (sector_gap_length != DefaultSectorGapLength) ? sector_gap_length : 54, 0xff, - 12500); // unintelligently: double the single-density bytes/rotation (or: 500kbps @ 300 rpm) + sector_gap_length, + sector_gap_filler_byte + ); } -std::shared_ptr Storage::Encodings::MFM::GetMFMTrackWithSectors(const std::vector §ors, std::size_t sector_gap_length, uint8_t sector_gap_filler_byte) { - return GetTrackWithSectors( - sectors, - 50, 0x4e, - 12, - 22, sector_gap_filler_byte, - 12, - (sector_gap_length != DefaultSectorGapLength) ? sector_gap_length : 54, 0xff, - 12500); // unintelligently: double the single-density bytes/rotation (or: 500kbps @ 300 rpm) +std::shared_ptr Storage::Encodings::MFM::TrackWithSectors( + Density density, + const std::vector §ors, + std::optional sector_gap_length, + std::optional sector_gap_filler_byte +) { + switch(density) { + case Density::Single: return TTrackWithSectors(sectors, sector_gap_length, sector_gap_filler_byte); + case Density::Double: return TTrackWithSectors(sectors, sector_gap_length, sector_gap_filler_byte); + case Density::High: return TTrackWithSectors(sectors, sector_gap_length, sector_gap_filler_byte); + } } std::unique_ptr Storage::Encodings::MFM::GetMFMEncoder(std::vector &target, std::vector *fuzzy_target) { diff --git a/Storage/Disk/Encodings/MFM/Encoder.hpp b/Storage/Disk/Encodings/MFM/Encoder.hpp index babec8b356..94ae4617f9 100644 --- a/Storage/Disk/Encodings/MFM/Encoder.hpp +++ b/Storage/Disk/Encodings/MFM/Encoder.hpp @@ -11,34 +11,34 @@ #include #include +#include #include +#include "Constants.hpp" #include "Sector.hpp" #include "../../Track/Track.hpp" #include "../../../../Numeric/CRC.hpp" namespace Storage::Encodings::MFM { -extern const std::size_t DefaultSectorGapLength; /*! - Converts a vector of sectors into a properly-encoded MFM track. + Converts a vector of sectors into a properly-encoded FM or MFM track. @param sectors The sectors to write. @param sector_gap_length If specified, sets the distance in whole bytes between each ID and its data. @param sector_gap_filler_byte If specified, sets the value (unencoded) that is used to populate the gap between each ID and its data. */ -std::shared_ptr GetMFMTrackWithSectors(const std::vector §ors, std::size_t sector_gap_length = DefaultSectorGapLength, uint8_t sector_gap_filler_byte = 0x4e); -std::shared_ptr GetMFMTrackWithSectors(const std::vector §ors, std::size_t sector_gap_length = DefaultSectorGapLength, uint8_t sector_gap_filler_byte = 0x4e); - -/*! - Converts a vector of sectors into a properly-encoded FM track. - - @param sectors The sectors to write. - @param sector_gap_length If specified, sets the distance in whole bytes between each ID and its data. - @param sector_gap_filler_byte If specified, sets the value (unencoded) that is used to populate the gap between each ID and its data. -*/ -std::shared_ptr GetFMTrackWithSectors(const std::vector §ors, std::size_t sector_gap_length = DefaultSectorGapLength, uint8_t sector_gap_filler_byte = 0xff); -std::shared_ptr GetFMTrackWithSectors(const std::vector §ors, std::size_t sector_gap_length = DefaultSectorGapLength, uint8_t sector_gap_filler_byte = 0xff); +std::shared_ptr TrackWithSectors( + Density density, + const std::vector §ors, + std::optional sector_gap_length = std::nullopt, + std::optional sector_gap_filler_byte = std::nullopt); + +std::shared_ptr TrackWithSectors( + Density density, + const std::vector §ors, + std::optional sector_gap_length = std::nullopt, + std::optional sector_gap_filler_byte = std::nullopt); class Encoder { public: diff --git a/Storage/Disk/Encodings/MFM/Parser.cpp b/Storage/Disk/Encodings/MFM/Parser.cpp index 79907f2036..efc8510422 100644 --- a/Storage/Disk/Encodings/MFM/Parser.cpp +++ b/Storage/Disk/Encodings/MFM/Parser.cpp @@ -14,40 +14,58 @@ using namespace Storage::Encodings::MFM; -Parser::Parser(bool is_mfm, const std::shared_ptr &disk) : - disk_(disk), is_mfm_(is_mfm) {} +Parser::Parser(const std::shared_ptr &disk) : + disk_(disk) {} -void Parser::install_sectors_from_track(const Storage::Disk::Track::Address &address) { +Parser::Parser(Density density, const std::shared_ptr &disk) : + disk_(disk), density_(density) {} + +void Parser::install_track(const Storage::Disk::Track::Address &address) { if(sectors_by_address_by_track_.find(address) != sectors_by_address_by_track_.end()) { return; } - std::shared_ptr track = disk_->get_track_at_position(address); + const auto track = disk_->get_track_at_position(address); if(!track) { return; } - std::map sectors = sectors_from_segment( - Storage::Disk::track_serialisation(*track, is_mfm_ ? MFMBitLength : FMBitLength), - is_mfm_); - std::map sectors_by_id; - for(const auto §or : sectors) { - sectors_by_id.insert(std::make_pair(sector.second.address.sector, std::move(sector.second))); + if(density_) { + append(parse_track(*track, *density_), sectors_by_id); + return; + } else { + // Just try all three in succession. + append(parse_track(*track, Density::Single), sectors_by_id); + append(parse_track(*track, Density::Double), sectors_by_id); + append(parse_track(*track, Density::High), sectors_by_id);; + } + + sectors_by_address_by_track_.emplace(address, std::move(sectors_by_id)); +} + +SectorMap Parser::parse_track(const Storage::Disk::Track &track, Density density) { + return sectors_from_segment( + Storage::Disk::track_serialisation(track, bit_length(density)), + density); +} + +void Parser::append(const SectorMap &source, std::map &destination) { + for(const auto §or : source) { + destination.emplace(sector.second.address.sector, std::move(sector.second)); } - sectors_by_address_by_track_.insert(std::make_pair(address, std::move(sectors_by_id))); } -Sector *Parser::get_sector(int head, int track, uint8_t sector) { - Disk::Track::Address address(head, Storage::Disk::HeadPosition(track)); - install_sectors_from_track(address); +const Sector *Parser::sector(int head, int track, uint8_t sector) { + const Disk::Track::Address address(head, Storage::Disk::HeadPosition(track)); + install_track(address); - auto sectors = sectors_by_address_by_track_.find(address); + const auto sectors = sectors_by_address_by_track_.find(address); if(sectors == sectors_by_address_by_track_.end()) { return nullptr; } - auto stored_sector = sectors->second.find(sector); + const auto stored_sector = sectors->second.find(sector); if(stored_sector == sectors->second.end()) { return nullptr; } diff --git a/Storage/Disk/Encodings/MFM/Parser.hpp b/Storage/Disk/Encodings/MFM/Parser.hpp index cdf0dd0345..8bbd912912 100644 --- a/Storage/Disk/Encodings/MFM/Parser.hpp +++ b/Storage/Disk/Encodings/MFM/Parser.hpp @@ -9,10 +9,14 @@ #ifndef Parser_hpp #define Parser_hpp +#include "Constants.hpp" #include "Sector.hpp" +#include "SegmentParser.hpp" #include "../../Track/Track.hpp" #include "../../Drive.hpp" +#include + namespace Storage::Encodings::MFM { /*! @@ -20,7 +24,11 @@ namespace Storage::Encodings::MFM { */ class Parser { public: - Parser(bool is_mfm, const std::shared_ptr &disk); + /// Creates a parser that will only attempt to interpret the underlying disk as being of @c density. + Parser(Density density, const std::shared_ptr &disk); + + /// Creates a parser that will automatically try all available FM and MFM densities to try to extract sectors. + Parser(const std::shared_ptr &disk); /*! Seeks to the physical track at @c head and @c track. Searches on it for a sector @@ -28,14 +36,24 @@ class Parser { @returns a sector if one was found; @c nullptr otherwise. */ - Storage::Encodings::MFM::Sector *get_sector(int head, int track, uint8_t sector); + const Storage::Encodings::MFM::Sector *sector(int head, int track, uint8_t sector); + + // TODO: set_sector. private: std::shared_ptr disk_; - bool is_mfm_ = true; - - void install_sectors_from_track(const Storage::Disk::Track::Address &address); - std::map> sectors_by_address_by_track_; + std::optional density_; + + void install_track(const Storage::Disk::Track::Address &address); + static SectorMap parse_track(const Storage::Disk::Track &track, Density density); + static void append(const SectorMap &source, std::map &destination); + + // Maps from a track address, i.e. head and position, to a map from + // sector IDs to sectors. + std::map< + Storage::Disk::Track::Address, + std::map + > sectors_by_address_by_track_; }; } diff --git a/Storage/Disk/Encodings/MFM/SegmentParser.cpp b/Storage/Disk/Encodings/MFM/SegmentParser.cpp index daf64abed9..86a69f0e23 100644 --- a/Storage/Disk/Encodings/MFM/SegmentParser.cpp +++ b/Storage/Disk/Encodings/MFM/SegmentParser.cpp @@ -11,10 +11,13 @@ using namespace Storage::Encodings::MFM; -std::map Storage::Encodings::MFM::sectors_from_segment(const Storage::Disk::PCMSegment &&segment, bool is_double_density) { +std::map Storage::Encodings::MFM::sectors_from_segment( + const Storage::Disk::PCMSegment &segment, + Density density +) { std::map result; Shifter shifter; - shifter.set_is_double_density(is_double_density); + shifter.set_is_mfm(is_mfm(density)); shifter.set_should_obey_syncs(true); std::unique_ptr new_sector; diff --git a/Storage/Disk/Encodings/MFM/SegmentParser.hpp b/Storage/Disk/Encodings/MFM/SegmentParser.hpp index 9fc1c8d248..587aa45e4f 100644 --- a/Storage/Disk/Encodings/MFM/SegmentParser.hpp +++ b/Storage/Disk/Encodings/MFM/SegmentParser.hpp @@ -9,6 +9,7 @@ #ifndef SegmentParser_hpp #define SegmentParser_hpp +#include "Constants.hpp" #include "Sector.hpp" #include "../../Track/PCMSegment.hpp" #include @@ -22,7 +23,7 @@ using SectorMap = std::map; the segment (counted in bits from the beginning and pointing to the location the disk had reached upon detection of the ID mark) to sector. */ -SectorMap sectors_from_segment(const Disk::PCMSegment &&segment, bool is_double_density); +SectorMap sectors_from_segment(const Disk::PCMSegment &segment, Density density); } diff --git a/Storage/Disk/Encodings/MFM/Shifter.cpp b/Storage/Disk/Encodings/MFM/Shifter.cpp index 6790031aa2..ba468c6064 100644 --- a/Storage/Disk/Encodings/MFM/Shifter.cpp +++ b/Storage/Disk/Encodings/MFM/Shifter.cpp @@ -16,9 +16,9 @@ using namespace Storage::Encodings::MFM; Shifter::Shifter() : owned_crc_generator_(new CRC::CCITT()), crc_generator_(owned_crc_generator_.get()) {} Shifter::Shifter(CRC::CCITT *crc_generator) : crc_generator_(crc_generator) {} -void Shifter::set_is_double_density(bool is_double_density) { - is_double_density_ = is_double_density; - if(!is_double_density) is_awaiting_marker_value_ = false; +void Shifter::set_is_mfm(bool is_mfm) { + is_mfm_ = is_mfm; + if(!is_mfm) is_awaiting_marker_value_ = false; } void Shifter::set_should_obey_syncs(bool should_obey_syncs) { @@ -31,7 +31,7 @@ void Shifter::add_input_bit(int value) { token_ = Token::None; if(should_obey_syncs_) { - if(!is_double_density_) { + if(!is_mfm_) { switch(shift_register_ & 0xffff) { case Storage::Encodings::MFM::FMIndexAddressMark: token_ = Token::Index; @@ -100,7 +100,7 @@ void Shifter::add_input_bit(int value) { token_ = Token::Byte; bits_since_token_ = 0; - if(is_awaiting_marker_value_ && is_double_density_) { + if(is_awaiting_marker_value_ && is_mfm_) { is_awaiting_marker_value_ = false; switch(get_byte()) { case Storage::Encodings::MFM::IndexAddressByte: diff --git a/Storage/Disk/Encodings/MFM/Shifter.hpp b/Storage/Disk/Encodings/MFM/Shifter.hpp index a53689652a..e5db207c1b 100644 --- a/Storage/Disk/Encodings/MFM/Shifter.hpp +++ b/Storage/Disk/Encodings/MFM/Shifter.hpp @@ -20,7 +20,7 @@ namespace Storage::Encodings::MFM { a stream of MFM tokens as output. So e.g. it is suitable for use in parsing the output of a PLL windowing of disk events. - It supports both FM and MFM parsing; see @c set_is_double_density. + It supports both FM and MFM parsing; see @c set_is_mfm. It will ordinarily honour sync patterns; that should be turned off when within a sector because false syncs can occur. See @c set_should_obey_syncs. @@ -48,7 +48,7 @@ class Shifter { Shifter(); Shifter(CRC::CCITT *crc_generator); - void set_is_double_density(bool is_double_density); + void set_is_mfm(bool is_mfm); void set_should_obey_syncs(bool should_obey_syncs); void add_input_bit(int bit); @@ -72,7 +72,7 @@ class Shifter { Token token_ = None; // Input configuration. - bool is_double_density_ = false; + bool is_mfm_ = false; std::unique_ptr owned_crc_generator_; CRC::CCITT *crc_generator_; diff --git a/Storage/Disk/Parsers/CPM.cpp b/Storage/Disk/Parsers/CPM.cpp index 23e5ab3f94..b6a757091b 100644 --- a/Storage/Disk/Parsers/CPM.cpp +++ b/Storage/Disk/Parsers/CPM.cpp @@ -16,7 +16,7 @@ using namespace Storage::Disk::CPM; std::unique_ptr Storage::Disk::CPM::GetCatalogue(const std::shared_ptr &disk, const ParameterBlock ¶meters) { - Storage::Encodings::MFM::Parser parser(true, disk); + Storage::Encodings::MFM::Parser parser(Encodings::MFM::Density::Double, disk); // Assemble the actual bytes of the catalogue. std::vector catalogue; @@ -29,7 +29,7 @@ std::unique_ptr Storage::Disk::CPM::GetCatalogue( if(catalogue_allocation_bitmap & 0x8000) { std::size_t size_read = 0; do { - Storage::Encodings::MFM::Sector *sector_contents = parser.get_sector(0, uint8_t(track), uint8_t(parameters.first_sector + sector)); + const Storage::Encodings::MFM::Sector *sector_contents = parser.sector(0, uint8_t(track), uint8_t(parameters.first_sector + sector)); if(!sector_contents || sector_contents->samples.empty()) { return nullptr; } @@ -138,7 +138,7 @@ std::unique_ptr Storage::Disk::CPM::GetCatalogue( track = first_sector / parameters.sectors_per_track; for(int s = 0; s < sectors_per_block && record < number_of_records; s++) { - Storage::Encodings::MFM::Sector *sector_contents = parser.get_sector(0, uint8_t(track), uint8_t(parameters.first_sector + sector)); + const Storage::Encodings::MFM::Sector *sector_contents = parser.sector(0, uint8_t(track), uint8_t(parameters.first_sector + sector)); if(!sector_contents || sector_contents->samples.empty()) break; sector++; if(sector == parameters.sectors_per_track) { diff --git a/Storage/Disk/Parsers/FAT.cpp b/Storage/Disk/Parsers/FAT.cpp index 528c732485..d534a51395 100644 --- a/Storage/Disk/Parsers/FAT.cpp +++ b/Storage/Disk/Parsers/FAT.cpp @@ -77,10 +77,10 @@ FAT::Directory directory_from(const std::vector &contents) { } std::optional FAT::GetVolume(const std::shared_ptr &disk) { - Storage::Encodings::MFM::Parser parser(true, disk); + Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk); // Grab the boot sector; that'll be enough to establish the volume. - Storage::Encodings::MFM::Sector *const boot_sector = parser.get_sector(0, 0, 1); + const Storage::Encodings::MFM::Sector *const boot_sector = parser.sector(0, 0, 1); if(!boot_sector || boot_sector->samples.empty() || boot_sector->samples[0].size() < 512) { return std::nullopt; } @@ -108,8 +108,8 @@ std::optional FAT::GetVolume(const std::shared_ptrsamples.empty() || fat_sector->samples[0].size() != volume.bytes_per_sector) { return std::nullopt; } @@ -130,8 +130,8 @@ std::optional FAT::GetVolume(const std::shared_ptrsamples.empty() || sector->samples[0].size() != volume.bytes_per_sector) { return std::nullopt; } @@ -143,7 +143,7 @@ std::optional FAT::GetVolume(const std::shared_ptr> FAT::GetFile(const std::shared_ptr &disk, const Volume &volume, const File &file) { - Storage::Encodings::MFM::Parser parser(true, disk); + Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk); std::vector contents; @@ -156,8 +156,8 @@ std::optional> FAT::GetFile(const std::shared_ptrsamples.empty() || sector_contents->samples[0].size() != volume.bytes_per_sector) { return std::nullopt; }