diff --git a/Components/DiskII/DiskII.cpp b/Components/DiskII/DiskII.cpp index 8669829fd..6a4b90b60 100644 --- a/Components/DiskII/DiskII.cpp +++ b/Components/DiskII/DiskII.cpp @@ -39,11 +39,9 @@ void DiskII::set_control(Control control, bool on) { case Control::Motor: motor_is_enabled_ = on; drives_[active_drive_].set_motor_on(on); - break; + return; } -// printf("%0x: Set control %d %s\n", stepper_mask_, control, on ? "on" : "off"); - // If the stepper magnet selections have changed, and any is on, see how // that moves the head. if(previous_stepper_mask ^ stepper_mask_ && stepper_mask_) { @@ -63,14 +61,7 @@ void DiskII::set_control(Control control, bool on) { } } -void DiskII::set_mode(Mode mode) { -// printf("Set mode %d\n", mode); - inputs_ = (inputs_ & ~input_mode) | ((mode == Mode::Write) ? input_mode : 0); - set_controller_can_sleep(); -} - void DiskII::select_drive(int drive) { -// printf("Select drive %d\n", drive); if((drive&1) == active_drive_) return; drives_[active_drive_].set_event_delegate(this); @@ -81,20 +72,6 @@ void DiskII::select_drive(int drive) { drives_[active_drive_].set_motor_on(motor_is_enabled_); } -void DiskII::set_data_register(uint8_t value) { -// printf("Set data register (?)\n"); - inputs_ |= input_command; - shift_register_ = value; - set_controller_can_sleep(); -} - -uint8_t DiskII::get_shift_register() { -// if(shift_register_ & 0x80) printf("[%02x] ", shift_register_); - inputs_ &= ~input_command; - set_controller_can_sleep(); - return shift_register_; -} - void DiskII::run_for(const Cycles cycles) { if(is_sleeping()) return; @@ -124,11 +101,7 @@ void DiskII::run_for(const Cycles cycles) { return; } break; - case 0xb: - // load data register from data bus... - printf("TODO\n"); - // shift_register_ = data_register_; - break; // load + case 0xb: shift_register_ = data_input_; break; // load data register from data bus } // TODO: surely there's a less heavyweight solution than this? @@ -221,15 +194,11 @@ bool DiskII::is_sleeping() { return controller_can_sleep_ && drive_is_sleeping_[0] && drive_is_sleeping_[1]; } -void DiskII::set_register(int address, uint8_t value) { - trigger_address(address, value); +void DiskII::set_data_input(uint8_t input) { + data_input_ = input; } -uint8_t DiskII::get_register(int address) { - return trigger_address(address, 0xff); -} - -uint8_t DiskII::trigger_address(int address, uint8_t value) { +int DiskII::read_address(int address) { switch(address & 0xf) { default: case 0x0: set_control(Control::P0, false); break; @@ -241,22 +210,19 @@ uint8_t DiskII::trigger_address(int address, uint8_t value) { case 0x6: set_control(Control::P3, false); break; case 0x7: set_control(Control::P3, true); break; - case 0x8: set_control(Control::Motor, false); break; + case 0x8: + shift_register_ = 0; + set_control(Control::Motor, false); + break; case 0x9: set_control(Control::Motor, true); break; case 0xa: select_drive(0); break; case 0xb: select_drive(1); break; - case 0xc: - inputs_ &= ~input_command; - break; - case 0xd: set_data_register(value); break; - - case 0xe: - set_mode(Mode::Read); - break; -// return shift_register_; - case 0xf: set_mode(Mode::Write); break; + case 0xc: inputs_ &= ~input_command; break; + case 0xd: inputs_ |= input_command; break; + case 0xe: inputs_ &= ~input_mode; break; + case 0xf: inputs_ |= input_mode; break; } set_controller_can_sleep(); return (address & 1) ? 0xff : shift_register_; diff --git a/Components/DiskII/DiskII.hpp b/Components/DiskII/DiskII.hpp index 14a714b71..f85a5ab49 100644 --- a/Components/DiskII/DiskII.hpp +++ b/Components/DiskII/DiskII.hpp @@ -33,15 +33,48 @@ class DiskII: public: DiskII(); - void set_register(int address, uint8_t value); - uint8_t get_register(int address); + /// Sets the current external value of the data bus. + void set_data_input(uint8_t input); + /*! + Submits an access to address @c address. + + @returns The 8-bit value loaded to the data bus by the DiskII if any; + @c DidNotLoad otherwise. + */ + int read_address(int address); + + /*! + The value returned by @c read_address if accessing that address + didn't cause the disk II to place anything onto the bus. + */ + const int DidNotLoad = -1; + + /// Advances the controller by @c cycles. void run_for(const Cycles cycles); + + /*! + Supplies the image of the state machine (i.e. P6) ROM, + which dictates how the Disk II will respond to input. + + To reduce processing costs, some assumptions are made by + the implementation as to the content of this ROM. + Including: + + If Q6 is set and Q7 is reset, the controller is testing + for write protect. If and when the shift register has + become full with the state of the write protect value, + no further processing is required. + */ void set_state_machine(const std::vector &); + /// Inserts @c disk into the drive @c drive. void set_disk(const std::shared_ptr &disk, int drive); + + // As per Sleeper. bool is_sleeping() override; + // The Disk II functions as a potential target for @c Activity::Sources. void set_activity_observer(Activity::Observer *observer); private: @@ -55,8 +88,6 @@ class DiskII: void set_control(Control control, bool on); void set_mode(Mode mode); void select_drive(int drive); - void set_data_register(uint8_t value); - uint8_t get_shift_register(); uint8_t trigger_address(int address, uint8_t value); void process_event(const Storage::Disk::Track::Event &event) override; @@ -78,6 +109,8 @@ class DiskII: bool motor_is_enabled_ = false; void set_controller_can_sleep(); + + uint8_t data_input_ = 0; }; } diff --git a/Machines/AppleII/DiskIICard.cpp b/Machines/AppleII/DiskIICard.cpp index e1447d6cc..6a0fb6c0f 100644 --- a/Machines/AppleII/DiskIICard.cpp +++ b/Machines/AppleII/DiskIICard.cpp @@ -25,10 +25,12 @@ void DiskIICard::perform_bus_operation(CPU::MOS6502::BusOperation operation, uin if(address < 0x100) { if(isReadOperation(operation)) *value = boot_[address]; } else { + // TODO: data input really shouldn't happen only upon a write. + diskii_.set_data_input(*value); + const int disk_value = diskii_.read_address(address); if(isReadOperation(operation)) { - *value = diskii_.get_register(address); - } else { - diskii_.set_register(address, *value); + if(disk_value != diskii_.DidNotLoad) + *value = static_cast(disk_value); } } } diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 43d1dfcc7..b37124de4 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -405,9 +405,8 @@ template class Co } } } else { - update_diskii(); - if(isReadOperation(operation)) *value = diskii_.get_register(address); - else diskii_.set_register(address, *value); + const int disk_value = diskii_.read_address(address); + if(isReadOperation(operation) && disk_value != diskii_.DidNotLoad) *value = static_cast(disk_value); } break; } @@ -436,8 +435,13 @@ template class Co tape_player_.run_for(Cycles(1)); switch(disk_interface) { default: break; - case Analyser::Static::Oric::Target::DiskInterface::Microdisc: microdisc_.run_for(Cycles(8)); break; - case Analyser::Static::Oric::Target::DiskInterface::Pravetz: cycles_since_diskii_update_ += 2; break; + case Analyser::Static::Oric::Target::DiskInterface::Microdisc: + microdisc_.run_for(Cycles(8)); + break; + case Analyser::Static::Oric::Target::DiskInterface::Pravetz: + diskii_.set_data_input(*value); + diskii_.run_for(Cycles(2)); + break; } cycles_since_video_update_++; return Cycles(1); @@ -446,7 +450,6 @@ template class Co forceinline void flush() { update_video(); via_port_handler_.flush(); - if(disk_interface == Analyser::Static::Oric::Target::DiskInterface::Pravetz) update_diskii(); } // to satisfy CRTMachine::Machine @@ -605,10 +608,10 @@ template class Co Apple::DiskII diskii_; std::vector pravetz_rom_; std::size_t pravetz_rom_base_pointer_ = 0; - Cycles cycles_since_diskii_update_; - void update_diskii() { - diskii_.run_for(cycles_since_diskii_update_.flush()); - } +// Cycles cycles_since_diskii_update_; +// void update_diskii() { +// diskii_.run_for(cycles_since_diskii_update_.flush()); +// } // Overlay RAM uint16_t ram_top_ = basic_visible_ram_top_; diff --git a/Storage/Disk/DiskImage/Formats/AppleDSK.hpp b/Storage/Disk/DiskImage/Formats/AppleDSK.hpp index 3e5ad3321..fb17f359e 100644 --- a/Storage/Disk/DiskImage/Formats/AppleDSK.hpp +++ b/Storage/Disk/DiskImage/Formats/AppleDSK.hpp @@ -35,6 +35,9 @@ class AppleDSK: public DiskImage { HeadPosition get_maximum_head_position() override; std::shared_ptr get_track_at_position(Track::Address address) override; + // TEST! + bool get_is_read_only() override { return false; } + private: Storage::FileHolder file_; int sectors_per_track_ = 16;