openMSX
Autofire.cc
Go to the documentation of this file.
1 #include "Autofire.hh"
2 #include "MSXMotherBoard.hh"
3 #include "Scheduler.hh"
4 #include "StateChange.hh"
6 #include <algorithm>
7 #include <cassert>
8 
9 namespace openmsx {
10 
11 class AutofireStateChange final : public StateChange
12 {
13 public:
14  AutofireStateChange() = default; // for serialize
15  AutofireStateChange(EmuTime::param time_, std::string name_, int value_)
16  : StateChange(time_)
17  , name(std::move(name_)), value(value_) {}
18  [[nodiscard]] const std::string& getName() const { return name; }
19  [[nodiscard]] int getValue() const { return value; }
20  template<typename Archive> void serialize(Archive& ar, unsigned /*version*/)
21  {
22  ar.template serializeBase<StateChange>(*this);
23  ar.serialize("name", name,
24  "value", value);
25  }
26 
27 private:
28  std::string name;
29  int value;
30 };
32 
33 
35  unsigned newMinInts, unsigned newMaxInts, static_string_view name_)
36  : scheduler(motherBoard.getScheduler())
37  , stateChangeDistributor(motherBoard.getStateChangeDistributor())
38  , name(name_)
39  , min_ints(std::max(newMinInts, 1u))
40  , max_ints(std::max(newMaxInts, min_ints + 1))
41  , speedSetting(motherBoard.getCommandController(), name,
42  "controls the speed of this autofire circuit", 0, 0, 100)
43  , clock(scheduler.getCurrentTime())
44 {
45  setClock(speedSetting.getInt());
46 
47  stateChangeDistributor.registerListener(*this);
48  speedSetting.attach(*this);
49 }
50 
52 {
53  speedSetting.detach(*this);
54  stateChangeDistributor.unregisterListener(*this);
55 }
56 
57 void Autofire::setSpeed(EmuTime::param time)
58 {
59  stateChangeDistributor.distributeNew(std::make_shared<AutofireStateChange>(
60  time, std::string(name), speedSetting.getInt()));
61 }
62 
63 void Autofire::setClock(int speed)
64 {
65  if (speed) {
66  clock.setFreq(
67  (2 * 50 * 60) / (max_ints - (speed * (max_ints - min_ints)) / 100));
68  } else {
69  clock.setPeriod(EmuDuration::zero()); // special value: disabled
70  }
71 }
72 
73 void Autofire::update(const Setting& setting) noexcept
74 {
75  (void)setting;
76  assert(&setting == &speedSetting);
77  setSpeed(scheduler.getCurrentTime());
78 }
79 
80 void Autofire::signalStateChange(const std::shared_ptr<StateChange>& event)
81 {
82  auto* as = dynamic_cast<AutofireStateChange*>(event.get());
83  if (!as) return;
84  if (as->getName() != name) return;
85 
86  setClock(as->getValue());
87 }
88 
89 void Autofire::stopReplay(EmuTime::param time) noexcept
90 {
91  setSpeed(time); // re-sync with current value of the setting
92 }
93 
94 bool Autofire::getSignal(EmuTime::param time)
95 {
96  return (clock.getPeriod() == EmuDuration::zero())
97  ? false // special value: disabled
98  : (clock.getTicksTill(time) & 1);
99 }
100 
101 template<typename Archive>
102 void Autofire::serialize(Archive& ar, unsigned /*version*/)
103 {
104  ar.serialize("clock", clock);
105 }
107 
108 } // namespace openmsx
BaseSetting * setting
Definition: Interpreter.cc:30
void serialize(Archive &ar, unsigned)
Definition: Autofire.cc:20
const std::string & getName() const
Definition: Autofire.cc:18
AutofireStateChange(EmuTime::param time_, std::string name_, int value_)
Definition: Autofire.cc:15
Autofire is a device that is between two other devices and outside the bus.
Definition: Autofire.hh:26
Autofire(MSXMotherBoard &motherBoard, unsigned newMinInts, unsigned newMaxInts, static_string_view name)
Definition: Autofire.cc:34
bool getSignal(EmuTime::param time)
Get the output signal in negative logic.
Definition: Autofire.cc:94
void serialize(Archive &ar, unsigned version)
Definition: Autofire.cc:102
unsigned getTicksTill(EmuTime::param e) const
Calculate the number of ticks for this clock until the given time.
Definition: DynamicClock.hh:51
EmuDuration getPeriod() const
Returns the length of one clock-cycle.
void setPeriod(EmuDuration period)
Set the duration of a clock tick.
void setFreq(unsigned freq)
Change the frequency at which this clock ticks.
static constexpr EmuDuration zero()
Definition: EmuDuration.hh:115
int getInt() const noexcept
void registerListener(StateChangeListener &listener)
(Un)registers the given object to receive state change events.
void distributeNew(const EventPtr &event)
Deliver the event to all registered listeners MSX input devices should call the distributeNew() versi...
void unregisterListener(StateChangeListener &listener)
Base class for all external MSX state changing events.
Definition: StateChange.hh:14
void detach(Observer< T > &observer)
Definition: Subject.hh:56
void attach(Observer< T > &observer)
Definition: Subject.hh:50
static_string_view
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:287
This file implemented 3 utility functions:
Definition: Autofire.cc:9
REGISTER_POLYMORPHIC_CLASS(StateChange, AutofireStateChange, "AutofireStateChange")
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:983