diff --git a/Storage/Disk/Disk.cpp b/Storage/Disk/Disk.cpp index b2945ce3a..c6b04e0ee 100644 --- a/Storage/Disk/Disk.cpp +++ b/Storage/Disk/Disk.cpp @@ -10,9 +10,23 @@ using namespace Storage::Disk; +int Disk::get_id_for_track_at_position(unsigned int head, unsigned int position) +{ + return (int)(position * get_head_count() + head); +} + +void Disk::set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr &track) +{ + if(!get_is_read_only()) return; + + int address = get_id_for_track_at_position(head, position); + cached_tracks_[address] = track; + modified_tracks_.insert(address); +} + std::shared_ptr Disk::get_track_at_position(unsigned int head, unsigned int position) { - int address = (int)(position * get_head_count() + head); + int address = get_id_for_track_at_position(head, position); std::map>::iterator cached_track = cached_tracks_.find(address); if(cached_track != cached_tracks_.end()) return cached_track->second; @@ -20,3 +34,17 @@ std::shared_ptr Disk::get_track_at_position(unsigned int head, unsigned i cached_tracks_[address] = track; return track; } + +std::shared_ptr Disk::get_modified_track_at_position(unsigned int head, unsigned int position) +{ + int address = get_id_for_track_at_position(head, position); + if(modified_tracks_.find(address) == modified_tracks_.end()) return nullptr; + std::map>::iterator cached_track = cached_tracks_.find(address); + if(cached_track == cached_tracks_.end()) return nullptr; + return cached_track->second; +} + +bool Disk::get_is_modified() +{ + return !modified_tracks_.empty(); +} diff --git a/Storage/Disk/Disk.hpp b/Storage/Disk/Disk.hpp index de18d43fb..514bc0c61 100644 --- a/Storage/Disk/Disk.hpp +++ b/Storage/Disk/Disk.hpp @@ -11,6 +11,7 @@ #include #include +#include #include "../Storage.hpp" namespace Storage { @@ -85,6 +86,18 @@ class Disk { */ std::shared_ptr get_track_at_position(unsigned int head, unsigned int position); + /*! + Replaces the Track at position @c position underneath @c head with @c track. Ignored if this disk is read-only. + Subclasses that are not read-only should use the protected methods @c get_is_modified and, optionally, + @c get_modified_track_at_position to query for changes when closing. + */ + void set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr &track); + + /*! + @returns whether the disk image is read only. Defaults to @c true if not overridden. + */ + virtual bool get_is_read_only() { return true; } + protected: /*! Subclasses should implement this to return the @c Track at @c position underneath @c head. Returned tracks @@ -93,8 +106,20 @@ class Disk { */ virtual std::shared_ptr get_uncached_track_at_position(unsigned int head, unsigned int position) = 0; + /*! + @returns @c true if any calls to set_track_at_position occurred; @c false otherwise. + */ + bool get_is_modified(); + + /*! + @returns the @c Track at @c position underneath @c head if a modification was written there. + */ + std::shared_ptr get_modified_track_at_position(unsigned int head, unsigned int position); + private: std::map> cached_tracks_; + std::set modified_tracks_; + int get_id_for_track_at_position(unsigned int head, unsigned int position); }; } diff --git a/Storage/Disk/Drive.cpp b/Storage/Disk/Drive.cpp index d50371262..0b9fb34cb 100644 --- a/Storage/Disk/Drive.cpp +++ b/Storage/Disk/Drive.cpp @@ -39,8 +39,19 @@ void Drive::set_head(unsigned int head) head_ = head; } +bool Drive::get_is_read_only() +{ + if(disk_) return disk_->get_is_read_only(); + return false; +} + std::shared_ptr Drive::get_track() { if(disk_) return disk_->get_track_at_position(head_, (unsigned int)head_position_); return nullptr; } + +void Drive::set_track(const std::shared_ptr &track) +{ + if(disk_) disk_->set_track_at_position(head_, (unsigned int)head_position_, track); +} diff --git a/Storage/Disk/Drive.hpp b/Storage/Disk/Drive.hpp index 0555b5107..aeeaf95ab 100644 --- a/Storage/Disk/Drive.hpp +++ b/Storage/Disk/Drive.hpp @@ -44,7 +44,10 @@ class Drive { */ void set_head(unsigned int head); + bool get_is_read_only(); + std::shared_ptr get_track(); + void set_track(const std::shared_ptr &track); private: std::shared_ptr disk_;