mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-21 20:29:06 +00:00
Merge pull request #1431 from TomHarte/UniqueSectors
Eliminate use of std::shared_ptr for tracks on both sides of DiskImageHolder.
This commit is contained in:
commit
5a3e4dd47b
@ -67,7 +67,7 @@ Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(
|
||||
|
||||
// Grab track 0, sector 0: the boot sector.
|
||||
const auto track_zero =
|
||||
disk->get_track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0)));
|
||||
disk->track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0)));
|
||||
const auto sector_map = Storage::Encodings::AppleGCR::sectors_from_segment(
|
||||
Storage::Disk::track_serialisation(*track_zero, Storage::Time(1, 50000)));
|
||||
|
||||
|
@ -44,7 +44,7 @@ Analyser::Static::TargetList Analyser::Static::FAT12::GetTargets(
|
||||
|
||||
// Attempt to grab MFM track 0, sector 1: the boot sector.
|
||||
const auto track_zero =
|
||||
disk->get_track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0)));
|
||||
disk->track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0)));
|
||||
const auto sector_map = Storage::Encodings::MFM::sectors_from_segment(
|
||||
Storage::Disk::track_serialisation(
|
||||
*track_zero,
|
||||
|
@ -43,12 +43,12 @@ public:
|
||||
@returns the @c Track at @c position underneath @c head if there are any detectable events there;
|
||||
returns @c nullptr otherwise.
|
||||
*/
|
||||
virtual std::shared_ptr<Track> get_track_at_position(Track::Address address) = 0;
|
||||
virtual Track *track_at_position(Track::Address) = 0;
|
||||
|
||||
/*!
|
||||
Replaces the Track at position @c position underneath @c head with @c track. Ignored if this disk is read-only.
|
||||
*/
|
||||
virtual void set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) = 0;
|
||||
virtual void set_track_at_position(Track::Address, const std::shared_ptr<Track> &) = 0;
|
||||
|
||||
/*!
|
||||
Provides a hint that no further tracks are likely to be written for a while.
|
||||
|
@ -50,12 +50,12 @@ public:
|
||||
@returns the @c Track at @c position underneath @c head if there are any detectable events there;
|
||||
returns @c nullptr otherwise.
|
||||
*/
|
||||
virtual std::shared_ptr<Track> get_track_at_position(Track::Address address) = 0;
|
||||
virtual std::unique_ptr<Track> track_at_position(Track::Address address) = 0;
|
||||
|
||||
/*!
|
||||
Replaces the Tracks indicated by the map, that maps from physical address to track content.
|
||||
*/
|
||||
virtual void set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &) {}
|
||||
virtual void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &) {}
|
||||
|
||||
/*!
|
||||
Communicates that it is likely to be a while before any more tracks are written.
|
||||
@ -72,6 +72,12 @@ public:
|
||||
This can avoid some degree of work when disk images offer sub-head-position precision.
|
||||
*/
|
||||
virtual bool tracks_differ(Track::Address lhs, Track::Address rhs) { return lhs != rhs; }
|
||||
|
||||
/*!
|
||||
Maps from an address to its canonical form; this provides a means for images that duplicate the same
|
||||
track at different addresses to declare as much.
|
||||
*/
|
||||
virtual Track::Address canonical_address(Track::Address address) { return address; }
|
||||
};
|
||||
|
||||
class DiskImageHolderBase: public Disk {
|
||||
@ -97,7 +103,7 @@ public:
|
||||
|
||||
HeadPosition get_maximum_head_position();
|
||||
int get_head_count();
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address address);
|
||||
Track *track_at_position(Track::Address address);
|
||||
void set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track);
|
||||
void flush_tracks();
|
||||
bool get_is_read_only();
|
||||
|
@ -22,10 +22,10 @@ template <typename T> void DiskImageHolder<T>::flush_tracks() {
|
||||
if(!unwritten_tracks_.empty()) {
|
||||
if(!update_queue_) update_queue_ = std::make_unique<Concurrency::AsyncTaskQueue<true>>();
|
||||
|
||||
using TrackMap = std::map<Track::Address, std::shared_ptr<Track>>;
|
||||
std::shared_ptr<TrackMap> track_copies(new TrackMap);
|
||||
using TrackMap = std::map<Track::Address, std::unique_ptr<Track>>;
|
||||
auto track_copies = std::make_shared<TrackMap>();
|
||||
for(const auto &address : unwritten_tracks_) {
|
||||
track_copies->insert({address, std::shared_ptr<Track>(cached_tracks_[address]->clone())});
|
||||
track_copies->insert({address, std::unique_ptr<Track>(cached_tracks_[address]->clone())});
|
||||
}
|
||||
unwritten_tracks_.clear();
|
||||
|
||||
@ -42,17 +42,18 @@ template <typename T> void DiskImageHolder<T>::set_track_at_position(Track::Addr
|
||||
cached_tracks_[address] = track;
|
||||
}
|
||||
|
||||
template <typename T> std::shared_ptr<Track> DiskImageHolder<T>::get_track_at_position(Track::Address address) {
|
||||
template <typename T> Track *DiskImageHolder<T>::track_at_position(Track::Address address) {
|
||||
if(address.head >= get_head_count()) return nullptr;
|
||||
if(address.position >= get_maximum_head_position()) return nullptr;
|
||||
|
||||
auto cached_track = cached_tracks_.find(address);
|
||||
if(cached_track != cached_tracks_.end()) return cached_track->second;
|
||||
const auto canonical_address = disk_image_.canonical_address(address);
|
||||
auto cached_track = cached_tracks_.find(canonical_address);
|
||||
if(cached_track != cached_tracks_.end()) return cached_track->second.get();
|
||||
|
||||
std::shared_ptr<Track> track = disk_image_.get_track_at_position(address);
|
||||
std::shared_ptr<Track> track = disk_image_.track_at_position(canonical_address);
|
||||
if(!track) return nullptr;
|
||||
cached_tracks_[address] = track;
|
||||
return track;
|
||||
cached_tracks_[canonical_address] = track;
|
||||
return track.get();
|
||||
}
|
||||
|
||||
template <typename T> DiskImageHolder<T>::~DiskImageHolder() {
|
||||
|
@ -124,7 +124,7 @@ int AmigaADF::get_head_count() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> AmigaADF::get_track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> AmigaADF::track_at_position(Track::Address address) {
|
||||
using namespace Storage::Encodings;
|
||||
|
||||
// Create an MFM encoder.
|
||||
@ -179,7 +179,7 @@ std::shared_ptr<Track> AmigaADF::get_track_at_position(Track::Address address) {
|
||||
encoder->add_byte(0xff);
|
||||
}
|
||||
|
||||
return std::make_shared<Storage::Disk::PCMTrack>(std::move(encoded_segment));
|
||||
return std::make_unique<Storage::Disk::PCMTrack>(std::move(encoded_segment));
|
||||
}
|
||||
|
||||
long AmigaADF::get_file_offset_for_position(Track::Address address) {
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
// implemented to satisfy @c Disk
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
|
@ -61,7 +61,7 @@ size_t AppleDSK::logical_sector_for_physical_sector(size_t physical) {
|
||||
return (physical * (is_prodos_ ? 8 : 7)) % 15;
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> AppleDSK::get_track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> AppleDSK::track_at_position(Track::Address address) {
|
||||
std::vector<uint8_t> track_data;
|
||||
{
|
||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||
@ -93,10 +93,10 @@ std::shared_ptr<Track> AppleDSK::get_track_at_position(Track::Address address) {
|
||||
const size_t offset_in_fifths = size_t(address.position.as_int() % 5);
|
||||
segment.rotate_right(offset_in_fifths * segment.data.size() / 5);
|
||||
|
||||
return std::make_shared<PCMTrack>(segment);
|
||||
return std::make_unique<PCMTrack>(segment);
|
||||
}
|
||||
|
||||
void AppleDSK::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
||||
void AppleDSK::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) {
|
||||
std::map<Track::Address, std::vector<uint8_t>> tracks_by_address;
|
||||
for(const auto &pair: tracks) {
|
||||
// Decode the track.
|
||||
|
@ -31,8 +31,8 @@ public:
|
||||
|
||||
// Implemented to satisfy @c DiskImage.
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &) final;
|
||||
bool get_is_read_only() final;
|
||||
|
||||
private:
|
||||
|
@ -198,7 +198,7 @@ std::size_t CPCDSK::index_for_track(::Storage::Disk::Track::Address address) {
|
||||
return size_t((address.position.as_int() * head_count_) + address.head);
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> CPCDSK::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||
std::unique_ptr<Track> CPCDSK::track_at_position(::Storage::Disk::Track::Address address) {
|
||||
// Given that thesea are interleaved images, determine which track, chronologically, is being requested.
|
||||
const std::size_t chronological_track = index_for_track(address);
|
||||
|
||||
@ -221,7 +221,7 @@ std::shared_ptr<Track> CPCDSK::get_track_at_position(::Storage::Disk::Track::Add
|
||||
track->filler_byte);
|
||||
}
|
||||
|
||||
void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::shared_ptr<::Storage::Disk::Track>> &tracks) {
|
||||
void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::unique_ptr<::Storage::Disk::Track>> &tracks) {
|
||||
// Patch changed tracks into the disk image.
|
||||
for(auto &pair: tracks) {
|
||||
// Assume MFM for now; with extensions DSK can contain FM tracks.
|
||||
|
@ -34,8 +34,8 @@ public:
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
bool get_is_read_only() final;
|
||||
void set_tracks(const std::map<::Storage::Disk::Track::Address, std::shared_ptr<::Storage::Disk::Track>> &tracks) final;
|
||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &) final;
|
||||
std::unique_ptr<::Storage::Disk::Track> track_at_position(::Storage::Disk::Track::Address) final;
|
||||
|
||||
private:
|
||||
struct Track {
|
||||
|
@ -38,7 +38,7 @@ HeadPosition D64::get_maximum_head_position() {
|
||||
return HeadPosition(number_of_tracks_);
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> D64::get_track_at_position(const Track::Address address) {
|
||||
std::unique_ptr<Track> D64::track_at_position(const Track::Address address) {
|
||||
// Figure out where this track starts on the disk.
|
||||
int offset_to_track = 0;
|
||||
int tracks_to_traverse = address.position.as_int();
|
||||
@ -135,5 +135,5 @@ std::shared_ptr<Track> D64::get_track_at_position(const Track::Address address)
|
||||
Encodings::CommodoreGCR::encode_block(§or_data[target_data_offset], end_of_data);
|
||||
}
|
||||
|
||||
return std::make_shared<PCMTrack>(PCMSegment(data));
|
||||
return std::make_unique<PCMTrack>(PCMSegment(data));
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
D64(const std::string &file_name);
|
||||
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
|
@ -79,7 +79,7 @@ long DMK::get_file_offset_for_position(Track::Address address) {
|
||||
return (address.head*head_count_ + address.position.as_int()) * track_length_ + 16;
|
||||
}
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> DMK::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||
std::unique_ptr<::Storage::Disk::Track> DMK::track_at_position(::Storage::Disk::Track::Address address) {
|
||||
file_.seek(get_file_offset_for_position(address), SEEK_SET);
|
||||
|
||||
// Read the IDAM table.
|
||||
@ -179,5 +179,5 @@ std::shared_ptr<::Storage::Disk::Track> DMK::get_track_at_position(::Storage::Di
|
||||
idam_pointer++;
|
||||
}
|
||||
|
||||
return std::make_shared<PCMTrack>(segments);
|
||||
return std::make_unique<PCMTrack>(segments);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
int get_head_count() final;
|
||||
bool get_is_read_only() final;
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
|
@ -36,9 +36,7 @@ HeadPosition G64::get_maximum_head_position() {
|
||||
return HeadPosition(number_of_tracks_ > 84 ? number_of_tracks_ : 84, 2);
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> G64::get_track_at_position(Track::Address address) {
|
||||
std::shared_ptr<Track> resulting_track;
|
||||
|
||||
std::unique_ptr<Track> G64::track_at_position(Track::Address address) {
|
||||
// seek to this track's entry in the track table
|
||||
file_.seek(long((address.position.as_half() * 4) + 0xc), SEEK_SET);
|
||||
|
||||
@ -93,7 +91,7 @@ std::shared_ptr<Track> G64::get_track_at_position(Track::Address address) {
|
||||
}
|
||||
}
|
||||
|
||||
resulting_track = std::make_shared<PCMTrack>(std::move(segments));
|
||||
return std::make_unique<PCMTrack>(std::move(segments));
|
||||
} else {
|
||||
PCMSegment segment(
|
||||
Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(unsigned(speed_zone_offset)),
|
||||
@ -101,11 +99,9 @@ std::shared_ptr<Track> G64::get_track_at_position(Track::Address address) {
|
||||
track_contents
|
||||
);
|
||||
|
||||
resulting_track = std::make_shared<PCMTrack>(std::move(segment));
|
||||
return std::make_unique<PCMTrack>(std::move(segment));
|
||||
}
|
||||
|
||||
// TODO: find out whether it's possible for a G64 to supply only a partial track. I don't think it is, which would make the
|
||||
// above correct but supposing I'm wrong, the above would produce some incorrectly clocked tracks
|
||||
|
||||
return resulting_track;
|
||||
// TODO: find out whether it's possible for a G64 to supply only a partial track. I don't think it is, which
|
||||
// would make the above correct but supposing I'm wrong, the above would produce some incorrectly clocked tracks.
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
|
||||
// implemented to satisfy @c Disk
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
using DiskImage::get_is_read_only;
|
||||
|
||||
private:
|
||||
|
@ -54,7 +54,7 @@ uint16_t HFE::seek_track(Track::Address address) {
|
||||
return track_length / 2; // Divide by two to give the track length for a single side.
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> HFE::get_track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> HFE::track_at_position(Track::Address address) {
|
||||
PCMSegment segment;
|
||||
{
|
||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||
@ -96,10 +96,10 @@ std::shared_ptr<Track> HFE::get_track_at_position(Track::Address address) {
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_shared<PCMTrack>(segment);
|
||||
return std::make_unique<PCMTrack>(segment);
|
||||
}
|
||||
|
||||
void HFE::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
||||
void HFE::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) {
|
||||
for(auto &track : tracks) {
|
||||
std::unique_lock lock_guard(file_.get_file_access_mutex());
|
||||
uint16_t track_length = seek_track(track.first);
|
||||
|
@ -33,8 +33,8 @@ public:
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
bool get_is_read_only() final;
|
||||
void set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) final;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
|
@ -98,7 +98,7 @@ int IMD::get_head_count() {
|
||||
return heads_ + 1;
|
||||
}
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> IMD::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||
std::unique_ptr<Track> IMD::track_at_position(Track::Address address) {
|
||||
auto location = track_locations_.find(address);
|
||||
if(location == track_locations_.end()) {
|
||||
return nullptr;
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
// DiskImage interface.
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
|
@ -186,7 +186,7 @@ int IPF::get_head_count() {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> IPF::get_track_at_position([[maybe_unused]] Track::Address address) {
|
||||
std::unique_ptr<Track> IPF::track_at_position([[maybe_unused]] Track::Address address) {
|
||||
// Get the track description, if it exists, and check either that the file has contents for the track.
|
||||
auto pair = tracks_.find(address);
|
||||
if(pair == tracks_.end()) {
|
||||
@ -313,7 +313,7 @@ std::shared_ptr<Track> IPF::get_track_at_position([[maybe_unused]] Track::Addres
|
||||
++block_count;
|
||||
}
|
||||
|
||||
return std::make_shared<Storage::Disk::PCMTrack>(segments);
|
||||
return std::make_unique<Storage::Disk::PCMTrack>(segments);
|
||||
}
|
||||
|
||||
/// @returns The correct bit length for @c block on a track of @c density.
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
// implemented to satisfy @c Disk
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
|
@ -21,7 +21,7 @@ void MFMSectorDump::set_geometry(int sectors_per_track, uint8_t sector_size, uin
|
||||
first_sector_ = first_sector;
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> MFMSectorDump::get_track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> MFMSectorDump::track_at_position(Track::Address address) {
|
||||
if(address.head >= get_head_count()) return nullptr;
|
||||
if(address.position.as_largest() >= get_maximum_head_position().as_largest()) return nullptr;
|
||||
|
||||
@ -44,7 +44,7 @@ std::shared_ptr<Track> MFMSectorDump::get_track_at_position(Track::Address addre
|
||||
density_);
|
||||
}
|
||||
|
||||
void MFMSectorDump::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
||||
void MFMSectorDump::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) {
|
||||
uint8_t parsed_track[(128 << sector_size_)*sectors_per_track_];
|
||||
|
||||
// TODO: it would be more efficient from a file access and locking point of view to parse the sectors
|
||||
|
@ -24,8 +24,8 @@ public:
|
||||
MFMSectorDump(const std::string &file_name);
|
||||
|
||||
bool get_is_read_only() final;
|
||||
void set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) final;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
|
||||
protected:
|
||||
Storage::FileHolder file_;
|
||||
|
@ -75,7 +75,7 @@ MSA::MSA(const std::string &file_name) :
|
||||
throw Error::InvalidFormat;
|
||||
}
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> MSA::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||
std::unique_ptr<Track> MSA::track_at_position(Track::Address address) {
|
||||
if(address.head >= sides_) return nullptr;
|
||||
|
||||
const auto position = address.position.as_int();
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
// Implemented to satisfy @c DiskImage.
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
bool get_is_read_only() final { return false; }
|
||||
|
||||
private:
|
||||
|
@ -171,7 +171,7 @@ bool MacintoshIMG::get_is_read_only() {
|
||||
return file_.get_is_known_read_only();
|
||||
}
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> MacintoshIMG::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||
std::unique_ptr<Track> MacintoshIMG::track_at_position(Track::Address address) {
|
||||
/*
|
||||
The format_ byte has the following meanings:
|
||||
|
||||
@ -246,13 +246,13 @@ std::shared_ptr<::Storage::Disk::Track> MacintoshIMG::get_track_at_position(::St
|
||||
// TODO: it seems some tracks are skewed respective to others; investigate further.
|
||||
|
||||
// segment.rotate_right(3000); // Just a test, yo.
|
||||
return std::make_shared<PCMTrack>(segment);
|
||||
return std::make_unique<PCMTrack>(segment);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MacintoshIMG::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
||||
void MacintoshIMG::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) {
|
||||
std::map<Track::Address, std::vector<uint8_t>> tracks_by_address;
|
||||
for(const auto &pair: tracks) {
|
||||
// Determine a data rate for the track.
|
||||
|
@ -47,8 +47,8 @@ public:
|
||||
int get_head_count() final;
|
||||
bool get_is_read_only() final;
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) final;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
|
@ -54,7 +54,14 @@ long NIB::file_offset(Track::Address address) {
|
||||
return long(address.position.as_int()) * track_length;
|
||||
}
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||
Track::Address NIB::canonical_address(Track::Address address) {
|
||||
return Track::Address(
|
||||
address.head,
|
||||
HeadPosition(address.position.as_int())
|
||||
);
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> NIB::track_at_position(Track::Address address) {
|
||||
static constexpr size_t MinimumSyncByteCount = 4;
|
||||
|
||||
// NIBs contain data for a fixed quantity of integer-position tracks underneath a single head only.
|
||||
@ -71,9 +78,6 @@ std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Di
|
||||
std::vector<uint8_t> track_data;
|
||||
{
|
||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||
if(cached_offset_ == offset && cached_track_) {
|
||||
return cached_track_;
|
||||
}
|
||||
file_.seek(offset, SEEK_SET);
|
||||
track_data = file_.read(track_length);
|
||||
}
|
||||
@ -133,12 +137,10 @@ std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Di
|
||||
}
|
||||
|
||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||
cached_offset_ = offset;
|
||||
cached_track_ = std::make_shared<PCMTrack>(segment);
|
||||
return cached_track_;
|
||||
return std::make_unique<PCMTrack>(segment);
|
||||
}
|
||||
|
||||
void NIB::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
||||
void NIB::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) {
|
||||
std::map<Track::Address, std::vector<uint8_t>> tracks_by_address;
|
||||
|
||||
// Convert to a map from address to a vector of data that contains the NIB representation
|
||||
@ -186,5 +188,4 @@ void NIB::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tra
|
||||
file_.seek(file_offset(track.first), SEEK_SET);
|
||||
file_.write(track.second);
|
||||
}
|
||||
cached_track_ = nullptr; // Conservative, but safe.
|
||||
}
|
||||
|
@ -27,20 +27,15 @@ public:
|
||||
|
||||
// Implemented to satisfy @c DiskImage.
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) final;
|
||||
Track::Address canonical_address(Track::Address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) final;
|
||||
bool get_is_read_only() final;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address address);
|
||||
long file_offset(Track::Address address);
|
||||
|
||||
// Cache for the last-generated track, given that head steps on an Apple II
|
||||
// occur in quarter-track increments, so there'll routinely be four gets in
|
||||
// a row for the same data.
|
||||
long cached_offset_ = 0;
|
||||
std::shared_ptr<Storage::Disk::PCMTrack> cached_track_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ long OricMFMDSK::get_file_offset_for_position(Track::Address address) {
|
||||
return long(seek_offset) * 6400 + 256;
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> OricMFMDSK::get_track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> OricMFMDSK::track_at_position(Track::Address address) {
|
||||
PCMSegment segment;
|
||||
{
|
||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||
@ -112,10 +112,10 @@ std::shared_ptr<Track> OricMFMDSK::get_track_at_position(Track::Address address)
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_shared<PCMTrack>(segment);
|
||||
return std::make_unique<PCMTrack>(segment);
|
||||
}
|
||||
|
||||
void OricMFMDSK::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
||||
void OricMFMDSK::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) {
|
||||
for(const auto &track : tracks) {
|
||||
PCMSegment segment = Storage::Disk::track_serialisation(*track.second, Storage::Encodings::MFM::MFMBitLength);
|
||||
Storage::Encodings::MFM::Shifter shifter;
|
||||
|
@ -32,8 +32,8 @@ public:
|
||||
int get_head_count() final;
|
||||
bool get_is_read_only() final;
|
||||
|
||||
void set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) final;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
|
@ -182,7 +182,7 @@ public:
|
||||
(void)first_sync_;
|
||||
}
|
||||
|
||||
std::shared_ptr<PCMTrack> get_track() {
|
||||
std::unique_ptr<PCMTrack> get_track() {
|
||||
// If no contents are supplied, return an unformatted track.
|
||||
if(sectors_.empty() && track_data_.empty()) {
|
||||
return nullptr;
|
||||
@ -192,11 +192,11 @@ public:
|
||||
// changes and fuzzy bits in sectors only.
|
||||
if(sectors_.empty()) {
|
||||
PCMSegment segment;
|
||||
std::unique_ptr<Storage::Encodings::MFM::Encoder> encoder = Storage::Encodings::MFM::GetMFMEncoder(segment.data);
|
||||
auto encoder = Storage::Encodings::MFM::GetMFMEncoder(segment.data);
|
||||
for(auto c: track_data_) {
|
||||
encoder->add_byte(c);
|
||||
}
|
||||
return std::make_shared<PCMTrack>(segment);
|
||||
return std::make_unique<PCMTrack>(segment);
|
||||
}
|
||||
|
||||
// Otherwise, seek to encode the sectors, using the track data to
|
||||
@ -377,7 +377,7 @@ public:
|
||||
track_size += 16;
|
||||
}
|
||||
|
||||
return std::make_shared<PCMTrack>(segments);
|
||||
return std::make_unique<PCMTrack>(segments);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -448,7 +448,7 @@ int STX::get_head_count() {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> STX::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||
std::unique_ptr<Track> STX::track_at_position(Track::Address address) {
|
||||
// These images have two sides, at most.
|
||||
if(address.head > 1) return nullptr;
|
||||
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
std::shared_ptr<Track> Storage::Disk::track_for_sectors(
|
||||
std::unique_ptr<Track> Storage::Disk::track_for_sectors(
|
||||
const uint8_t *const source,
|
||||
int number_of_sectors,
|
||||
uint8_t track,
|
||||
|
@ -17,7 +17,22 @@
|
||||
|
||||
namespace Storage::Disk {
|
||||
|
||||
std::shared_ptr<Track> 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);
|
||||
std::unique_ptr<Track> 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
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ bool WOZ::tracks_differ(Track::Address lhs, Track::Address rhs) {
|
||||
return offset1 != offset2;
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> WOZ::get_track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> WOZ::track_at_position(Track::Address address) {
|
||||
const long offset = file_offset(address);
|
||||
if(offset == NoSuchTrack) {
|
||||
return nullptr;
|
||||
@ -183,10 +183,10 @@ std::shared_ptr<Track> WOZ::get_track_at_position(Track::Address address) {
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_shared<PCMTrack>(PCMSegment(number_of_bits, track_contents));
|
||||
return std::make_unique<PCMTrack>(PCMSegment(number_of_bits, track_contents));
|
||||
}
|
||||
|
||||
void WOZ::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
||||
void WOZ::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) {
|
||||
if(type_ == Type::WOZ2) return;
|
||||
|
||||
for(const auto &pair: tracks) {
|
||||
|
@ -26,8 +26,8 @@ public:
|
||||
// Implemented to satisfy @c DiskImage.
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
std::shared_ptr<Track> get_track_at_position(Track::Address address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks) final;
|
||||
bool get_is_read_only() final;
|
||||
bool tracks_differ(Track::Address, Track::Address) final;
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include "Drive.hpp"
|
||||
|
||||
#include "Track/UnformattedTrack.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
@ -107,7 +105,7 @@ void Drive::step(HeadPosition offset) {
|
||||
did_step(head_position_);
|
||||
}
|
||||
|
||||
std::shared_ptr<Track> Drive::step_to(HeadPosition offset) {
|
||||
Track *Drive::step_to(HeadPosition offset) {
|
||||
HeadPosition old_head_position = head_position_;
|
||||
head_position_ = std::max(offset, HeadPosition(0));
|
||||
|
||||
@ -343,8 +341,8 @@ void Drive::process_next_event() {
|
||||
|
||||
// MARK: - Track management
|
||||
|
||||
std::shared_ptr<Track> Drive::get_track() {
|
||||
if(disk_) return disk_->get_track_at_position(Track::Address(head_, head_position_));
|
||||
Track *Drive::get_track() {
|
||||
if(disk_) return disk_->track_at_position(Track::Address(head_, head_position_));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -355,7 +353,7 @@ void Drive::set_track(const std::shared_ptr<Track> &track) {
|
||||
void Drive::setup_track() {
|
||||
track_ = get_track();
|
||||
if(!track_) {
|
||||
track_ = std::make_shared<UnformattedTrack>();
|
||||
track_ = &unformatted_track_;
|
||||
}
|
||||
|
||||
float offset = 0.0f;
|
||||
@ -426,11 +424,11 @@ void Drive::end_writing() {
|
||||
|
||||
if(!patched_track_) {
|
||||
// Avoid creating a new patched track if this one is already patched
|
||||
patched_track_ = std::dynamic_pointer_cast<PCMTrack>(track_);
|
||||
if(!patched_track_ || !patched_track_->is_resampled_clone()) {
|
||||
Track *const tr = track_.get();
|
||||
// patched_track_ = dynamic_cast<PCMTrack *>(track_);
|
||||
// if(!patched_track_ || !patched_track_->is_resampled_clone()) {
|
||||
Track *const tr = track_;
|
||||
patched_track_.reset(PCMTrack::resampled_clone(tr, high_resolution_track_rate));
|
||||
}
|
||||
// }
|
||||
}
|
||||
patched_track_->add_segment(write_start_time_, write_segment_, clamp_writing_to_index_hole_);
|
||||
cycles_since_index_hole_ %= cycles_per_revolution_;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "Disk.hpp"
|
||||
#include "Track/PCMSegment.hpp"
|
||||
#include "Track/PCMTrack.hpp"
|
||||
#include "Track/UnformattedTrack.hpp"
|
||||
|
||||
#include "../TimedEventLoop.hpp"
|
||||
#include "../../Activity/Observer.hpp"
|
||||
@ -174,7 +175,7 @@ public:
|
||||
|
||||
It's for the benefit of user-optional fast-loading mechanisms **ONLY**.
|
||||
*/
|
||||
std::shared_ptr<Track> step_to(HeadPosition offset);
|
||||
Track *step_to(HeadPosition offset);
|
||||
|
||||
/*!
|
||||
Alters the rotational velocity of this drive.
|
||||
@ -209,7 +210,8 @@ private:
|
||||
// Drives contain an entire disk; from that a certain track
|
||||
// will be currently under the head.
|
||||
std::shared_ptr<Disk> disk_;
|
||||
std::shared_ptr<Track> track_;
|
||||
UnformattedTrack unformatted_track_;
|
||||
Track *track_ = nullptr;
|
||||
bool has_disk_ = false;
|
||||
|
||||
// Contains the multiplier that converts between track-relative lengths
|
||||
@ -274,7 +276,7 @@ private:
|
||||
/*!
|
||||
@returns the track underneath the current head at the location now stepped to.
|
||||
*/
|
||||
std::shared_ptr<Track> get_track();
|
||||
Track *get_track();
|
||||
|
||||
/*!
|
||||
Attempts to set @c track as the track underneath the current head at the location now stepped to.
|
||||
|
@ -179,7 +179,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> std::shared_ptr<Storage::Disk::Track>
|
||||
template<class T> std::unique_ptr<Storage::Disk::Track>
|
||||
GTrackWithSectors(
|
||||
const std::vector<const Sector *> §ors,
|
||||
std::size_t post_index_address_mark_bytes, uint8_t post_index_address_mark_value,
|
||||
@ -300,7 +300,7 @@ template<class T> std::shared_ptr<Storage::Disk::Track>
|
||||
// Allow the amount of data written to be up to 10% more than the expected size. Which is generous.
|
||||
if(segment.data.size() > max_size) segment.data.resize(max_size);
|
||||
|
||||
return std::make_shared<Storage::Disk::PCMTrack>(std::move(segment));
|
||||
return std::make_unique<Storage::Disk::PCMTrack>(std::move(segment));
|
||||
}
|
||||
|
||||
Encoder::Encoder(std::vector<bool> &target, std::vector<bool> *fuzzy_target) :
|
||||
@ -339,7 +339,7 @@ void Encoder::add_crc(bool incorrectly) {
|
||||
|
||||
namespace {
|
||||
template <Density density>
|
||||
std::shared_ptr<Storage::Disk::Track> TTrackWithSectors(
|
||||
std::unique_ptr<Storage::Disk::Track> TTrackWithSectors(
|
||||
const std::vector<const Sector *> §ors,
|
||||
std::optional<std::size_t> sector_gap_length,
|
||||
std::optional<uint8_t> sector_gap_filler_byte
|
||||
@ -361,7 +361,7 @@ std::shared_ptr<Storage::Disk::Track> TTrackWithSectors(
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<Storage::Disk::Track> Storage::Encodings::MFM::TrackWithSectors(
|
||||
std::unique_ptr<Storage::Disk::Track> Storage::Encodings::MFM::TrackWithSectors(
|
||||
Density density,
|
||||
const std::vector<Sector> §ors,
|
||||
std::optional<std::size_t> sector_gap_length,
|
||||
@ -375,7 +375,7 @@ std::shared_ptr<Storage::Disk::Track> Storage::Encodings::MFM::TrackWithSectors(
|
||||
);
|
||||
}
|
||||
|
||||
std::shared_ptr<Storage::Disk::Track> Storage::Encodings::MFM::TrackWithSectors(
|
||||
std::unique_ptr<Storage::Disk::Track> Storage::Encodings::MFM::TrackWithSectors(
|
||||
Density density,
|
||||
const std::vector<const Sector *> §ors,
|
||||
std::optional<std::size_t> sector_gap_length,
|
||||
|
@ -27,13 +27,13 @@ namespace Storage::Encodings::MFM {
|
||||
@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<Storage::Disk::Track> TrackWithSectors(
|
||||
std::unique_ptr<Storage::Disk::Track> TrackWithSectors(
|
||||
Density density,
|
||||
const std::vector<Sector> §ors,
|
||||
std::optional<std::size_t> sector_gap_length = std::nullopt,
|
||||
std::optional<uint8_t> sector_gap_filler_byte = std::nullopt);
|
||||
|
||||
std::shared_ptr<Storage::Disk::Track> TrackWithSectors(
|
||||
std::unique_ptr<Storage::Disk::Track> TrackWithSectors(
|
||||
Density density,
|
||||
const std::vector<const Sector *> §ors,
|
||||
std::optional<std::size_t> sector_gap_length = std::nullopt,
|
||||
|
@ -25,7 +25,7 @@ void Parser::install_track(const Storage::Disk::Track::Address &address) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto track = disk_->get_track_at_position(address);
|
||||
const auto track = disk_->track_at_position(address);
|
||||
if(!track) {
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user