diff --git a/Components/DiskII/DiskII.cpp b/Components/DiskII/DiskII.cpp index bc2a5b9e0..31a3455f8 100644 --- a/Components/DiskII/DiskII.cpp +++ b/Components/DiskII/DiskII.cpp @@ -19,7 +19,7 @@ namespace { } DiskII::DiskII() : - drives_{{2045454, 300, 1}, {2045454, 300, 1}} + drives_{{2000000, 300, 1}, {2045454, 300, 1}} { } diff --git a/Storage/Disk/Controller/DiskController.cpp b/Storage/Disk/Controller/DiskController.cpp index c37f0d8c7..e6788c873 100644 --- a/Storage/Disk/Controller/DiskController.cpp +++ b/Storage/Disk/Controller/DiskController.cpp @@ -66,7 +66,7 @@ void Controller::set_expected_bit_length(Time bit_length) { // this conversion doesn't need to be exact because there's a lot of variation to be taken // account of in rotation speed, air turbulence, etc, so a direct conversion will do - int clocks_per_bit = static_cast(cycles_per_bit.get_unsigned_int()); + int clocks_per_bit = cycles_per_bit.get(); pll_.reset(new DigitalPhaseLockedLoop(clocks_per_bit, 3)); pll_->set_delegate(this); } diff --git a/Storage/Disk/Drive.cpp b/Storage/Disk/Drive.cpp index f32cb31f7..66ce42233 100644 --- a/Storage/Disk/Drive.cpp +++ b/Storage/Disk/Drive.cpp @@ -117,7 +117,7 @@ void Drive::run_for(const Cycles cycles) { int cycles_until_next_event = static_cast(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 = static_cast(cycles_until_bits_written_.get_unsigned_int()); + int write_cycles_target = cycles_until_bits_written_.get(); 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); } @@ -168,7 +168,6 @@ void Drive::get_next_event(const Time &duration_already_passed) { } void Drive::process_next_event() { - // TODO: ready test here. if(current_event_.type == Track::Event::IndexHole) { // assert(get_time_into_track() == Time(1) || get_time_into_track() == Time(0)); if(ready_index_count_ < 2) ready_index_count_++; diff --git a/Storage/Disk/Track/PCMSegment.cpp b/Storage/Disk/Track/PCMSegment.cpp index ee7ea3b01..da07e0248 100644 --- a/Storage/Disk/Track/PCMSegment.cpp +++ b/Storage/Disk/Track/PCMSegment.cpp @@ -106,7 +106,7 @@ Storage::Time PCMSegmentEventSource::seek_to(const Time &time_from_start) { // bit_pointer_ always records _the next bit_ that might trigger an event, // so should be one beyond the one reached by a seek. Time relative_time = time_from_start - half_bit_length; - bit_pointer_ = 1 + (relative_time / segment_->length_of_a_bit).get_unsigned_int(); + bit_pointer_ = 1 + (relative_time / segment_->length_of_a_bit).get(); // map up to the correct amount of time return half_bit_length + segment_->length_of_a_bit * static_cast(bit_pointer_ - 1); diff --git a/Storage/Disk/Track/TrackSerialiser.cpp b/Storage/Disk/Track/TrackSerialiser.cpp index af7b0a387..be67dba35 100644 --- a/Storage/Disk/Track/TrackSerialiser.cpp +++ b/Storage/Disk/Track/TrackSerialiser.cpp @@ -40,7 +40,7 @@ Storage::Disk::PCMSegment Storage::Disk::track_serialisation(Track &track, Time Time extended_length = next_event.length * length_multiplier + time_error; time_error.clock_rate = extended_length.clock_rate; time_error.length = extended_length.length % extended_length.clock_rate; - pll.run_for(Cycles(static_cast(extended_length.get_unsigned_int()))); + pll.run_for(Cycles(extended_length.get())); pll.add_pulse(); // If the PLL is now sufficiently primed, restart, and start recording bits this time. diff --git a/Storage/Storage.hpp b/Storage/Storage.hpp index c55364356..f51043e4a 100644 --- a/Storage/Storage.hpp +++ b/Storage/Storage.hpp @@ -47,12 +47,8 @@ struct Time { /*! @returns the floating point conversion of this @c Time. This will often be less precise. */ - inline float get_float() const { - return static_cast(length) / static_cast(clock_rate); - } - - inline unsigned int get_unsigned_int() const { - return length / clock_rate; + template T get() const { + return static_cast(length) / static_cast(clock_rate); } inline bool operator < (const Time &other) const { diff --git a/Storage/Tape/Parsers/Acorn.cpp b/Storage/Tape/Parsers/Acorn.cpp index 627f02eac..d9d84d561 100644 --- a/Storage/Tape/Parsers/Acorn.cpp +++ b/Storage/Tape/Parsers/Acorn.cpp @@ -75,7 +75,7 @@ Shifter::Shifter() : } void Shifter::process_pulse(const Storage::Tape::Tape::Pulse &pulse) { - pll_.run_for(Cycles(static_cast(static_cast(PLLClockRate) * pulse.length.get_float()))); + pll_.run_for(Cycles(static_cast(static_cast(PLLClockRate) * pulse.length.get()))); bool is_high = pulse.type == Storage::Tape::Tape::Pulse::High; if(is_high != was_high_) { diff --git a/Storage/Tape/Parsers/Commodore.cpp b/Storage/Tape/Parsers/Commodore.cpp index 59e619b9f..c6ebad897 100644 --- a/Storage/Tape/Parsers/Commodore.cpp +++ b/Storage/Tape/Parsers/Commodore.cpp @@ -279,7 +279,7 @@ void Parser::process_pulse(const Storage::Tape::Tape::Pulse &pulse) wave_period_ = 0.0f; } - wave_period_ += pulse.length.get_float(); + wave_period_ += pulse.length.get(); previous_was_high_ = is_high; } diff --git a/Storage/Tape/Parsers/Oric.cpp b/Storage/Tape/Parsers/Oric.cpp index 662b2638f..884456c83 100644 --- a/Storage/Tape/Parsers/Oric.cpp +++ b/Storage/Tape/Parsers/Oric.cpp @@ -62,7 +62,7 @@ void Parser::process_pulse(const Storage::Tape::Tape::Pulse &pulse) cycle_length_ = 0.0f; } wave_was_high_ = wave_is_high; - cycle_length_ += pulse.length.get_float(); + cycle_length_ += pulse.length.get(); } void Parser::inspect_waves(const std::vector &waves) diff --git a/Storage/Tape/Parsers/ZX8081.cpp b/Storage/Tape/Parsers/ZX8081.cpp index bb47e9f53..f63b5772f 100644 --- a/Storage/Tape/Parsers/ZX8081.cpp +++ b/Storage/Tape/Parsers/ZX8081.cpp @@ -31,7 +31,7 @@ void Parser::process_pulse(const Storage::Tape::Tape::Pulse &pulse) { void Parser::post_pulse() { const float expected_pulse_length = 300.0f / 1000000.0f; const float expected_gap_length = 1300.0f / 1000000.0f; - float pulse_time = pulse_time_.get_float(); + float pulse_time = pulse_time_.get(); if(pulse_time > expected_gap_length * 1.25f) { push_wave(WaveType::LongGap); diff --git a/Storage/TimedEventLoop.cpp b/Storage/TimedEventLoop.cpp index bd9bea643..1f1682115 100644 --- a/Storage/TimedEventLoop.cpp +++ b/Storage/TimedEventLoop.cpp @@ -64,7 +64,9 @@ void TimedEventLoop::jump_to_next_event() { } void TimedEventLoop::set_next_event_time_interval(Time interval) { - // Calculate [interval]*[input clock rate] + [subcycles until this event]. + // Calculate [interval]*[input clock rate] + [subcycles until this event] + // = interval.numerator * input clock / interval.denominator + subcycles.numerator / subcycles.denominator + // = (interval.numerator * input clock * subcycles.denominator + subcycles.numerator * interval.denominator) / (interval.denominator * subcycles.denominator) int64_t denominator = static_cast(interval.clock_rate) * static_cast(subcycles_until_event_.clock_rate); int64_t numerator = static_cast(subcycles_until_event_.clock_rate) * static_cast(input_clock_rate_) * static_cast(interval.length) + @@ -72,7 +74,7 @@ void TimedEventLoop::set_next_event_time_interval(Time interval) { // Simplify if necessary: try just simplifying the interval and recalculating; if that doesn't // work then try simplifying the whole thing. - if(numerator < 0 || denominator < 0 || denominator > std::numeric_limits::max()) { + if(numerator < 0 || denominator < 0 || denominator > std::numeric_limits::max()) { interval.simplify(); denominator = static_cast(interval.clock_rate) * static_cast(subcycles_until_event_.clock_rate); numerator = @@ -80,19 +82,36 @@ void TimedEventLoop::set_next_event_time_interval(Time interval) { static_cast(interval.clock_rate) * static_cast(subcycles_until_event_.length); } - if(numerator < 0 || denominator < 0 || denominator > std::numeric_limits::max()) { + if(numerator < 0 || denominator < 0 || denominator > std::numeric_limits::max()) { int64_t common_divisor = NumberTheory::greatest_common_divisor(numerator % denominator, denominator); denominator /= common_divisor; numerator /= common_divisor; } - // TODO: if that doesn't work then reduce precision. + // If even that doesn't work then reduce precision. + if(numerator < 0 || denominator < 0 || denominator > std::numeric_limits::max()) { + const double double_interval = interval.get(); + const double double_subcycles_remaining = subcycles_until_event_.get(); + const double output = double_interval * static_cast(input_clock_rate_) + double_subcycles_remaining; + + if(output < 1.0) { + denominator = std::numeric_limits::max(); + numerator = static_cast(denominator * output); + } else { + numerator = std::numeric_limits::max(); + denominator = static_cast(numerator / output); + } + } // So this event will fire in the integral number of cycles from now, putting us at the remainder // number of subcycles + const int addition = static_cast(numerator / denominator); assert(cycles_until_event_ == 0); - cycles_until_event_ += static_cast(numerator / denominator); - assert(cycles_until_event_ >= 0); + assert(addition >= 0); + if(addition < 0) { + assert(false); + } + cycles_until_event_ += addition; subcycles_until_event_.length = static_cast(numerator % denominator); subcycles_until_event_.clock_rate = static_cast(denominator); subcycles_until_event_.simplify();