From 44cdc124afcfa2c58534da53b02a127bd12b36f0 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 7 Oct 2017 19:37:36 -0400 Subject: [PATCH] Switches to providing a full record of changes to disk images, rather than feeding them a track at a time. Gets explicit about `override`s while doing so, to ensure full adaptation. --- Storage/Disk/DiskImage/DiskImage.hpp | 4 +- .../DiskImage/DiskImageImplementation.hpp | 5 +- Storage/Disk/DiskImage/Formats/AcornADF.hpp | 6 +- Storage/Disk/DiskImage/Formats/CPCDSK.hpp | 6 +- Storage/Disk/DiskImage/Formats/D64.hpp | 4 +- Storage/Disk/DiskImage/Formats/G64.hpp | 4 +- Storage/Disk/DiskImage/Formats/HFE.cpp | 34 +++++---- Storage/Disk/DiskImage/Formats/HFE.hpp | 8 +- .../Disk/DiskImage/Formats/MFMSectorDump.cpp | 21 +++-- .../Disk/DiskImage/Formats/MFMSectorDump.hpp | 4 +- Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp | 76 ++++++++++--------- Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp | 8 +- Storage/Disk/DiskImage/Formats/SSD.hpp | 6 +- 13 files changed, 96 insertions(+), 90 deletions(-) diff --git a/Storage/Disk/DiskImage/DiskImage.hpp b/Storage/Disk/DiskImage/DiskImage.hpp index 011b5e5ac..7237c8b53 100644 --- a/Storage/Disk/DiskImage/DiskImage.hpp +++ b/Storage/Disk/DiskImage/DiskImage.hpp @@ -49,9 +49,9 @@ class DiskImage { virtual std::shared_ptr get_track_at_position(Track::Address address) = 0; /*! - Replaces the Track at position @c position underneath @c head with @c track. Ignored if this disk is read-only. + Replaces the Tracks indicated by the map, that maps from physical address to track content. */ - virtual void set_track_at_position(Track::Address address, const std::shared_ptr &track) {} + virtual void set_tracks(const std::map> &tracks) {} /*! Communicates that it is likely to be a while before any more tracks are written. diff --git a/Storage/Disk/DiskImage/DiskImageImplementation.hpp b/Storage/Disk/DiskImage/DiskImageImplementation.hpp index 9ef1da3d3..3fb13bb38 100644 --- a/Storage/Disk/DiskImage/DiskImageImplementation.hpp +++ b/Storage/Disk/DiskImage/DiskImageImplementation.hpp @@ -30,10 +30,7 @@ template void DiskImageHolder::flush_tracks() { unwritten_tracks_.clear(); update_queue_->enqueue([this, track_copies]() { - // TODO: communicate these as a batch, not one by one. - for(auto &pair : *track_copies) { - disk_image_.set_track_at_position(pair.first, pair.second); - } + disk_image_.set_tracks(*track_copies); }); } } diff --git a/Storage/Disk/DiskImage/Formats/AcornADF.hpp b/Storage/Disk/DiskImage/Formats/AcornADF.hpp index ee4949657..186cf7be4 100644 --- a/Storage/Disk/DiskImage/Formats/AcornADF.hpp +++ b/Storage/Disk/DiskImage/Formats/AcornADF.hpp @@ -31,11 +31,11 @@ class AcornADF: public MFMSectorDump { ErrorNotAcornADF, }; - int get_head_position_count(); - int get_head_count(); + int get_head_position_count() override; + int get_head_count() override; private: - long get_file_offset_for_position(Track::Address address); + long get_file_offset_for_position(Track::Address address) override; }; } diff --git a/Storage/Disk/DiskImage/Formats/CPCDSK.hpp b/Storage/Disk/DiskImage/Formats/CPCDSK.hpp index be90f9c09..f7c5b6a12 100644 --- a/Storage/Disk/DiskImage/Formats/CPCDSK.hpp +++ b/Storage/Disk/DiskImage/Formats/CPCDSK.hpp @@ -35,10 +35,10 @@ class CPCDSK: public DiskImage, public Storage::FileHolder { }; // implemented to satisfy @c Disk - int get_head_position_count(); - int get_head_count(); + int get_head_position_count() override; + int get_head_count() override; using DiskImage::get_is_read_only; - std::shared_ptr get_track_at_position(Track::Address address); + std::shared_ptr get_track_at_position(Track::Address address) override; private: int head_count_; diff --git a/Storage/Disk/DiskImage/Formats/D64.hpp b/Storage/Disk/DiskImage/Formats/D64.hpp index da4532cab..9c83669c5 100644 --- a/Storage/Disk/DiskImage/Formats/D64.hpp +++ b/Storage/Disk/DiskImage/Formats/D64.hpp @@ -33,9 +33,9 @@ class D64: public DiskImage, public Storage::FileHolder { }; // implemented to satisfy @c Disk - int get_head_position_count(); + int get_head_position_count() override; using DiskImage::get_is_read_only; - std::shared_ptr get_track_at_position(Track::Address address); + std::shared_ptr get_track_at_position(Track::Address address) override; private: int number_of_tracks_; diff --git a/Storage/Disk/DiskImage/Formats/G64.hpp b/Storage/Disk/DiskImage/Formats/G64.hpp index 92b06fed4..92b57d3be 100644 --- a/Storage/Disk/DiskImage/Formats/G64.hpp +++ b/Storage/Disk/DiskImage/Formats/G64.hpp @@ -36,8 +36,8 @@ class G64: public DiskImage, public Storage::FileHolder { }; // implemented to satisfy @c Disk - int get_head_position_count(); - std::shared_ptr get_track_at_position(Track::Address address); + int get_head_position_count() override; + std::shared_ptr get_track_at_position(Track::Address address) override; using DiskImage::get_is_read_only; private: diff --git a/Storage/Disk/DiskImage/Formats/HFE.cpp b/Storage/Disk/DiskImage/Formats/HFE.cpp index 86e9692a0..a0068b38a 100644 --- a/Storage/Disk/DiskImage/Formats/HFE.cpp +++ b/Storage/Disk/DiskImage/Formats/HFE.cpp @@ -84,24 +84,26 @@ std::shared_ptr HFE::get_track_at_position(Track::Address address) { return track; } -void HFE::set_track_at_position(Track::Address address, const std::shared_ptr &track) { - std::unique_lock lock_guard(file_access_mutex_); - uint16_t track_length = seek_track(address); - lock_guard.unlock(); +void HFE::set_tracks(const std::map> &tracks) { + for(auto &track : tracks) { + std::unique_lock lock_guard(file_access_mutex_); + uint16_t track_length = seek_track(track.first); + lock_guard.unlock(); - PCMSegment segment = Storage::Disk::track_serialisation(*track, Storage::Time(1, track_length * 8)); - Storage::Data::BitReverse::reverse(segment.data); - uint16_t data_length = std::min(static_cast(segment.data.size()), track_length); + PCMSegment segment = Storage::Disk::track_serialisation(*track.second, Storage::Time(1, track_length * 8)); + Storage::Data::BitReverse::reverse(segment.data); + uint16_t data_length = std::min(static_cast(segment.data.size()), track_length); - lock_guard.lock(); - seek_track(address); + lock_guard.lock(); + seek_track(track.first); - uint16_t c = 0; - while(c < data_length) { - uint16_t length = (uint16_t)std::min(256, data_length - c); - fwrite(&segment.data[c], 1, length, file_); - c += length; - fseek(file_, 256, SEEK_CUR); + uint16_t c = 0; + while(c < data_length) { + uint16_t length = (uint16_t)std::min(256, data_length - c); + fwrite(&segment.data[c], 1, length, file_); + c += length; + fseek(file_, 256, SEEK_CUR); + } + lock_guard.unlock(); } - lock_guard.unlock(); } diff --git a/Storage/Disk/DiskImage/Formats/HFE.hpp b/Storage/Disk/DiskImage/Formats/HFE.hpp index 3020a67b9..1720666b7 100644 --- a/Storage/Disk/DiskImage/Formats/HFE.hpp +++ b/Storage/Disk/DiskImage/Formats/HFE.hpp @@ -34,11 +34,11 @@ class HFE: public DiskImage, public Storage::FileHolder { }; // implemented to satisfy @c Disk - int get_head_position_count(); - int get_head_count(); + int get_head_position_count() override; + int get_head_count() override; using Storage::FileHolder::get_is_read_only; - void set_track_at_position(Track::Address address, const std::shared_ptr &track); - std::shared_ptr get_track_at_position(Track::Address address); + void set_tracks(const std::map> &tracks) override; + std::shared_ptr get_track_at_position(Track::Address address) override; private: uint16_t seek_track(Track::Address address); diff --git a/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp b/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp index bb2e0b460..8f558bf4f 100644 --- a/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp +++ b/Storage/Disk/DiskImage/Formats/MFMSectorDump.cpp @@ -35,16 +35,21 @@ std::shared_ptr MFMSectorDump::get_track_at_position(Track::Address addre return track_for_sectors(sectors, static_cast(address.position), static_cast(address.head), 0, sector_size_, is_double_density_); } -void MFMSectorDump::set_track_at_position(Track::Address address, const std::shared_ptr &track) { +void MFMSectorDump::set_tracks(const std::map> &tracks) { uint8_t parsed_track[(128 << sector_size_)*sectors_per_track_]; - // Assumption here: sector IDs will run from 0. - decode_sectors(*track, parsed_track, 0, static_cast(sectors_per_track_-1), sector_size_, is_double_density_); - long file_offset = get_file_offset_for_position(address); + // TODO: it would be more efficient from a file access and locking point of view to parse the sectors + // in one loop, then write in another. - std::lock_guard lock_guard(file_access_mutex_); - ensure_file_is_at_least_length(file_offset); - fseek(file_, file_offset, SEEK_SET); - fwrite(parsed_track, 1, sizeof(parsed_track), file_); + for(auto &track : tracks) { + // Assumption here: sector IDs will run from 0. + decode_sectors(*track.second, parsed_track, 0, static_cast(sectors_per_track_-1), sector_size_, is_double_density_); + long file_offset = get_file_offset_for_position(track.first); + + std::lock_guard lock_guard(file_access_mutex_); + ensure_file_is_at_least_length(file_offset); + fseek(file_, file_offset, SEEK_SET); + fwrite(parsed_track, 1, sizeof(parsed_track), file_); + } fflush(file_); } diff --git a/Storage/Disk/DiskImage/Formats/MFMSectorDump.hpp b/Storage/Disk/DiskImage/Formats/MFMSectorDump.hpp index 6d0d9afd0..489072cdb 100644 --- a/Storage/Disk/DiskImage/Formats/MFMSectorDump.hpp +++ b/Storage/Disk/DiskImage/Formats/MFMSectorDump.hpp @@ -24,8 +24,8 @@ class MFMSectorDump: public DiskImage, public Storage::FileHolder { void set_geometry(int sectors_per_track, uint8_t sector_size, bool is_double_density); using Storage::FileHolder::get_is_read_only; - void set_track_at_position(Track::Address address, const std::shared_ptr &track); - std::shared_ptr get_track_at_position(Track::Address address); + void set_tracks(const std::map> &tracks) override; + std::shared_ptr get_track_at_position(Track::Address address) override; private: std::mutex file_access_mutex_; diff --git a/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp b/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp index 83b1b9a67..5a5c7b94e 100644 --- a/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp +++ b/Storage/Disk/DiskImage/Formats/OricMFMDSK.cpp @@ -114,49 +114,51 @@ std::shared_ptr OricMFMDSK::get_track_at_position(Track::Address address) return track; } -void OricMFMDSK::set_track_at_position(Track::Address address, const std::shared_ptr &track) { - PCMSegment segment = Storage::Disk::track_serialisation(*track, Storage::Encodings::MFM::MFMBitLength); - Storage::Encodings::MFM::Shifter shifter; - shifter.set_is_double_density(true); - shifter.set_should_obey_syncs(true); - std::vector parsed_track; - int size = 0; - int offset = 0; - bool capture_size = false; +void OricMFMDSK::set_tracks(const std::map> &tracks) { + for(auto &track : tracks) { + PCMSegment segment = Storage::Disk::track_serialisation(*track.second, Storage::Encodings::MFM::MFMBitLength); + Storage::Encodings::MFM::Shifter shifter; + shifter.set_is_double_density(true); + shifter.set_should_obey_syncs(true); + std::vector parsed_track; + int size = 0; + int offset = 0; + bool capture_size = false; - for(unsigned int bit = 0; bit < segment.number_of_bits; ++bit) { - shifter.add_input_bit(segment.bit(bit)); - if(shifter.get_token() == Storage::Encodings::MFM::Shifter::Token::None) continue; - parsed_track.push_back(shifter.get_byte()); + for(unsigned int bit = 0; bit < segment.number_of_bits; ++bit) { + shifter.add_input_bit(segment.bit(bit)); + if(shifter.get_token() == Storage::Encodings::MFM::Shifter::Token::None) continue; + parsed_track.push_back(shifter.get_byte()); - if(offset) { - offset--; - if(!offset) { - shifter.set_should_obey_syncs(true); + if(offset) { + offset--; + if(!offset) { + shifter.set_should_obey_syncs(true); + } + if(capture_size && offset == 2) { + size = parsed_track.back(); + capture_size = false; + } } - if(capture_size && offset == 2) { - size = parsed_track.back(); - capture_size = false; + + if( shifter.get_token() == Storage::Encodings::MFM::Shifter::Token::Data || + shifter.get_token() == Storage::Encodings::MFM::Shifter::Token::DeletedData) { + offset = 128 << size; + shifter.set_should_obey_syncs(false); + } + + if(shifter.get_token() == Storage::Encodings::MFM::Shifter::Token::ID) { + offset = 6; + shifter.set_should_obey_syncs(false); + capture_size = true; } } - if( shifter.get_token() == Storage::Encodings::MFM::Shifter::Token::Data || - shifter.get_token() == Storage::Encodings::MFM::Shifter::Token::DeletedData) { - offset = 128 << size; - shifter.set_should_obey_syncs(false); - } + long file_offset = get_file_offset_for_position(track.first); - if(shifter.get_token() == Storage::Encodings::MFM::Shifter::Token::ID) { - offset = 6; - shifter.set_should_obey_syncs(false); - capture_size = true; - } + std::lock_guard lock_guard(file_access_mutex_); + fseek(file_, file_offset, SEEK_SET); + size_t track_size = std::min((size_t)6400, parsed_track.size()); + fwrite(parsed_track.data(), 1, track_size, file_); } - - long file_offset = get_file_offset_for_position(address); - - std::lock_guard lock_guard(file_access_mutex_); - fseek(file_, file_offset, SEEK_SET); - size_t track_size = std::min((size_t)6400, parsed_track.size()); - fwrite(parsed_track.data(), 1, track_size, file_); } diff --git a/Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp b/Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp index cefc7c970..25ae3cb41 100644 --- a/Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp +++ b/Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp @@ -32,11 +32,11 @@ class OricMFMDSK: public DiskImage, public Storage::FileHolder { }; // implemented to satisfy @c Disk - int get_head_position_count(); - int get_head_count(); + int get_head_position_count() override; + int get_head_count() override; using Storage::FileHolder::get_is_read_only; - void set_track_at_position(Track::Address address, const std::shared_ptr &track); - std::shared_ptr get_track_at_position(Track::Address address); + void set_tracks(const std::map> &tracks) override; + std::shared_ptr get_track_at_position(Track::Address address) override; private: std::mutex file_access_mutex_; diff --git a/Storage/Disk/DiskImage/Formats/SSD.hpp b/Storage/Disk/DiskImage/Formats/SSD.hpp index 23b90ce51..fa11d8c47 100644 --- a/Storage/Disk/DiskImage/Formats/SSD.hpp +++ b/Storage/Disk/DiskImage/Formats/SSD.hpp @@ -31,11 +31,11 @@ class SSD: public MFMSectorDump { ErrorNotSSD, }; - int get_head_position_count(); - int get_head_count(); + int get_head_position_count() override; + int get_head_count() override; private: - long get_file_offset_for_position(Track::Address address); + long get_file_offset_for_position(Track::Address address) override; int head_count_; int track_count_;