diff --git a/Components/1770/1770.cpp b/Components/1770/1770.cpp index 6e2011f45..168dfb817 100644 --- a/Components/1770/1770.cpp +++ b/Components/1770/1770.cpp @@ -124,10 +124,11 @@ uint8_t WD1770::get_register(int address) { } } -void WD1770::run_for_cycles(unsigned int number_of_cycles) { - Storage::Disk::Controller::run_for_cycles((int)number_of_cycles); +void WD1770::run_for(const Cycles &cycles) { + Storage::Disk::Controller::run_for(cycles); if(delay_time_) { + unsigned int number_of_cycles = (unsigned int)cycles.as_int(); if(delay_time_ <= number_of_cycles) { delay_time_ = 0; posit_event(Event::Timer); diff --git a/Components/1770/1770.hpp b/Components/1770/1770.hpp index 507393946..0272a74d5 100644 --- a/Components/1770/1770.hpp +++ b/Components/1770/1770.hpp @@ -11,6 +11,7 @@ #include "../../Storage/Disk/DiskController.hpp" #include "../../NumberTheory/CRC.hpp" +#include "../ClockReceiver.hpp" namespace WD { @@ -18,7 +19,7 @@ namespace WD { Provides an emulation of various Western Digital drive controllers, including the WD1770, WD1772, FDC1773 and FDC1793. */ -class WD1770: public Storage::Disk::Controller { +class WD1770: public ClockReceiver, public Storage::Disk::Controller { public: enum Personality { P1770, // implies automatic motor-on management, with Type 2 commands offering a spin-up disable @@ -43,7 +44,7 @@ class WD1770: public Storage::Disk::Controller { uint8_t get_register(int address); /// Runs the controller for @c number_of_cycles cycles. - void run_for_cycles(unsigned int number_of_cycles); + void run_for(const Cycles &cycles); enum Flag: uint8_t { NotReady = 0x80, diff --git a/Machines/Commodore/1540/C1540.cpp b/Machines/Commodore/1540/C1540.cpp index ae3266038..8e379ee37 100644 --- a/Machines/Commodore/1540/C1540.cpp +++ b/Machines/Commodore/1540/C1540.cpp @@ -83,7 +83,7 @@ void Machine::run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor::run_for(Cycles(number_of_cycles)); set_motor_on(drive_VIA_.get_motor_enabled()); if(drive_VIA_.get_motor_enabled()) // TODO: motor speed up/down - Storage::Disk::Controller::run_for_cycles(number_of_cycles); + Storage::Disk::Controller::run_for(Cycles(number_of_cycles)); } #pragma mark - 6522 delegate diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 67513e38a..dc85fbc32 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -187,7 +187,7 @@ unsigned int Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation typer_.reset(); } } - tape_->run_for_cycles(1); + tape_->run_for(Cycles(1)); if(c1540_) c1540_->run_for_cycles(1); return 1; diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 7441c7f90..f27e26ce6 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -329,7 +329,7 @@ unsigned int Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation } if(typer_) typer_->update((int)cycles); - if(plus3_) plus3_->run_for_cycles(4*cycles); + if(plus3_) plus3_->run_for(Cycles(4*(int)cycles)); if(shift_restart_counter_) { shift_restart_counter_ -= cycles; if(shift_restart_counter_ <= 0) { diff --git a/Machines/Electron/Tape.cpp b/Machines/Electron/Tape.cpp index 4d0d37959..a328bc23d 100644 --- a/Machines/Electron/Tape.cpp +++ b/Machines/Electron/Tape.cpp @@ -84,7 +84,7 @@ void Tape::run_for_cycles(unsigned int number_of_cycles) { if(is_enabled_) { if(is_in_input_mode_) { if(is_running_) { - TapePlayer::run_for_cycles((int)number_of_cycles); + TapePlayer::run_for(Cycles((int)number_of_cycles)); } } else { output_.cycles_into_pulse += number_of_cycles; diff --git a/Machines/Oric/Microdisc.cpp b/Machines/Oric/Microdisc.cpp index f9bed5a0e..e5f248fbc 100644 --- a/Machines/Oric/Microdisc.cpp +++ b/Machines/Oric/Microdisc.cpp @@ -109,7 +109,7 @@ void Microdisc::run_for_cycles(unsigned int number_of_cycles) { head_load_request_counter_ += number_of_cycles; if(head_load_request_counter_ >= head_load_request_counter_target) set_head_loaded(true); } - WD::WD1770::run_for_cycles(number_of_cycles); + WD::WD1770::run_for(Cycles((int)number_of_cycles)); } bool Microdisc::get_drive_is_ready() { diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 8c4a6d52f..3dd709834 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -243,7 +243,7 @@ void Machine::VIA::flush() { void Machine::VIA::run_for_cycles(unsigned int number_of_cycles) { cycles_since_ay_update_ += number_of_cycles; MOS::MOS6522::run_for_cycles(number_of_cycles); - tape->run_for_cycles((int)number_of_cycles); + tape->run_for(Cycles((int)number_of_cycles)); } void Machine::VIA::update_ay() { diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index 5641ee94b..8c6dc32d8 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -55,7 +55,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { if(is_zx81_) horizontal_counter_ %= HalfCycles(Cycles(207)); if(!tape_advance_delay_) { - tape_player_.run_for_cycles(cycle.length.as_int()); + tape_player_.run_for(cycle.length); } else { tape_advance_delay_ = std::max(tape_advance_delay_ - cycle.length, HalfCycles(0)); } diff --git a/StaticAnalyser/Commodore/Disk.cpp b/StaticAnalyser/Commodore/Disk.cpp index fa54e613c..37c89c015 100644 --- a/StaticAnalyser/Commodore/Disk.cpp +++ b/StaticAnalyser/Commodore/Disk.cpp @@ -78,13 +78,13 @@ class CommodoreGCRParser: public Storage::Disk::Controller { // find end of lead-in while(shift_register_ == 0x3ff && index_count_ < 2) { - run_for_cycles(1); + run_for(Cycles(1)); } // continue for a further nine bits bit_count_ = 0; while(bit_count_ < 9 && index_count_ < 2) { - run_for_cycles(1); + run_for(Cycles(1)); } return Storage::Encodings::CommodoreGCR::decoding_from_dectet(shift_register_); @@ -92,14 +92,14 @@ class CommodoreGCRParser: public Storage::Disk::Controller { unsigned int get_next_byte() { bit_count_ = 0; - while(bit_count_ < 10) run_for_cycles(1); + while(bit_count_ < 10) run_for(Cycles(1)); return Storage::Encodings::CommodoreGCR::decoding_from_dectet(shift_register_); } void proceed_to_shift_value(unsigned int shift_value) { index_count_ = 0; while(shift_register_ != shift_value && index_count_ < 2) { - run_for_cycles(1); + run_for(Cycles(1)); } } diff --git a/Storage/Disk/DiskController.cpp b/Storage/Disk/DiskController.cpp index 675be3403..2c48b7541 100644 --- a/Storage/Disk/DiskController.cpp +++ b/Storage/Disk/DiskController.cpp @@ -75,7 +75,7 @@ void Controller::run_for(const Cycles &cycles) { } } } - TimedEventLoop::run_for_cycles(cycles_to_run_for); + TimedEventLoop::run_for(Cycles(cycles_to_run_for)); } } } diff --git a/Storage/Disk/Encodings/MFM.cpp b/Storage/Disk/Encodings/MFM.cpp index 33c69e0b3..1aa908e15 100644 --- a/Storage/Disk/Encodings/MFM.cpp +++ b/Storage/Disk/Encodings/MFM.cpp @@ -294,7 +294,7 @@ uint8_t Parser::get_byte_for_shift_value(uint16_t value) { uint8_t Parser::get_next_byte() { bit_count_ = 0; - while(bit_count_ < 16) run_for_cycles(1); + while(bit_count_ < 16) run_for(Cycles(1)); uint8_t byte = get_byte_for_shift_value((uint16_t)shift_register_); crc_generator_.add(byte); return byte; @@ -309,7 +309,7 @@ std::vector Parser::get_track() { // align to the next index hole index_count_ = 0; - while(!index_count_) run_for_cycles(1); + while(!index_count_) run_for(Cycles(1)); // capture every other bit until the next index hole index_count_ = 0; @@ -319,7 +319,7 @@ std::vector Parser::get_track() { bool found_sync = false; while(!index_count_ && !found_sync && bit_count_ < 16) { int previous_bit_count = bit_count_; - run_for_cycles(1); + run_for(Cycles(1)); if(!distance_until_permissible_sync && bit_count_ != previous_bit_count) { uint16_t low_shift_register = (shift_register_&0xffff); @@ -393,7 +393,7 @@ std::shared_ptr Parser::get_next_sector() // look for an ID address mark bool id_found = false; while(!id_found) { - run_for_cycles(1); + run_for(Cycles(1)); if(is_mfm_) { while(shift_register_ == MFMSync) { uint8_t mark = get_next_byte(); @@ -424,7 +424,7 @@ std::shared_ptr Parser::get_next_sector() // look for data mark bool data_found = false; while(!data_found) { - run_for_cycles(1); + run_for(Cycles(1)); if(is_mfm_) { while(shift_register_ == MFMSync) { uint8_t mark = get_next_byte(); diff --git a/Storage/Tape/Tape.cpp b/Storage/Tape/Tape.cpp index e0e3e81e3..8cb536557 100644 --- a/Storage/Tape/Tape.cpp +++ b/Storage/Tape/Tape.cpp @@ -92,9 +92,9 @@ void TapePlayer::get_next_pulse() { set_next_event_time_interval(current_pulse_.length); } -void TapePlayer::run_for_cycles(int number_of_cycles) { +void TapePlayer::run_for(const Cycles &cycles) { if(has_tape()) { - TimedEventLoop::run_for_cycles(number_of_cycles); + TimedEventLoop::run_for(cycles); } } @@ -125,8 +125,8 @@ bool BinaryTapePlayer::get_input() { return motor_is_running_ && input_level_; } -void BinaryTapePlayer::run_for_cycles(int number_of_cycles) { - if(motor_is_running_) TapePlayer::run_for_cycles(number_of_cycles); +void BinaryTapePlayer::run_for(const Cycles &cycles) { + if(motor_is_running_) TapePlayer::run_for(cycles); } void BinaryTapePlayer::set_delegate(Delegate *delegate) { diff --git a/Storage/Tape/Tape.hpp b/Storage/Tape/Tape.hpp index 6f72ee4f7..f978fb55e 100644 --- a/Storage/Tape/Tape.hpp +++ b/Storage/Tape/Tape.hpp @@ -11,6 +11,7 @@ #include #include "../TimedEventLoop.hpp" +#include "../../Components/ClockReceiver.hpp" namespace Storage { namespace Tape { @@ -91,7 +92,7 @@ class Tape { Will call @c process_input_pulse instantaneously upon reaching *the end* of a pulse. Therefore a subclass can decode pulses into data within process_input_pulse, using the supplied pulse's @c length and @c type. */ -class TapePlayer: public TimedEventLoop { +class TapePlayer: public ClockReceiver, public TimedEventLoop { public: TapePlayer(unsigned int input_clock_rate); @@ -99,7 +100,7 @@ class TapePlayer: public TimedEventLoop { bool has_tape(); std::shared_ptr get_tape(); - void run_for_cycles(int number_of_cycles); + void run_for(const Cycles &cycles); void run_for_input_pulse(); protected: @@ -121,14 +122,14 @@ class TapePlayer: public TimedEventLoop { They can also provide a delegate to be notified upon any change in the input level. */ -class BinaryTapePlayer: public TapePlayer { +class BinaryTapePlayer: public ClockReceiver, public TapePlayer { public: BinaryTapePlayer(unsigned int input_clock_rate); void set_motor_control(bool enabled); void set_tape_output(bool set); bool get_input(); - void run_for_cycles(int number_of_cycles); + void run_for(const Cycles &cycles); class Delegate { public: diff --git a/Storage/TimedEventLoop.cpp b/Storage/TimedEventLoop.cpp index 25cb2456d..9587a550c 100644 --- a/Storage/TimedEventLoop.cpp +++ b/Storage/TimedEventLoop.cpp @@ -15,8 +15,8 @@ using namespace Storage; TimedEventLoop::TimedEventLoop(unsigned int input_clock_rate) : input_clock_rate_(input_clock_rate) {} -void TimedEventLoop::run_for_cycles(int number_of_cycles) { - cycles_until_event_ -= number_of_cycles; +void TimedEventLoop::run_for(const Cycles &cycles) { + cycles_until_event_ -= cycles.as_int(); while(cycles_until_event_ <= 0) { process_next_event(); } diff --git a/Storage/TimedEventLoop.hpp b/Storage/TimedEventLoop.hpp index cd4e3af42..e2cee9a0f 100644 --- a/Storage/TimedEventLoop.hpp +++ b/Storage/TimedEventLoop.hpp @@ -13,6 +13,7 @@ #include #include "../SignalProcessing/Stepper.hpp" +#include "../Components/ClockReceiver.hpp" namespace Storage { @@ -36,7 +37,7 @@ namespace Storage { @c reset_timer to initiate a distinctly-timed stream or @c jump_to_next_event to short-circuit the timing loop and fast forward immediately to the next event. */ - class TimedEventLoop { + class TimedEventLoop: public ClockReceiver { public: /*! Constructs a timed event loop that will be clocked at @c input_clock_rate. @@ -46,7 +47,7 @@ namespace Storage { /*! Advances the event loop by @c number_of_cycles cycles. */ - void run_for_cycles(int number_of_cycles); + void run_for(const Cycles &cycles); /*! @returns the number of whole cycles remaining until the next event is triggered.