mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-21 18:37:11 +00:00
Improve const
ness, remove unnecessary virtual
s.
This commit is contained in:
parent
43353ce892
commit
8dcccf11bf
@ -40,6 +40,10 @@ public:
|
||||
get_drive().set_disk(disk);
|
||||
}
|
||||
|
||||
const Storage::Disk::Disk *disk() const {
|
||||
return get_drive().disk();
|
||||
}
|
||||
|
||||
void set_activity_observer(Activity::Observer *observer) {
|
||||
get_drive().set_activity_observer(observer, "Drive 1", true);
|
||||
}
|
||||
|
@ -696,6 +696,12 @@ template<Model model> class ConcreteMachine:
|
||||
return !media.tapes.empty() || (!media.disks.empty() && model == Model::Plus3);
|
||||
}
|
||||
|
||||
ChangeEffect effect_for_file_did_change(const std::string &file_name) override {
|
||||
fdc_->disk();
|
||||
|
||||
return ChangeEffect::None;
|
||||
}
|
||||
|
||||
// MARK: - ClockingHint::Observer.
|
||||
|
||||
void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) override {
|
||||
|
@ -82,11 +82,6 @@ class MachineDocument:
|
||||
case .none: fallthrough
|
||||
@unknown default: break
|
||||
}
|
||||
|
||||
Swift.print("Content changed")
|
||||
|
||||
// TODO: tell machine content has changed. Machine will need to indicate
|
||||
// whether it's the one that changed it. If not, restart the machine.
|
||||
})
|
||||
} else {
|
||||
throw NSError(domain: "MachineDocument", code: -1, userInfo: nil)
|
||||
|
@ -32,18 +32,18 @@ public:
|
||||
This is not necessarily a track count. There is no implicit guarantee that every position will
|
||||
return a distinct track, or, e.g. if the media is holeless, will return any track at all.
|
||||
*/
|
||||
virtual HeadPosition get_maximum_head_position() = 0;
|
||||
virtual HeadPosition get_maximum_head_position() const = 0;
|
||||
|
||||
/*!
|
||||
@returns the number of heads (and, therefore, impliedly surfaces) available on this disk.
|
||||
*/
|
||||
virtual int get_head_count() = 0;
|
||||
virtual int get_head_count() const = 0;
|
||||
|
||||
/*!
|
||||
@returns the @c Track at @c position underneath @c head if there are any detectable events there;
|
||||
returns @c nullptr otherwise.
|
||||
*/
|
||||
virtual Track *track_at_position(Track::Address) = 0;
|
||||
virtual Track *track_at_position(Track::Address) const = 0;
|
||||
|
||||
/*!
|
||||
Replaces the Track at position @c position underneath @c head with @c track. Ignored if this disk is read-only.
|
||||
@ -58,13 +58,23 @@ public:
|
||||
/*!
|
||||
@returns whether the disk image is read only. Defaults to @c true if not overridden.
|
||||
*/
|
||||
virtual bool get_is_read_only() = 0;
|
||||
virtual bool get_is_read_only() const = 0;
|
||||
|
||||
/*!
|
||||
@returns @c true if the tracks at the two addresses are different. @c false if they are the same track.
|
||||
This can avoid some degree of work when disk images offer sub-head-position precision.
|
||||
*/
|
||||
virtual bool tracks_differ(Track::Address, Track::Address) = 0;
|
||||
virtual bool tracks_differ(Track::Address, Track::Address) const = 0;
|
||||
|
||||
/*!
|
||||
@returns @c true if the file named by the string is what underlies this disk image; @c false otherwise.
|
||||
*/
|
||||
virtual bool represents(const std::string &) const = 0;
|
||||
|
||||
/*!
|
||||
@returns @c true if this disk has been written to at any point; @c false otherwise.
|
||||
*/
|
||||
virtual bool has_written() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -39,51 +39,51 @@ public:
|
||||
This is not necessarily a track count. There is no implicit guarantee that every position will
|
||||
return a distinct track, or, e.g. if the media is holeless, will return any track at all.
|
||||
*/
|
||||
virtual HeadPosition get_maximum_head_position() = 0;
|
||||
// virtual HeadPosition get_maximum_head_position() = 0;
|
||||
|
||||
/*!
|
||||
@returns the number of heads (and, therefore, impliedly surfaces) available on this disk.
|
||||
*/
|
||||
virtual int get_head_count() { return 1; }
|
||||
int get_head_count() const { return 1; }
|
||||
|
||||
/*!
|
||||
@returns the @c Track at @c position underneath @c head if there are any detectable events there;
|
||||
returns @c nullptr otherwise.
|
||||
*/
|
||||
virtual std::unique_ptr<Track> 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::unique_ptr<Track>> &) {}
|
||||
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.
|
||||
*/
|
||||
virtual void flush_tracks() {}
|
||||
void flush_tracks() {}
|
||||
|
||||
/*!
|
||||
@returns whether the disk image is read only. Defaults to @c true if not overridden.
|
||||
*/
|
||||
virtual bool get_is_read_only() { return true; }
|
||||
bool get_is_read_only() const { return true; }
|
||||
|
||||
/*!
|
||||
@returns @c true if the tracks at the two addresses are different. @c false if they are the same track.
|
||||
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; }
|
||||
bool tracks_differ(Track::Address lhs, Track::Address rhs) const { 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; }
|
||||
Track::Address canonical_address(Track::Address address) const { return address; }
|
||||
};
|
||||
|
||||
class DiskImageHolderBase: public Disk {
|
||||
protected:
|
||||
std::set<Track::Address> unwritten_tracks_;
|
||||
std::map<Track::Address, std::shared_ptr<Track>> cached_tracks_;
|
||||
mutable std::map<Track::Address, std::shared_ptr<Track>> cached_tracks_;
|
||||
std::unique_ptr<Concurrency::AsyncTaskQueue<true>> update_queue_;
|
||||
};
|
||||
|
||||
@ -95,22 +95,26 @@ class DiskImageHolderBase: public Disk {
|
||||
Implements TargetPlatform::TypeDistinguisher to return either no information whatsoever, if
|
||||
the underlying image doesn't implement TypeDistinguisher, or else to pass the call along.
|
||||
*/
|
||||
template <typename T> class DiskImageHolder: public DiskImageHolderBase, public TargetPlatform::Distinguisher {
|
||||
template <typename T>
|
||||
class DiskImageHolder: public DiskImageHolderBase, public TargetPlatform::Distinguisher {
|
||||
public:
|
||||
template <typename... Ts> DiskImageHolder(Ts&&... args) :
|
||||
disk_image_(args...) {}
|
||||
~DiskImageHolder();
|
||||
|
||||
HeadPosition get_maximum_head_position();
|
||||
int get_head_count();
|
||||
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();
|
||||
bool tracks_differ(Track::Address lhs, Track::Address rhs);
|
||||
HeadPosition get_maximum_head_position() const override;
|
||||
int get_head_count() const override;
|
||||
Track *track_at_position(Track::Address address) const override;
|
||||
void set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) override;
|
||||
void flush_tracks() override;
|
||||
bool tracks_differ(Track::Address lhs, Track::Address rhs) const override;
|
||||
bool get_is_read_only() const override;
|
||||
bool represents(const std::string &) const override;
|
||||
bool has_written() const override;
|
||||
|
||||
private:
|
||||
T disk_image_;
|
||||
bool has_written_ = false;
|
||||
|
||||
TargetPlatform::Type target_platforms() final {
|
||||
if constexpr (std::is_base_of<TargetPlatform::Distinguisher, T>::value) {
|
||||
|
@ -6,19 +6,34 @@
|
||||
// Copyright 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
template <typename T> HeadPosition DiskImageHolder<T>::get_maximum_head_position() {
|
||||
template <typename T>
|
||||
HeadPosition DiskImageHolder<T>::get_maximum_head_position() const {
|
||||
return disk_image_.get_maximum_head_position();
|
||||
}
|
||||
|
||||
template <typename T> int DiskImageHolder<T>::get_head_count() {
|
||||
template <typename T>
|
||||
int DiskImageHolder<T>::get_head_count() const {
|
||||
return disk_image_.get_head_count();
|
||||
}
|
||||
|
||||
template <typename T> bool DiskImageHolder<T>::get_is_read_only() {
|
||||
template <typename T>
|
||||
bool DiskImageHolder<T>::get_is_read_only() const {
|
||||
return disk_image_.get_is_read_only();
|
||||
}
|
||||
|
||||
template <typename T> void DiskImageHolder<T>::flush_tracks() {
|
||||
template <typename T>
|
||||
bool DiskImageHolder<T>::represents(const std::string &file) const {
|
||||
return false; // TODO.
|
||||
// return disk_image_.represents(file);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DiskImageHolder<T>::has_written() const {
|
||||
return has_written_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DiskImageHolder<T>::flush_tracks() {
|
||||
if(!unwritten_tracks_.empty()) {
|
||||
if(!update_queue_) update_queue_ = std::make_unique<Concurrency::AsyncTaskQueue<true>>();
|
||||
|
||||
@ -35,14 +50,17 @@ template <typename T> void DiskImageHolder<T>::flush_tracks() {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void DiskImageHolder<T>::set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) {
|
||||
template <typename T>
|
||||
void DiskImageHolder<T>::set_track_at_position(Track::Address address, const std::shared_ptr<Track> &track) {
|
||||
if(disk_image_.get_is_read_only()) return;
|
||||
has_written_ = true;
|
||||
|
||||
unwritten_tracks_.insert(address);
|
||||
cached_tracks_[address] = track;
|
||||
}
|
||||
|
||||
template <typename T> Track *DiskImageHolder<T>::track_at_position(Track::Address address) {
|
||||
template <typename T>
|
||||
Track *DiskImageHolder<T>::track_at_position(Track::Address address) const {
|
||||
if(address.head >= get_head_count()) return nullptr;
|
||||
if(address.position >= get_maximum_head_position()) return nullptr;
|
||||
|
||||
@ -56,10 +74,12 @@ template <typename T> Track *DiskImageHolder<T>::track_at_position(Track::Addres
|
||||
return track.get();
|
||||
}
|
||||
|
||||
template <typename T> DiskImageHolder<T>::~DiskImageHolder() {
|
||||
template <typename T>
|
||||
DiskImageHolder<T>::~DiskImageHolder() {
|
||||
if(update_queue_) update_queue_->flush();
|
||||
}
|
||||
|
||||
template <typename T> bool DiskImageHolder<T>::tracks_differ(Track::Address lhs, Track::Address rhs) {
|
||||
template <typename T>
|
||||
bool DiskImageHolder<T>::tracks_differ(Track::Address lhs, Track::Address rhs) const {
|
||||
return disk_image_.tracks_differ(lhs, rhs);
|
||||
}
|
||||
|
@ -78,7 +78,8 @@ Disk2MG::DiskOrMassStorageDevice Disk2MG::open(const std::string &file_name) {
|
||||
// 'ProDOS order', which could still mean Macintosh-style (ie. not ProDOS, but whatever)
|
||||
// or Apple II-style. Try them both.
|
||||
try {
|
||||
return new DiskImageHolder<Storage::Disk::MacintoshIMG>(file_name, MacintoshIMG::FixedType::GCR, data_start, data_size);
|
||||
return new DiskImageHolder<Storage::Disk::MacintoshIMG>(
|
||||
file_name, MacintoshIMG::FixedType::GCR, data_start, data_size);
|
||||
} catch(...) {}
|
||||
|
||||
// TODO: Apple II-style.
|
||||
|
@ -111,14 +111,14 @@ AcornADF::AcornADF(const std::string &file_name) : MFMSectorDump(file_name) {
|
||||
set_geometry(sectors_per_track_, sector_size_, 0, density);
|
||||
}
|
||||
|
||||
HeadPosition AcornADF::get_maximum_head_position() {
|
||||
HeadPosition AcornADF::get_maximum_head_position() const {
|
||||
return HeadPosition(80);
|
||||
}
|
||||
|
||||
int AcornADF::get_head_count() {
|
||||
int AcornADF::get_head_count() const {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
long AcornADF::get_file_offset_for_position(Track::Address address) {
|
||||
long AcornADF::get_file_offset_for_position(Track::Address address) const {
|
||||
return (address.position.as_int() * head_count_ + address.head) * (128 << sector_size_) * sectors_per_track_;
|
||||
}
|
||||
|
@ -27,11 +27,11 @@ public:
|
||||
*/
|
||||
AcornADF(const std::string &file_name);
|
||||
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
HeadPosition get_maximum_head_position() const final;
|
||||
int get_head_count() const final;
|
||||
|
||||
private:
|
||||
long get_file_offset_for_position(Track::Address) final;
|
||||
long get_file_offset_for_position(Track::Address) const final;
|
||||
int head_count_ = 1;
|
||||
uint8_t sector_size_ = 1;
|
||||
int sectors_per_track_ = 16;
|
||||
|
@ -116,15 +116,15 @@ AmigaADF::AmigaADF(const std::string &file_name) :
|
||||
if(file_.stats().st_size != 901120) throw Error::InvalidFormat;
|
||||
}
|
||||
|
||||
HeadPosition AmigaADF::get_maximum_head_position() {
|
||||
HeadPosition AmigaADF::get_maximum_head_position() const {
|
||||
return HeadPosition(80);
|
||||
}
|
||||
|
||||
int AmigaADF::get_head_count() {
|
||||
int AmigaADF::get_head_count() const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> AmigaADF::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> AmigaADF::track_at_position(Track::Address address) const {
|
||||
using namespace Storage::Encodings;
|
||||
|
||||
// Create an MFM encoder.
|
||||
@ -182,6 +182,6 @@ std::unique_ptr<Track> AmigaADF::track_at_position(Track::Address address) {
|
||||
return std::make_unique<Storage::Disk::PCMTrack>(std::move(encoded_segment));
|
||||
}
|
||||
|
||||
long AmigaADF::get_file_offset_for_position(Track::Address address) {
|
||||
long AmigaADF::get_file_offset_for_position(Track::Address address) const {
|
||||
return (address.position.as_int() * 2 + address.head) * 512 * 11;
|
||||
}
|
||||
|
@ -29,13 +29,13 @@ public:
|
||||
AmigaADF(const std::string &file_name);
|
||||
|
||||
// implemented to satisfy @c Disk
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address);
|
||||
mutable Storage::FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address) const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -42,26 +42,26 @@ AppleDSK::AppleDSK(const std::string &file_name) :
|
||||
}
|
||||
}
|
||||
|
||||
HeadPosition AppleDSK::get_maximum_head_position() {
|
||||
HeadPosition AppleDSK::get_maximum_head_position() const {
|
||||
return HeadPosition(number_of_tracks);
|
||||
}
|
||||
|
||||
bool AppleDSK::get_is_read_only() {
|
||||
bool AppleDSK::get_is_read_only() const {
|
||||
return file_.get_is_known_read_only();
|
||||
}
|
||||
|
||||
long AppleDSK::file_offset(Track::Address address) {
|
||||
long AppleDSK::file_offset(Track::Address address) const {
|
||||
return address.position.as_int() * bytes_per_sector * sectors_per_track_;
|
||||
}
|
||||
|
||||
size_t AppleDSK::logical_sector_for_physical_sector(size_t physical) {
|
||||
size_t AppleDSK::logical_sector_for_physical_sector(size_t physical) const {
|
||||
// DOS and Pro DOS interleave sectors on disk, and they're represented in a disk
|
||||
// image in physical order rather than logical.
|
||||
if(physical == 15) return 15;
|
||||
return (physical * (is_prodos_ ? 8 : 7)) % 15;
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> AppleDSK::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> AppleDSK::track_at_position(Track::Address address) const {
|
||||
std::vector<uint8_t> track_data;
|
||||
{
|
||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||
|
@ -30,18 +30,18 @@ public:
|
||||
AppleDSK(const std::string &file_name);
|
||||
|
||||
// Implemented to satisfy @c DiskImage.
|
||||
HeadPosition get_maximum_head_position() 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;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &);
|
||||
bool get_is_read_only() const;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
mutable Storage::FileHolder file_;
|
||||
int sectors_per_track_ = 16;
|
||||
bool is_prodos_ = false;
|
||||
|
||||
long file_offset(Track::Address);
|
||||
size_t logical_sector_for_physical_sector(size_t physical);
|
||||
long file_offset(Track::Address) const;
|
||||
size_t logical_sector_for_physical_sector(size_t physical) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -186,19 +186,19 @@ CPCDSK::CPCDSK(const std::string &file_name) :
|
||||
}
|
||||
}
|
||||
|
||||
HeadPosition CPCDSK::get_maximum_head_position() {
|
||||
HeadPosition CPCDSK::get_maximum_head_position() const {
|
||||
return HeadPosition(head_position_count_);
|
||||
}
|
||||
|
||||
int CPCDSK::get_head_count() {
|
||||
int CPCDSK::get_head_count() const {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
std::size_t CPCDSK::index_for_track(::Storage::Disk::Track::Address address) {
|
||||
std::size_t CPCDSK::index_for_track(::Storage::Disk::Track::Address address) const {
|
||||
return size_t((address.position.as_int() * head_count_) + address.head);
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> CPCDSK::track_at_position(::Storage::Disk::Track::Address address) {
|
||||
std::unique_ptr<Track> CPCDSK::track_at_position(::Storage::Disk::Track::Address address) const {
|
||||
// Given that thesea are interleaved images, determine which track, chronologically, is being requested.
|
||||
const std::size_t chronological_track = index_for_track(address);
|
||||
|
||||
@ -385,6 +385,6 @@ void CPCDSK::set_tracks(const std::map<::Storage::Disk::Track::Address, std::uni
|
||||
}
|
||||
}
|
||||
|
||||
bool CPCDSK::get_is_read_only() {
|
||||
bool CPCDSK::get_is_read_only() const {
|
||||
return is_read_only_;
|
||||
}
|
||||
|
@ -31,11 +31,11 @@ public:
|
||||
CPCDSK(const std::string &file_name);
|
||||
|
||||
// DiskImage interface.
|
||||
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::unique_ptr<Track>> &) final;
|
||||
std::unique_ptr<::Storage::Disk::Track> track_at_position(::Storage::Disk::Track::Address) final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
bool get_is_read_only() const;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &);
|
||||
std::unique_ptr<::Storage::Disk::Track> track_at_position(::Storage::Disk::Track::Address) const;
|
||||
|
||||
private:
|
||||
struct Track {
|
||||
@ -60,7 +60,7 @@ private:
|
||||
};
|
||||
std::string file_name_;
|
||||
std::vector<std::unique_ptr<Track>> tracks_;
|
||||
std::size_t index_for_track(::Storage::Disk::Track::Address address);
|
||||
std::size_t index_for_track(::Storage::Disk::Track::Address address) const;
|
||||
|
||||
int head_count_;
|
||||
int head_position_count_;
|
||||
|
@ -34,11 +34,11 @@ D64::D64(const std::string &file_name) :
|
||||
}
|
||||
}
|
||||
|
||||
HeadPosition D64::get_maximum_head_position() {
|
||||
HeadPosition D64::get_maximum_head_position() const {
|
||||
return HeadPosition(number_of_tracks_);
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> D64::track_at_position(const Track::Address address) {
|
||||
std::unique_ptr<Track> D64::track_at_position(const Track::Address address) const {
|
||||
// Figure out where this track starts on the disk.
|
||||
int offset_to_track = 0;
|
||||
int tracks_to_traverse = address.position.as_int();
|
||||
|
@ -26,11 +26,11 @@ public:
|
||||
*/
|
||||
D64(const std::string &file_name);
|
||||
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
mutable Storage::FileHolder file_;
|
||||
int number_of_tracks_;
|
||||
uint16_t disk_id_;
|
||||
};
|
||||
|
@ -61,25 +61,25 @@ DMK::DMK(const std::string &file_name) :
|
||||
if(format) throw Error::InvalidFormat;
|
||||
}
|
||||
|
||||
HeadPosition DMK::get_maximum_head_position() {
|
||||
HeadPosition DMK::get_maximum_head_position() const {
|
||||
return HeadPosition(head_position_count_);
|
||||
}
|
||||
|
||||
int DMK::get_head_count() {
|
||||
int DMK::get_head_count() const {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
bool DMK::get_is_read_only() {
|
||||
bool DMK::get_is_read_only() const {
|
||||
return true;
|
||||
// Given that track serialisation is not yet implemented, treat all DMKs as read-only.
|
||||
// return is_read_only_;
|
||||
}
|
||||
|
||||
long DMK::get_file_offset_for_position(Track::Address address) {
|
||||
long DMK::get_file_offset_for_position(const Track::Address address) const {
|
||||
return (address.head*head_count_ + address.position.as_int()) * track_length_ + 16;
|
||||
}
|
||||
|
||||
std::unique_ptr<::Storage::Disk::Track> DMK::track_at_position(::Storage::Disk::Track::Address address) {
|
||||
std::unique_ptr<::Storage::Disk::Track> DMK::track_at_position(const ::Storage::Disk::Track::Address address) const {
|
||||
file_.seek(get_file_offset_for_position(address), SEEK_SET);
|
||||
|
||||
// Read the IDAM table.
|
||||
|
@ -28,16 +28,15 @@ public:
|
||||
*/
|
||||
DMK(const std::string &file_name);
|
||||
|
||||
// implemented to satisfy @c Disk
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
bool get_is_read_only() final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
bool get_is_read_only() const;
|
||||
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address address);
|
||||
mutable FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address address) const;
|
||||
|
||||
bool is_read_only_;
|
||||
int head_position_count_;
|
||||
|
@ -49,14 +49,14 @@ FAT12::FAT12(const std::string &file_name) :
|
||||
);
|
||||
}
|
||||
|
||||
HeadPosition FAT12::get_maximum_head_position() {
|
||||
HeadPosition FAT12::get_maximum_head_position() const {
|
||||
return HeadPosition(track_count_);
|
||||
}
|
||||
|
||||
int FAT12::get_head_count() {
|
||||
int FAT12::get_head_count() const {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
long FAT12::get_file_offset_for_position(Track::Address address) {
|
||||
long FAT12::get_file_offset_for_position(Track::Address address) const {
|
||||
return (address.position.as_int() * head_count_ + address.head) * sector_size_ * sector_count_;
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ namespace Storage::Disk {
|
||||
class FAT12: public MFMSectorDump {
|
||||
public:
|
||||
FAT12(const std::string &file_name);
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
HeadPosition get_maximum_head_position() const final;
|
||||
int get_head_count() const final;
|
||||
|
||||
private:
|
||||
long get_file_offset_for_position(Track::Address address) final;
|
||||
long get_file_offset_for_position(Track::Address address) const;
|
||||
|
||||
int head_count_;
|
||||
int track_count_;
|
||||
|
@ -30,13 +30,13 @@ G64::G64(const std::string &file_name) :
|
||||
maximum_track_size_ = file_.get_le<uint16_t>();
|
||||
}
|
||||
|
||||
HeadPosition G64::get_maximum_head_position() {
|
||||
HeadPosition G64::get_maximum_head_position() const {
|
||||
// give at least 84 tracks, to yield the normal geometry but,
|
||||
// if there are more, shove them in
|
||||
return HeadPosition(number_of_tracks_ > 84 ? number_of_tracks_ : 84, 2);
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> G64::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> G64::track_at_position(const Track::Address address) const {
|
||||
// seek to this track's entry in the track table
|
||||
file_.seek(long((address.position.as_half() * 4) + 0xc), SEEK_SET);
|
||||
|
||||
|
@ -30,12 +30,12 @@ public:
|
||||
G64(const std::string &file_name);
|
||||
|
||||
// implemented to satisfy @c Disk
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
using DiskImage::get_is_read_only;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
mutable Storage::FileHolder file_;
|
||||
uint8_t number_of_tracks_;
|
||||
uint16_t maximum_track_size_;
|
||||
};
|
||||
|
@ -25,11 +25,11 @@ HFE::HFE(const std::string &file_name) :
|
||||
track_list_offset_ = long(file_.get_le<uint16_t>()) << 9;
|
||||
}
|
||||
|
||||
HeadPosition HFE::get_maximum_head_position() {
|
||||
HeadPosition HFE::get_maximum_head_position() const {
|
||||
return HeadPosition(track_count_);
|
||||
}
|
||||
|
||||
int HFE::get_head_count() {
|
||||
int HFE::get_head_count() const {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ int HFE::get_head_count() {
|
||||
To read the track, start from the current file position, read 256 bytes,
|
||||
skip 256 bytes, read 256 bytes, skip 256 bytes, etc.
|
||||
*/
|
||||
uint16_t HFE::seek_track(Track::Address address) {
|
||||
uint16_t HFE::seek_track(const Track::Address address) const {
|
||||
// Get track position and length from the lookup table; data is then always interleaved
|
||||
// based on an assumption of two heads.
|
||||
file_.seek(track_list_offset_ + address.position.as_int() * 4, SEEK_SET);
|
||||
@ -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::unique_ptr<Track> HFE::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> HFE::track_at_position(const Track::Address address) const {
|
||||
PCMSegment segment;
|
||||
{
|
||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||
@ -125,6 +125,6 @@ void HFE::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tra
|
||||
}
|
||||
}
|
||||
|
||||
bool HFE::get_is_read_only() {
|
||||
bool HFE::get_is_read_only() const {
|
||||
return file_.get_is_known_read_only();
|
||||
}
|
||||
|
@ -30,15 +30,15 @@ public:
|
||||
HFE(const std::string &file_name);
|
||||
|
||||
// implemented to satisfy @c Disk
|
||||
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::unique_ptr<Track>> &tracks) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
bool get_is_read_only() const;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks);
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
uint16_t seek_track(Track::Address address);
|
||||
mutable Storage::FileHolder file_;
|
||||
uint16_t seek_track(Track::Address address) const;
|
||||
|
||||
int head_count_;
|
||||
int track_count_;
|
||||
|
@ -90,15 +90,15 @@ IMD::IMD(const std::string &file_name) : file_(file_name) {
|
||||
++ heads_;
|
||||
}
|
||||
|
||||
HeadPosition IMD::get_maximum_head_position() {
|
||||
HeadPosition IMD::get_maximum_head_position() const {
|
||||
return HeadPosition(cylinders_);
|
||||
}
|
||||
|
||||
int IMD::get_head_count() {
|
||||
int IMD::get_head_count() const {
|
||||
return heads_ + 1;
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> IMD::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> IMD::track_at_position(const Track::Address address) const {
|
||||
auto location = track_locations_.find(address);
|
||||
if(location == track_locations_.end()) {
|
||||
return nullptr;
|
||||
|
@ -29,12 +29,12 @@ public:
|
||||
IMD(const std::string &file_name);
|
||||
|
||||
// DiskImage interface.
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
mutable FileHolder file_;
|
||||
std::map<Storage::Disk::Track::Address, long> track_locations_;
|
||||
uint8_t cylinders_ = 0, heads_ = 0;
|
||||
};
|
||||
|
@ -109,7 +109,7 @@ IPF::IPF(const std::string &file_name) : file_(file_name) {
|
||||
|
||||
// If the file didn't declare anything, default to supporting everything.
|
||||
if(!platform_type_) {
|
||||
platform_type_ = ~0;
|
||||
platform_type_ = ~TargetPlatform::IntType(0);
|
||||
}
|
||||
|
||||
// Ignore: disk number, creator ID, reserved area.
|
||||
@ -178,15 +178,15 @@ IPF::IPF(const std::string &file_name) : file_(file_name) {
|
||||
}
|
||||
}
|
||||
|
||||
HeadPosition IPF::get_maximum_head_position() {
|
||||
HeadPosition IPF::get_maximum_head_position() const {
|
||||
return HeadPosition(track_count_);
|
||||
}
|
||||
|
||||
int IPF::get_head_count() {
|
||||
int IPF::get_head_count() const {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> IPF::track_at_position([[maybe_unused]] Track::Address address) {
|
||||
std::unique_ptr<Track> IPF::track_at_position(const Track::Address address) const {
|
||||
// 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()) {
|
||||
@ -322,7 +322,7 @@ std::unique_ptr<Track> IPF::track_at_position([[maybe_unused]] Track::Address ad
|
||||
/// densities (or, equivalently, lengths) in the file, densities are named according to their protection scheme and the decoder
|
||||
/// is required to know all named protection schemes. Which makes IPF unable to handle arbitrary disks (or, indeed, disks
|
||||
/// with multiple protection schemes on a single track).
|
||||
Storage::Time IPF::bit_length(TrackDescription::Density density, int block) {
|
||||
Storage::Time IPF::bit_length(TrackDescription::Density density, int block) const {
|
||||
constexpr unsigned int us = 100'000'000;
|
||||
static constexpr auto us170 = Storage::Time::simplified(170, us);
|
||||
static constexpr auto us180 = Storage::Time::simplified(180, us);
|
||||
@ -378,7 +378,7 @@ Storage::Time IPF::bit_length(TrackDescription::Density density, int block) {
|
||||
return us200; // i.e. default to 2µs.
|
||||
}
|
||||
|
||||
void IPF::add_gap(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length, size_t num_bits, uint32_t value) {
|
||||
void IPF::add_gap(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length, size_t num_bits, uint32_t value) const {
|
||||
auto &segment = track.emplace_back();
|
||||
segment.length_of_a_bit = bit_length;
|
||||
|
||||
@ -396,7 +396,7 @@ void IPF::add_gap(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length
|
||||
segment.data.resize(num_bits);
|
||||
}
|
||||
|
||||
void IPF::add_unencoded_data(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length, size_t num_bits) {
|
||||
void IPF::add_unencoded_data(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length, size_t num_bits) const {
|
||||
auto &segment = track.emplace_back();
|
||||
segment.length_of_a_bit = bit_length;
|
||||
|
||||
@ -415,7 +415,7 @@ void IPF::add_unencoded_data(std::vector<Storage::Disk::PCMSegment> &track, Time
|
||||
segment.data.resize(num_bits * 2);
|
||||
}
|
||||
|
||||
void IPF::add_raw_data(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length, size_t num_bits) {
|
||||
void IPF::add_raw_data(std::vector<Storage::Disk::PCMSegment> &track, Time bit_length, size_t num_bits) const {
|
||||
auto &segment = track.emplace_back();
|
||||
segment.length_of_a_bit = bit_length;
|
||||
|
||||
|
@ -36,12 +36,12 @@ public:
|
||||
IPF(const std::string &file_name);
|
||||
|
||||
// implemented to satisfy @c Disk
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
mutable Storage::FileHolder file_;
|
||||
uint16_t seek_track(Track::Address address);
|
||||
|
||||
struct TrackDescription {
|
||||
@ -77,10 +77,10 @@ private:
|
||||
}
|
||||
TargetPlatform::IntType platform_type_ = TargetPlatform::Amiga;
|
||||
|
||||
Time bit_length(TrackDescription::Density, int block);
|
||||
void add_gap(std::vector<Storage::Disk::PCMSegment> &, Time bit_length, size_t num_bits, uint32_t value);
|
||||
void add_unencoded_data(std::vector<Storage::Disk::PCMSegment> &, Time bit_length, size_t num_bits);
|
||||
void add_raw_data(std::vector<Storage::Disk::PCMSegment> &, Time bit_length, size_t num_bits);
|
||||
Time bit_length(TrackDescription::Density, int block) const;
|
||||
void add_gap(std::vector<Storage::Disk::PCMSegment> &, Time bit_length, size_t num_bits, uint32_t value) const;
|
||||
void add_unencoded_data(std::vector<Storage::Disk::PCMSegment> &, Time bit_length, size_t num_bits) const;
|
||||
void add_raw_data(std::vector<Storage::Disk::PCMSegment> &, Time bit_length, size_t num_bits) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ void MFMSectorDump::set_geometry(int sectors_per_track, uint8_t sector_size, uin
|
||||
first_sector_ = first_sector;
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> MFMSectorDump::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> MFMSectorDump::track_at_position(Track::Address address) const {
|
||||
if(address.head >= get_head_count()) return nullptr;
|
||||
if(address.position.as_largest() >= get_maximum_head_position().as_largest()) return nullptr;
|
||||
|
||||
@ -68,6 +68,6 @@ void MFMSectorDump::set_tracks(const std::map<Track::Address, std::unique_ptr<Tr
|
||||
file_.flush();
|
||||
}
|
||||
|
||||
bool MFMSectorDump::get_is_read_only() {
|
||||
bool MFMSectorDump::get_is_read_only() const {
|
||||
return file_.get_is_known_read_only();
|
||||
}
|
||||
|
@ -23,16 +23,18 @@ class MFMSectorDump: public DiskImage {
|
||||
public:
|
||||
MFMSectorDump(const std::string &file_name);
|
||||
|
||||
bool get_is_read_only() 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;
|
||||
bool get_is_read_only() const;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks);
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
|
||||
protected:
|
||||
Storage::FileHolder file_;
|
||||
void set_geometry(int sectors_per_track, uint8_t sector_size, uint8_t first_sector, Encodings::MFM::Density density);
|
||||
mutable Storage::FileHolder file_;
|
||||
void set_geometry(int sectors_per_track, uint8_t sector_size, uint8_t first_sector, Encodings::MFM::Density);
|
||||
|
||||
private:
|
||||
virtual long get_file_offset_for_position(Track::Address address) = 0;
|
||||
virtual int get_head_count() const = 0;
|
||||
virtual HeadPosition get_maximum_head_position() const = 0;
|
||||
virtual long get_file_offset_for_position(Track::Address) const = 0;
|
||||
|
||||
int sectors_per_track_ = 0;
|
||||
uint8_t sector_size_ = 0;
|
||||
|
@ -75,7 +75,7 @@ MSA::MSA(const std::string &file_name) :
|
||||
throw Error::InvalidFormat;
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> MSA::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> MSA::track_at_position(Track::Address address) const {
|
||||
if(address.head >= sides_) return nullptr;
|
||||
|
||||
const auto position = address.position.as_int();
|
||||
@ -87,10 +87,10 @@ std::unique_ptr<Track> MSA::track_at_position(Track::Address address) {
|
||||
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() {
|
||||
HeadPosition MSA::get_maximum_head_position() const {
|
||||
return HeadPosition(ending_track_ + 1);
|
||||
}
|
||||
|
||||
int MSA::get_head_count() {
|
||||
int MSA::get_head_count() const {
|
||||
return sides_;
|
||||
}
|
||||
|
@ -24,13 +24,13 @@ public:
|
||||
MSA(const std::string &file_name);
|
||||
|
||||
// Implemented to satisfy @c DiskImage.
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
bool get_is_read_only() final { return false; }
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
bool get_is_read_only() const { return false; }
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
mutable FileHolder file_;
|
||||
uint16_t sectors_per_track_;
|
||||
uint16_t sides_;
|
||||
uint16_t starting_track_;
|
||||
|
@ -143,7 +143,7 @@ void MacintoshIMG::construct_raw_gcr(size_t offset, size_t size) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t MacintoshIMG::checksum(const std::vector<uint8_t> &data, size_t bytes_to_skip) {
|
||||
uint32_t MacintoshIMG::checksum(const std::vector<uint8_t> &data, size_t bytes_to_skip) const {
|
||||
uint32_t result = 0;
|
||||
|
||||
// Checksum algorithm is: take each two bytes as a big-endian word; add that to a
|
||||
@ -157,21 +157,21 @@ uint32_t MacintoshIMG::checksum(const std::vector<uint8_t> &data, size_t bytes_t
|
||||
return result;
|
||||
}
|
||||
|
||||
HeadPosition MacintoshIMG::get_maximum_head_position() {
|
||||
HeadPosition MacintoshIMG::get_maximum_head_position() const {
|
||||
return HeadPosition(80);
|
||||
}
|
||||
|
||||
int MacintoshIMG::get_head_count() {
|
||||
int MacintoshIMG::get_head_count() const {
|
||||
// Bit 5 in the format field indicates whether this disk is double
|
||||
// sided, regardless of whether it is GCR or MFM.
|
||||
return 1 + ((format_ & 0x20) >> 5);
|
||||
}
|
||||
|
||||
bool MacintoshIMG::get_is_read_only() {
|
||||
bool MacintoshIMG::get_is_read_only() const {
|
||||
return file_.get_is_known_read_only();
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> MacintoshIMG::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> MacintoshIMG::track_at_position(Track::Address address) const {
|
||||
/*
|
||||
The format_ byte has the following meanings:
|
||||
|
||||
@ -197,8 +197,8 @@ std::unique_ptr<Track> MacintoshIMG::track_at_position(Track::Address address) {
|
||||
|
||||
if(start_sector*512 >= data_.size()) return nullptr;
|
||||
|
||||
uint8_t *const sector = &data_[512 * start_sector];
|
||||
uint8_t *const tags = tags_.size() ? &tags_[12 * start_sector] : nullptr;
|
||||
const uint8_t *const sector = &data_[512 * start_sector];
|
||||
const uint8_t *const tags = tags_.size() ? &tags_[12 * start_sector] : nullptr;
|
||||
|
||||
Storage::Disk::PCMSegment segment;
|
||||
segment += Encodings::AppleGCR::six_and_two_sync(24);
|
||||
|
@ -43,15 +43,15 @@ public:
|
||||
MacintoshIMG(const std::string &file_name, FixedType type, size_t offset = 0, size_t length = 0);
|
||||
|
||||
// implemented to satisfy @c Disk
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
bool get_is_read_only() final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
bool get_is_read_only() const;
|
||||
|
||||
std::unique_ptr<Track> track_at_position(Track::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) const;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks);
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
mutable Storage::FileHolder file_;
|
||||
|
||||
enum class Encoding {
|
||||
GCR400,
|
||||
@ -64,9 +64,9 @@ private:
|
||||
std::vector<uint8_t> data_;
|
||||
std::vector<uint8_t> tags_;
|
||||
bool is_diskCopy_file_ = false;
|
||||
std::mutex buffer_mutex_;
|
||||
mutable std::mutex buffer_mutex_;
|
||||
|
||||
uint32_t checksum(const std::vector<uint8_t> &, size_t bytes_to_skip = 0);
|
||||
uint32_t checksum(const std::vector<uint8_t> &, size_t bytes_to_skip = 0) const;
|
||||
void construct_raw_gcr(size_t offset, size_t length = 0);
|
||||
long raw_offset_ = 0;
|
||||
};
|
||||
|
@ -42,26 +42,26 @@ NIB::NIB(const std::string &file_name) :
|
||||
}
|
||||
}
|
||||
|
||||
HeadPosition NIB::get_maximum_head_position() {
|
||||
HeadPosition NIB::get_maximum_head_position() const {
|
||||
return HeadPosition(number_of_tracks);
|
||||
}
|
||||
|
||||
bool NIB::get_is_read_only() {
|
||||
bool NIB::get_is_read_only() const {
|
||||
return file_.get_is_known_read_only();
|
||||
}
|
||||
|
||||
long NIB::file_offset(Track::Address address) {
|
||||
long NIB::file_offset(const Track::Address address) const {
|
||||
return long(address.position.as_int()) * track_length;
|
||||
}
|
||||
|
||||
Track::Address NIB::canonical_address(Track::Address address) {
|
||||
Track::Address NIB::canonical_address(const Track::Address address) const {
|
||||
return Track::Address(
|
||||
address.head,
|
||||
HeadPosition(address.position.as_int())
|
||||
);
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> NIB::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> NIB::track_at_position(const Track::Address address) const {
|
||||
static constexpr size_t MinimumSyncByteCount = 4;
|
||||
|
||||
// NIBs contain data for a fixed quantity of integer-position tracks underneath a single head only.
|
||||
|
@ -26,16 +26,16 @@ public:
|
||||
NIB(const std::string &file_name);
|
||||
|
||||
// Implemented to satisfy @c DiskImage.
|
||||
HeadPosition get_maximum_head_position() 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;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
Track::Address canonical_address(Track::Address) const;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks);
|
||||
bool get_is_read_only() const;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address address);
|
||||
long file_offset(Track::Address address);
|
||||
mutable FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address address) const;
|
||||
long file_offset(Track::Address address) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -29,15 +29,15 @@ OricMFMDSK::OricMFMDSK(const std::string &file_name) :
|
||||
throw Error::InvalidFormat;
|
||||
}
|
||||
|
||||
HeadPosition OricMFMDSK::get_maximum_head_position() {
|
||||
HeadPosition OricMFMDSK::get_maximum_head_position() const {
|
||||
return HeadPosition(int(track_count_));
|
||||
}
|
||||
|
||||
int OricMFMDSK::get_head_count() {
|
||||
int OricMFMDSK::get_head_count() const {
|
||||
return int(head_count_);
|
||||
}
|
||||
|
||||
long OricMFMDSK::get_file_offset_for_position(Track::Address address) {
|
||||
long OricMFMDSK::get_file_offset_for_position(Track::Address address) const {
|
||||
int seek_offset = 0;
|
||||
switch(geometry_type_) {
|
||||
case 1:
|
||||
@ -50,7 +50,7 @@ long OricMFMDSK::get_file_offset_for_position(Track::Address address) {
|
||||
return long(seek_offset) * 6400 + 256;
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> OricMFMDSK::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> OricMFMDSK::track_at_position(const Track::Address address) const {
|
||||
PCMSegment segment;
|
||||
{
|
||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||
@ -164,6 +164,6 @@ void OricMFMDSK::set_tracks(const std::map<Track::Address, std::unique_ptr<Track
|
||||
}
|
||||
}
|
||||
|
||||
bool OricMFMDSK::get_is_read_only() {
|
||||
bool OricMFMDSK::get_is_read_only() const {
|
||||
return file_.get_is_known_read_only();
|
||||
}
|
||||
|
@ -28,16 +28,16 @@ public:
|
||||
OricMFMDSK(const std::string &file_name);
|
||||
|
||||
// implemented to satisfy @c DiskImage
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
bool get_is_read_only() final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
bool get_is_read_only() const;
|
||||
|
||||
void set_tracks(const std::map<Track::Address, std::unique_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);
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address address);
|
||||
mutable Storage::FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address address) const;
|
||||
|
||||
uint32_t head_count_;
|
||||
uint32_t track_count_;
|
||||
|
@ -55,14 +55,14 @@ PCBooter::PCBooter(const std::string &file_name) :
|
||||
// as it can also be used to disambiguate FAT12 disks.
|
||||
}
|
||||
|
||||
HeadPosition PCBooter::get_maximum_head_position() {
|
||||
HeadPosition PCBooter::get_maximum_head_position() const {
|
||||
return HeadPosition(track_count_);
|
||||
}
|
||||
|
||||
int PCBooter::get_head_count() {
|
||||
int PCBooter::get_head_count() const {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
long PCBooter::get_file_offset_for_position(Track::Address address) {
|
||||
long PCBooter::get_file_offset_for_position(Track::Address address) const {
|
||||
return (address.position.as_int() * head_count_ + address.head) * 512 * sector_count_;
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ namespace Storage::Disk {
|
||||
class PCBooter: public MFMSectorDump {
|
||||
public:
|
||||
PCBooter(const std::string &file_name);
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
HeadPosition get_maximum_head_position() const final;
|
||||
int get_head_count() const final;
|
||||
|
||||
private:
|
||||
long get_file_offset_for_position(Track::Address address) final;
|
||||
long get_file_offset_for_position(Track::Address address) const final;
|
||||
|
||||
int head_count_;
|
||||
int track_count_;
|
||||
|
@ -32,14 +32,14 @@ SSD::SSD(const std::string &file_name) : MFMSectorDump(file_name) {
|
||||
set_geometry(sectors_per_track, sector_size, 0, Encodings::MFM::Density::Single);
|
||||
}
|
||||
|
||||
HeadPosition SSD::get_maximum_head_position() {
|
||||
HeadPosition SSD::get_maximum_head_position() const {
|
||||
return HeadPosition(track_count_);
|
||||
}
|
||||
|
||||
int SSD::get_head_count() {
|
||||
int SSD::get_head_count() const {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
long SSD::get_file_offset_for_position(Track::Address address) {
|
||||
long SSD::get_file_offset_for_position(const Track::Address address) const {
|
||||
return (address.position.as_int() * head_count_ + address.head) * 256 * 10;
|
||||
}
|
||||
|
@ -25,11 +25,11 @@ public:
|
||||
*/
|
||||
SSD(const std::string &file_name);
|
||||
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
HeadPosition get_maximum_head_position() const final;
|
||||
int get_head_count() const final;
|
||||
|
||||
private:
|
||||
long get_file_offset_for_position(Track::Address address) final;
|
||||
long get_file_offset_for_position(Track::Address address) const final;
|
||||
|
||||
int head_count_;
|
||||
int track_count_;
|
||||
|
@ -440,15 +440,15 @@ STX::STX(const std::string &file_name) : file_(file_name) {
|
||||
}
|
||||
}
|
||||
|
||||
HeadPosition STX::get_maximum_head_position() {
|
||||
HeadPosition STX::get_maximum_head_position() const {
|
||||
return HeadPosition(track_count_ + 1); // Same issue as MSA; must fix!
|
||||
}
|
||||
|
||||
int STX::get_head_count() {
|
||||
int STX::get_head_count() const {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> STX::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> STX::track_at_position(const Track::Address address) const {
|
||||
// These images have two sides, at most.
|
||||
if(address.head > 1) return nullptr;
|
||||
|
||||
|
@ -27,13 +27,13 @@ public:
|
||||
*/
|
||||
STX(const std::string &file_name);
|
||||
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) final;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
mutable FileHolder file_;
|
||||
|
||||
int track_count_;
|
||||
int head_count_;
|
||||
|
@ -107,15 +107,15 @@ WOZ::WOZ(const std::string &file_name) :
|
||||
if(tracks_offset_ == -1 || !has_tmap) throw Error::InvalidFormat;
|
||||
}
|
||||
|
||||
HeadPosition WOZ::get_maximum_head_position() {
|
||||
HeadPosition WOZ::get_maximum_head_position() const {
|
||||
return is_3_5_disk_ ? HeadPosition(80) : HeadPosition(160, 4);
|
||||
}
|
||||
|
||||
int WOZ::get_head_count() {
|
||||
int WOZ::get_head_count() const {
|
||||
return is_3_5_disk_ ? 2 : 1;
|
||||
}
|
||||
|
||||
long WOZ::file_offset(Track::Address address) {
|
||||
long WOZ::file_offset(Track::Address address) const {
|
||||
// Calculate table position.
|
||||
int table_position;
|
||||
if(!is_3_5_disk_) {
|
||||
@ -141,13 +141,13 @@ long WOZ::file_offset(Track::Address address) {
|
||||
}
|
||||
}
|
||||
|
||||
bool WOZ::tracks_differ(Track::Address lhs, Track::Address rhs) {
|
||||
bool WOZ::tracks_differ(Track::Address lhs, Track::Address rhs) const {
|
||||
const long offset1 = file_offset(lhs);
|
||||
const long offset2 = file_offset(rhs);
|
||||
return offset1 != offset2;
|
||||
}
|
||||
|
||||
std::unique_ptr<Track> WOZ::track_at_position(Track::Address address) {
|
||||
std::unique_ptr<Track> WOZ::track_at_position(Track::Address address) const {
|
||||
const long offset = file_offset(address);
|
||||
if(offset == NoSuchTrack) {
|
||||
return nullptr;
|
||||
@ -218,7 +218,7 @@ void WOZ::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tra
|
||||
file_.write(post_crc_contents_);
|
||||
}
|
||||
|
||||
bool WOZ::get_is_read_only() {
|
||||
bool WOZ::get_is_read_only() const {
|
||||
/*
|
||||
There is an unintended issue with the disk code that sits above here: it doesn't understand the idea
|
||||
of multiple addresses mapping to the same track, yet it maintains a cache of track contents. Therefore
|
||||
|
@ -24,15 +24,15 @@ public:
|
||||
WOZ(const std::string &file_name);
|
||||
|
||||
// Implemented to satisfy @c DiskImage.
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() 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;
|
||||
HeadPosition get_maximum_head_position() const;
|
||||
int get_head_count() const;
|
||||
std::unique_ptr<Track> track_at_position(Track::Address) const;
|
||||
void set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tracks);
|
||||
bool get_is_read_only() const;
|
||||
bool tracks_differ(Track::Address, Track::Address) const;
|
||||
|
||||
private:
|
||||
Storage::FileHolder file_;
|
||||
mutable Storage::FileHolder file_;
|
||||
enum class Type {
|
||||
WOZ1, WOZ2
|
||||
} type_ = Type::WOZ1;
|
||||
@ -49,7 +49,7 @@ private:
|
||||
@returns The offset within the file of the track at @c address or @c NoSuchTrack if
|
||||
the track does not exit.
|
||||
*/
|
||||
long file_offset(Track::Address address);
|
||||
long file_offset(Track::Address address) const;
|
||||
constexpr static long NoSuchTrack = 0; // This is an offset a track definitely can't lie at.
|
||||
};
|
||||
|
||||
|
@ -66,6 +66,10 @@ void Drive::set_disk(const std::shared_ptr<Disk> &disk) {
|
||||
update_clocking_observer();
|
||||
}
|
||||
|
||||
const Disk *Drive::disk() const {
|
||||
return disk_.get();
|
||||
}
|
||||
|
||||
bool Drive::has_disk() const {
|
||||
return has_disk_;
|
||||
}
|
||||
|
@ -50,6 +50,11 @@ public:
|
||||
*/
|
||||
void set_disk(const std::shared_ptr<Disk> &disk);
|
||||
|
||||
/*!
|
||||
@returns The attached disk, if any.
|
||||
*/
|
||||
const Disk *disk() const;
|
||||
|
||||
/*!
|
||||
@returns @c true if a disk is currently inserted; @c false otherwise.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user