diff --git a/Components/8272/i8272.cpp b/Components/8272/i8272.cpp index fea0e1094..39a7e9035 100644 --- a/Components/8272/i8272.cpp +++ b/Components/8272/i8272.cpp @@ -119,11 +119,12 @@ void i8272::run_for(Cycles cycles) { // Perform a step. int direction = (drives_[c].target_head_position < drives_[c].head_position) ? -1 : 1; printf("Target %d versus believed %d\n", drives_[c].target_head_position, drives_[c].head_position); - drives_[c].drive->step(direction); + select_drive(c); + get_drive().step(direction); if(drives_[c].target_head_position >= 0) drives_[c].head_position += direction; // Check for completion. - if(drives_[c].seek_is_satisfied()) { + if(seek_is_satisfied(c)) { drives_[c].phase = Drive::CompletedSeeking; drives_seeking_--; break; @@ -192,12 +193,6 @@ uint8_t i8272::get_register(int address) { } } -void i8272::set_disk(std::shared_ptr disk, int drive) { - if(drive < 4 && drive >= 0) { - drives_[drive].drive->set_disk(disk); - } -} - #define BEGIN_SECTION() switch(resume_point_) { default: #define END_SECTION() } @@ -235,7 +230,7 @@ void i8272::set_disk(std::shared_ptr disk, int drive) { #define SET_DRIVE_HEAD_MFM() \ active_drive_ = command_[1]&3; \ active_head_ = (command_[1] >> 2)&1; \ - set_drive(drives_[active_drive_].drive); \ + select_drive(active_drive_); \ get_drive().set_head((unsigned int)active_head_); \ set_is_double_density(command_[0] & 0x40); @@ -503,7 +498,7 @@ void i8272::posit_event(int event_type) { write_data: printf("Write [deleted] data [%02x %02x %02x %02x ... %02x %02x]\n", command_[2], command_[3], command_[4], command_[5], command_[6], command_[8]); - if(drives_[active_drive_].drive->get_is_read_only()) { + if(get_drive().get_is_read_only()) { SetNotWriteable(); goto abort; } @@ -618,7 +613,7 @@ void i8272::posit_event(int event_type) { // Performs format [/write] track. format_track: printf("Format track\n"); - if(drives_[active_drive_].drive->get_is_read_only()) { + if(get_drive().get_is_read_only()) { SetNotWriteable(); goto abort; } @@ -711,6 +706,7 @@ void i8272::posit_event(int event_type) { seek: { int drive = command_[1]&3; + select_drive(drive); // Increment the seeking count if this drive wasn't already seeking. if(drives_[drive].phase != Drive::Seeking) { @@ -740,7 +736,7 @@ void i8272::posit_event(int event_type) { } // Check whether any steps are even needed; if not then mark as completed already. - if(drives_[drive].seek_is_satisfied()) { + if(seek_is_satisfied(drive)) { drives_[drive].phase = Drive::CompletedSeeking; drives_seeking_--; } @@ -792,12 +788,13 @@ void i8272::posit_event(int event_type) { printf("Sense drive status\n"); { int drive = command_[1] & 3; + select_drive(drive); result_stack_.push_back( (command_[1] & 7) | // drive and head number 0x08 | // single sided - (drives_[drive].drive->get_is_track_zero() ? 0x10 : 0x00) | - (drives_[drive].drive->get_is_ready() ? 0x20 : 0x00) | - (drives_[drive].drive->get_is_read_only() ? 0x40 : 0x00) + (get_drive().get_is_track_zero() ? 0x10 : 0x00) | + (get_drive().get_is_ready() ? 0x20 : 0x00) | + (get_drive().get_is_read_only() ? 0x40 : 0x00) ); } goto post_result; @@ -852,9 +849,9 @@ void i8272::posit_event(int event_type) { END_SECTION() } -bool i8272::Drive::seek_is_satisfied() { - return (target_head_position == head_position) || - (target_head_position == -1 && drive->get_is_track_zero()); +bool i8272::seek_is_satisfied(int drive) { + return (drives_[drive].target_head_position == drives_[drive].head_position) || + (drives_[drive].target_head_position == -1 && get_drive().get_is_track_zero()); } void i8272::set_dma_acknowledge(bool dack) { diff --git a/Components/8272/i8272.hpp b/Components/8272/i8272.hpp index 6b01af86d..2edab4e24 100644 --- a/Components/8272/i8272.hpp +++ b/Components/8272/i8272.hpp @@ -39,10 +39,11 @@ class i8272: public Storage::Disk::MFMController { void set_dma_acknowledge(bool dack); void set_terminal_count(bool tc); - void set_disk(std::shared_ptr disk, int drive); - bool is_sleeping(); + protected: + virtual void select_drive(int number) = 0; + private: // The bus handler, for interrupt and DMA-driven usage. BusHandler &bus_handler_; @@ -91,24 +92,20 @@ class i8272: public Storage::Disk::MFMController { int steps_taken; int target_head_position; // either an actual number, or -1 to indicate to step until track zero - /// @returns @c true if the currently queued-up seek or recalibrate has reached where it should be. - bool seek_is_satisfied(); - // Head state. int head_unload_delay[2]; bool head_is_loaded[2]; - // The connected drive. - std::shared_ptr drive; - Drive() : head_position(0), phase(NotSeeking), - drive(new Storage::Disk::Drive(8000000, 300)), // TODO: these constants can't live here. head_is_loaded{false, false}, head_unload_delay{0, 0} {}; } drives_[4]; int drives_seeking_; + /// @returns @c true if the selected drive, which is number @c drive, can stop seeking. + bool seek_is_satisfied(int drive); + // User-supplied parameters; as per the specify command. int step_rate_time_; int head_unload_time_; diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index 534aa2e78..fe46a63c7 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -582,13 +582,25 @@ class KeyboardState: public GI::AY38910::PortHandler { class FDC: public Intel::i8272::i8272 { private: Intel::i8272::BusHandler bus_handler_; + std::shared_ptr drive_; public: - FDC() : i8272(bus_handler_, Cycles(8000000)) {} + FDC() : + i8272(bus_handler_, Cycles(8000000)), + drive_(new Storage::Disk::Drive(8000000, 300)) { + set_drive(drive_); + } void set_motor_on(bool on) { - // TODO: should set all motors on, not 8272.hjust the one active drive. - get_drive().set_motor_on(on); + drive_->set_motor_on(on); + } + + void select_drive(int c) { + // TODO: support more than one drive. + } + + void set_disk(std::shared_ptr disk, int drive) { + drive_->set_disk(disk); } };