From 909685d87d8c04b6d613da565ff7fca283655124 Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Sat, 26 Oct 2019 22:57:05 -0400
Subject: [PATCH] A drive with no disk is now happy to spin its motor.

It'll continue to produce index-hole events, which might not be accurate for 5.25" drives. Research to do.
---
 Storage/Disk/Drive.cpp | 62 +++++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 25 deletions(-)

diff --git a/Storage/Disk/Drive.cpp b/Storage/Disk/Drive.cpp
index e0068ba5d..eab718c70 100644
--- a/Storage/Disk/Drive.cpp
+++ b/Storage/Disk/Drive.cpp
@@ -98,7 +98,7 @@ std::shared_ptr<Track> Drive::step_to(HeadPosition offset) {
 	HeadPosition old_head_position = head_position_;
 	head_position_ = std::max(offset, HeadPosition(0));
 
-	if(head_position_ != old_head_position) {
+	if(disk_ && head_position_ != old_head_position) {
 		track_ = nullptr;
 		setup_track();
 	}
@@ -178,35 +178,39 @@ void Drive::advance(const Cycles cycles) {
 }
 
 void Drive::run_for(const Cycles cycles) {
-	if(has_disk_ && motor_is_on_) {
-		Time zero(0);
+	if(motor_is_on_) {
+		if(has_disk_) {
+			Time zero(0);
 
-		int number_of_cycles = cycles.as_int();
-		while(number_of_cycles) {
-			int cycles_until_next_event = static_cast<int>(get_cycles_until_next_event());
-			int cycles_to_run_for = std::min(cycles_until_next_event, number_of_cycles);
-			if(!is_reading_ && cycles_until_bits_written_ > zero) {
-				int write_cycles_target = cycles_until_bits_written_.get<int>();
-				if(cycles_until_bits_written_.length % cycles_until_bits_written_.clock_rate) write_cycles_target++;
-				cycles_to_run_for = std::min(cycles_to_run_for, write_cycles_target);
-			}
+			int number_of_cycles = cycles.as_int();
+			while(number_of_cycles) {
+				int cycles_until_next_event = static_cast<int>(get_cycles_until_next_event());
+				int cycles_to_run_for = std::min(cycles_until_next_event, number_of_cycles);
+				if(!is_reading_ && cycles_until_bits_written_ > zero) {
+					int write_cycles_target = cycles_until_bits_written_.get<int>();
+					if(cycles_until_bits_written_.length % cycles_until_bits_written_.clock_rate) write_cycles_target++;
+					cycles_to_run_for = std::min(cycles_to_run_for, write_cycles_target);
+				}
 
-			number_of_cycles -= cycles_to_run_for;
-			if(!is_reading_) {
-				if(cycles_until_bits_written_ > zero) {
-					Storage::Time cycles_to_run_for_time(cycles_to_run_for);
-					if(cycles_until_bits_written_ <= cycles_to_run_for_time) {
-						if(event_delegate_) event_delegate_->process_write_completed();
-						if(cycles_until_bits_written_ <= cycles_to_run_for_time)
-							cycles_until_bits_written_.set_zero();
-						else
+				number_of_cycles -= cycles_to_run_for;
+				if(!is_reading_) {
+					if(cycles_until_bits_written_ > zero) {
+						Storage::Time cycles_to_run_for_time(cycles_to_run_for);
+						if(cycles_until_bits_written_ <= cycles_to_run_for_time) {
+							if(event_delegate_) event_delegate_->process_write_completed();
+							if(cycles_until_bits_written_ <= cycles_to_run_for_time)
+								cycles_until_bits_written_.set_zero();
+							else
+								cycles_until_bits_written_ -= cycles_to_run_for_time;
+						} else {
 							cycles_until_bits_written_ -= cycles_to_run_for_time;
-					} else {
-						cycles_until_bits_written_ -= cycles_to_run_for_time;
+						}
 					}
 				}
+				TimedEventLoop::run_for(Cycles(cycles_to_run_for));
 			}
-			TimedEventLoop::run_for(Cycles(cycles_to_run_for));
+		} else {
+			TimedEventLoop::run_for(cycles);
 		}
 	}
 }
@@ -214,6 +218,13 @@ void Drive::run_for(const Cycles cycles) {
 // MARK: - Track timed event loop
 
 void Drive::get_next_event(float duration_already_passed) {
+	if(!disk_) {
+		current_event_.type = Track::Event::IndexHole;
+		current_event_.length = 1.0f;
+		set_next_event_time_interval((current_event_.length - duration_already_passed) * rotational_multiplier_);
+		return;
+	}
+
 	// Grab a new track if not already in possession of one. This will recursively call get_next_event,
 	// supplying a proper duration_already_passed.
 	if(!track_) {
@@ -322,7 +333,8 @@ void Drive::invalidate_track() {
 
 void Drive::begin_writing(Time bit_length, bool clamp_to_index_hole) {
 	// Do nothing if already writing.
-	if(!is_reading_) return;
+	// TODO: cope properly if there's no disk to write to.
+	if(!is_reading_ || !disk_) return;
 
 	// Get a copy of the track if that hasn't happened yet.
 	if(!track_) {