diff --git a/ClockReceiver/ClockReceiver.hpp b/ClockReceiver/ClockReceiver.hpp index 8f650a973..ba4aa337a 100644 --- a/ClockReceiver/ClockReceiver.hpp +++ b/ClockReceiver/ClockReceiver.hpp @@ -9,6 +9,8 @@ #ifndef ClockReceiver_hpp #define ClockReceiver_hpp +#include + /*! Provides a class that wraps a plain int, providing most of the basic arithmetic and Boolean operators, but forcing callers and receivers to be explicit as to usage. @@ -118,13 +120,7 @@ class HalfCycles: public WrappedInt { inline HalfCycles(const HalfCycles &half_cycles) : WrappedInt(half_cycles.length_) {} }; -/*! - ClockReceiver is a template for components that receove a clock, measured either - in cycles or in half cycles. They are expected to implement either of the run_for - methods and to declare that they are `using` the other; buying into the template - means that the other run_for will automatically map appropriately to the implemented - one, so callers may use either. - +/* Alignment rule: run_for(Cycles) may be called only at the start of a cycle. E.g. the following @@ -150,22 +146,24 @@ class HalfCycles: public WrappedInt { of a full cycle. The second will do the second half. Etc. */ -template class ClockReceiver { + +/*! + If a component implements only run_for(Cycles), an owner can wrap it in HalfClockReceiver + automatically to gain run_for(HalfCycles). +*/ +template class HalfClockReceiver: public T { public: - ClockReceiver() : half_cycle_carry_(0) {} - - inline void run_for(const Cycles &cycles) { - static_cast(this)->run_for(HalfCycles(cycles)); - } + using T::T; + using T::run_for; inline void run_for(const HalfCycles &half_cycles) { int cycles = half_cycles.as_int() + half_cycle_carry_; half_cycle_carry_ = cycles & 1; - static_cast(this)->run_for(Cycles(cycles >> 1)); + T::run_for(Cycles(cycles >> 1)); } private: - int half_cycle_carry_; + int half_cycle_carry_ = 0; }; #endif /* ClockReceiver_hpp */ diff --git a/Components/6522/6522.hpp b/Components/6522/6522.hpp index 7eee8df14..0a7ea313c 100644 --- a/Components/6522/6522.hpp +++ b/Components/6522/6522.hpp @@ -13,8 +13,6 @@ #include #include -#include "../../ClockReceiver/ClockReceiver.hpp" - namespace MOS { /*! @@ -28,7 +26,7 @@ namespace MOS { Consumers should derive their own curiously-recurring-template-pattern subclass, implementing bus communications as required. */ -template class MOS6522: public ClockReceiver> { +template class MOS6522 { private: enum InterruptFlag: uint8_t { CA2ActiveEdge = 1 << 0, diff --git a/Components/6532/6532.hpp b/Components/6532/6532.hpp index 42ff5dc6f..854f1068c 100644 --- a/Components/6532/6532.hpp +++ b/Components/6532/6532.hpp @@ -12,8 +12,6 @@ #include #include -#include "../../ClockReceiver/ClockReceiver.hpp" - namespace MOS { /*! @@ -27,7 +25,7 @@ namespace MOS { Consumers should derive their own curiously-recurring-template-pattern subclass, implementing bus communications as required. */ -template class MOS6532: public ClockReceiver> { +template class MOS6532 { public: inline void set_ram(uint16_t address, uint8_t value) { ram_[address&0x7f] = value; } inline uint8_t get_ram(uint16_t address) { return ram_[address & 0x7f]; } @@ -106,7 +104,6 @@ template class MOS6532: public ClockReceiver> { return 0xff; } - using ClockReceiver>::run_for; inline void run_for(const Cycles &cycles) { unsigned int number_of_cycles = (unsigned int)cycles.as_int(); diff --git a/Components/6560/6560.hpp b/Components/6560/6560.hpp index 44c5c943a..88573338f 100644 --- a/Components/6560/6560.hpp +++ b/Components/6560/6560.hpp @@ -41,7 +41,7 @@ class Speaker: public ::Outputs::Filter { @c set_register and @c get_register provide register access. */ -template class MOS6560: public ClockReceiver> { +template class MOS6560 { public: MOS6560() : crt_(new Outputs::CRT::CRT(65*4, 4, Outputs::CRT::NTSC60, 2)), @@ -147,7 +147,6 @@ template class MOS6560: public ClockReceiver> { } } - using ClockReceiver>::run_for; /*! Runs for cycles. Derr. */ diff --git a/Machines/Atari2600/TIA.hpp b/Machines/Atari2600/TIA.hpp index 8e7f50826..b8cc92178 100644 --- a/Machines/Atari2600/TIA.hpp +++ b/Machines/Atari2600/TIA.hpp @@ -12,11 +12,10 @@ #include #include "../CRTMachine.hpp" -#include "../../ClockReceiver/ClockReceiver.hpp" namespace Atari2600 { -class TIA: public ClockReceiver { +class TIA { public: TIA(); // The supplied hook is for unit testing only; if instantiated with a line_end_function then it will @@ -32,7 +31,6 @@ class TIA: public ClockReceiver { Advances the TIA by @c cycles. Any queued setters take effect in the first cycle performed. */ void run_for(const Cycles &cycles); - using ClockReceiver::run_for; void set_output_mode(OutputMode output_mode); void set_sync(bool sync); diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index 7badbb228..fc0961952 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -11,6 +11,7 @@ #include "../../Processors/6502/6502.hpp" #include "../../Storage/Tape/Tape.hpp" +#include "../../ClockReceiver/ClockReceiver.hpp" #include "../ConfigurationTarget.hpp" #include "../CRTMachine.hpp" diff --git a/Machines/Electron/Video.hpp b/Machines/Electron/Video.hpp index 65ad5bc2d..1414c1abc 100644 --- a/Machines/Electron/Video.hpp +++ b/Machines/Electron/Video.hpp @@ -22,7 +22,7 @@ namespace Electron { running either at 40 or 80 columns. Memory is shared between video and CPU; when the video is accessing it the CPU may not. */ -class VideoOutput: public ClockReceiver { +class VideoOutput { public: /*! Instantiates a VideoOutput that will read its pixels from @c memory. The pointer supplied @@ -35,7 +35,6 @@ class VideoOutput: public ClockReceiver { /// Produces the next @c cycles of video output. void run_for(const Cycles &cycles); - using ClockReceiver::run_for; /*! Writes @c value to the register at @c address. May mutate the results of @c get_next_interrupt, diff --git a/Machines/Oric/Video.hpp b/Machines/Oric/Video.hpp index 6ceb076fb..d17c0b54a 100644 --- a/Machines/Oric/Video.hpp +++ b/Machines/Oric/Video.hpp @@ -14,12 +14,11 @@ namespace Oric { -class VideoOutput: public ClockReceiver { +class VideoOutput { public: VideoOutput(uint8_t *memory); std::shared_ptr get_crt(); void run_for(const Cycles &cycles); - using ClockReceiver::run_for; void set_colour_rom(const std::vector &rom); void set_output_device(Outputs::CRT::OutputDevice output_device); diff --git a/Machines/ZX8081/Video.hpp b/Machines/ZX8081/Video.hpp index 5c128d424..cb8a7caba 100644 --- a/Machines/ZX8081/Video.hpp +++ b/Machines/ZX8081/Video.hpp @@ -24,7 +24,7 @@ namespace ZX8081 { a 1-bit graphic and output over the next 4 cycles, picking between the white level and the black level. */ -class Video: public ClockReceiver