diff --git a/Machines/Oric/BD500.cpp b/Machines/Oric/BD500.cpp index e8c3df0b7..638870b33 100644 --- a/Machines/Oric/BD500.cpp +++ b/Machines/Oric/BD500.cpp @@ -10,7 +10,7 @@ using namespace Oric; -BD500::BD500() : DiskController(P1793, 9000000) { +BD500::BD500() : DiskController(P1793, 9000000, Storage::Disk::Drive::ReadyType::ShugartModifiedRDY) { disable_basic_rom_ = true; select_paged_item(); set_is_double_density(true); diff --git a/Machines/Oric/DiskController.hpp b/Machines/Oric/DiskController.hpp index 7ffa2614b..4bfa0e4d8 100644 --- a/Machines/Oric/DiskController.hpp +++ b/Machines/Oric/DiskController.hpp @@ -13,13 +13,13 @@ namespace Oric { class DiskController: public WD::WD1770 { public: - DiskController(WD::WD1770::Personality personality, int clock_rate) : - WD::WD1770(personality), clock_rate_(clock_rate) {} + DiskController(WD::WD1770::Personality personality, int clock_rate, Storage::Disk::Drive::ReadyType ready_type) : + WD::WD1770(personality), clock_rate_(clock_rate), ready_type_(ready_type) {} void set_disk(std::shared_ptr disk, int d) { const size_t drive = size_t(d); if(!drives_[drive]) { - drives_[drive] = std::make_unique(clock_rate_, 300, 2); + drives_[drive] = std::make_unique(clock_rate_, 300, 2, ready_type_); if(drive == selected_drive_) set_drive(drives_[drive]); } drives_[drive]->set_disk(disk); @@ -67,6 +67,7 @@ class DiskController: public WD::WD1770 { private: PagedItem paged_item_ = PagedItem::DiskROM; int clock_rate_; + Storage::Disk::Drive::ReadyType ready_type_; inline void set_paged_item(PagedItem item) { if(paged_item_ == item) return; diff --git a/Machines/Oric/Jasmin.cpp b/Machines/Oric/Jasmin.cpp index 502953364..7aec9f014 100644 --- a/Machines/Oric/Jasmin.cpp +++ b/Machines/Oric/Jasmin.cpp @@ -12,7 +12,7 @@ using namespace Oric; // NB: there's some controversy here on WD1770 versus WD1772, but between those two I think // the only difference is stepping rates, and it says 1770 on the schematic I'm looking at. -Jasmin::Jasmin() : DiskController(P1770, 8000000) { +Jasmin::Jasmin() : DiskController(P1770, 8000000, Storage::Disk::Drive::ReadyType::ShugartRDY) { set_is_double_density(true); select_paged_item(); } diff --git a/Machines/Oric/Microdisc.cpp b/Machines/Oric/Microdisc.cpp index 02ba46e4e..11c5e2e64 100644 --- a/Machines/Oric/Microdisc.cpp +++ b/Machines/Oric/Microdisc.cpp @@ -18,7 +18,7 @@ namespace { const Cycles::IntType head_load_request_counter_target = 7653333; } -Microdisc::Microdisc() : DiskController(P1793, 8000000) { +Microdisc::Microdisc() : DiskController(P1793, 8000000, Storage::Disk::Drive::ReadyType::ShugartRDY) { set_control_register(last_control_, 0xff); } diff --git a/Storage/Disk/Drive.cpp b/Storage/Disk/Drive.cpp index 261ba711d..39fa5f9ae 100644 --- a/Storage/Disk/Drive.cpp +++ b/Storage/Disk/Drive.cpp @@ -18,9 +18,10 @@ using namespace Storage::Disk; -Drive::Drive(int input_clock_rate, int revolutions_per_minute, int number_of_heads): +Drive::Drive(int input_clock_rate, int revolutions_per_minute, int number_of_heads, ReadyType rdy_type): Storage::TimedEventLoop(input_clock_rate), - available_heads_(number_of_heads) { + available_heads_(number_of_heads), + ready_type_(rdy_type) { set_rotation_speed(revolutions_per_minute); const auto seed = static_cast(std::chrono::system_clock::now().time_since_epoch().count()); @@ -35,7 +36,7 @@ Drive::Drive(int input_clock_rate, int revolutions_per_minute, int number_of_hea } } -Drive::Drive(int input_clock_rate, int number_of_heads) : Drive(input_clock_rate, 300, number_of_heads) {} +Drive::Drive(int input_clock_rate, int number_of_heads, ReadyType rdy_type) : Drive(input_clock_rate, 300, number_of_heads, rdy_type) {} void Drive::set_rotation_speed(float revolutions_per_minute) { // Rationalise the supplied speed so that cycles_per_revolution_ is exact. @@ -54,6 +55,9 @@ Drive::~Drive() { } void Drive::set_disk(const std::shared_ptr &disk) { + if(ready_type_ == ReadyType::ShugartModifiedRDY || ready_type_ == ReadyType::IBMRDY) { + is_ready_ = false; + } if(disk_) disk_->flush_tracks(); disk_ = disk; has_disk_ = !!disk_; @@ -76,6 +80,10 @@ bool Drive::get_is_track_zero() const { } void Drive::step(HeadPosition offset) { + if(ready_type_ == ReadyType::IBMRDY) { + is_ready_ = true; + } + HeadPosition old_head_position = head_position_; head_position_ += offset; if(head_position_ < HeadPosition(0)) { @@ -142,7 +150,7 @@ bool Drive::get_is_read_only() const { } bool Drive::get_is_ready() const { - return ready_index_count_ == 2; + return is_ready_; } void Drive::set_motor_on(bool motor_is_on) { @@ -303,7 +311,10 @@ void Drive::get_next_event(float duration_already_passed) { void Drive::process_next_event() { if(current_event_.type == Track::Event::IndexHole) { - if(ready_index_count_ < 2) ready_index_count_++; + ++ready_index_count_; + if(ready_index_count_ == 2 && (ready_type_ == ReadyType::ShugartRDY || ready_type_ == ReadyType::ShugartModifiedRDY)) { + is_ready_ = true; + } cycles_since_index_hole_ = 0; } if( @@ -427,6 +438,9 @@ void Drive::set_disk_is_rotating(bool is_rotating) { } if(!is_rotating) { + if(ready_type_ == ReadyType::ShugartRDY) { + is_ready_ = false; + } ready_index_count_ = 0; if(disk_) disk_->flush_tracks(); } diff --git a/Storage/Disk/Drive.hpp b/Storage/Disk/Drive.hpp index c568a399f..573e7b363 100644 --- a/Storage/Disk/Drive.hpp +++ b/Storage/Disk/Drive.hpp @@ -24,12 +24,21 @@ namespace Disk { class Drive: public ClockingHint::Source, public TimedEventLoop { public: - Drive(int input_clock_rate, int revolutions_per_minute, int number_of_heads); - Drive(int input_clock_rate, int number_of_heads); + enum class ReadyType { + /// Indicates that RDY will go active when the motor is on and two index holes have passed; it will go inactive when the motor is off. + ShugartRDY, + /// Indicates that RDY will go active when the motor is on and two index holes have passed; it will go inactive when the disk is ejected. + ShugartModifiedRDY, + /// Indicates that RDY will go active when the head steps; it will go inactive when the disk is ejected. + IBMRDY, + }; + + Drive(int input_clock_rate, int revolutions_per_minute, int number_of_heads, ReadyType rdy_type = ReadyType::ShugartRDY); + Drive(int input_clock_rate, int number_of_heads, ReadyType rdy_type = ReadyType::ShugartRDY); ~Drive(); /*! - Replaces whatever is in the drive with @c disk. + Replaces whatever is in the drive with @c disk. Supply @c nullptr to eject any current disk and leave none inserted. */ void set_disk(const std::shared_ptr &disk); @@ -232,8 +241,10 @@ class Drive: public ClockingHint::Source, public TimedEventLoop { PCMSegment write_segment_; Time write_start_time_; - // Indicates progress towards drive ready state. + // Indicates progress towards Shugart-style drive ready states. int ready_index_count_ = 0; + ReadyType ready_type_; + bool is_ready_ = false; // Maintains appropriate counting to know when to indicate that writing // is complete.