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 static std::string_view nameForId(Autofire::ID id)
12 {
13  switch (id) {
14  case Autofire::RENSHATURBO: return "renshaturbo";
15  default: return "unknown-autofire";
16  }
17 }
18 
19 class AutofireStateChange final : public StateChange
20 {
21 public:
22  AutofireStateChange() = default; // for serialize
23  AutofireStateChange(EmuTime::param time_, Autofire::ID id_, int value_)
24  : StateChange(time_)
25  , id(id_), value(value_) {}
26  [[nodiscard]] auto getId() const { return id; }
27  [[nodiscard]] int getValue() const { return value; }
28  template<typename Archive> void serialize(Archive& ar, unsigned /*version*/)
29  {
30  ar.template serializeBase<StateChange>(*this);
31  // for backwards compatibility serialize 'id' as 'name'
32  std::string name = Archive::IS_LOADER ? "" : std::string(nameForId(id));
33  ar.serialize("name", name,
34  "value", value);
35  if constexpr (Archive::IS_LOADER) {
36  id = (name == nameForId(Autofire::RENSHATURBO))
39  }
40  }
41 
42 private:
44  int value;
45 };
47 
48 
50  unsigned newMinInts, unsigned newMaxInts, ID id_)
51  : scheduler(motherBoard.getScheduler())
52  , stateChangeDistributor(motherBoard.getStateChangeDistributor())
53  , min_ints(std::max(newMinInts, 1u))
54  , max_ints(std::max(newMaxInts, min_ints + 1))
55  , speedSetting(motherBoard.getCommandController(), nameForId(id_),
56  "controls the speed of this autofire circuit", 0, 0, 100)
57  , clock(scheduler.getCurrentTime())
58  , id(id_)
59 {
60  setClock(speedSetting.getInt());
61 
62  stateChangeDistributor.registerListener(*this);
63  speedSetting.attach(*this);
64 }
65 
67 {
68  speedSetting.detach(*this);
69  stateChangeDistributor.unregisterListener(*this);
70 }
71 
72 void Autofire::setSpeed(EmuTime::param time)
73 {
74  stateChangeDistributor.distributeNew<AutofireStateChange>(
75  time, id, speedSetting.getInt());
76 }
77 
78 void Autofire::setClock(int speed)
79 {
80  if (speed) {
81  clock.setFreq(
82  (2 * 50 * 60) / (max_ints - (speed * (max_ints - min_ints)) / 100));
83  } else {
84  clock.setPeriod(EmuDuration::zero()); // special value: disabled
85  }
86 }
87 
88 void Autofire::update(const Setting& setting) noexcept
89 {
90  (void)setting;
91  assert(&setting == &speedSetting);
92  setSpeed(scheduler.getCurrentTime());
93 }
94 
95 void Autofire::signalStateChange(const StateChange& event)
96 {
97  const auto* as = dynamic_cast<const AutofireStateChange*>(&event);
98  if (!as) return;
99  if (as->getId() != id) return;
100 
101  setClock(as->getValue());
102 }
103 
104 void Autofire::stopReplay(EmuTime::param time) noexcept
105 {
106  setSpeed(time); // re-sync with current value of the setting
107 }
108 
109 bool Autofire::getSignal(EmuTime::param time)
110 {
111  return (clock.getPeriod() == EmuDuration::zero())
112  ? false // special value: disabled
113  : (clock.getTicksTill(time) & 1);
114 }
115 
116 template<typename Archive>
117 void Autofire::serialize(Archive& ar, unsigned /*version*/)
118 {
119  ar.serialize("clock", clock);
120 }
122 
123 } // namespace openmsx
BaseSetting * setting
Definition: Interpreter.cc:27
uintptr_t id
Definition: Interpreter.cc:26
AutofireStateChange(EmuTime::param time_, Autofire::ID id_, int value_)
Definition: Autofire.cc:23
void serialize(Archive &ar, unsigned)
Definition: Autofire.cc:28
Autofire is a device that is between two other devices and outside the bus.
Definition: Autofire.hh:26
bool getSignal(EmuTime::param time)
Get the output signal in negative logic.
Definition: Autofire.cc:109
Autofire(MSXMotherBoard &motherBoard, unsigned newMinInts, unsigned newMaxInts, ID id)
Definition: Autofire.cc:49
void serialize(Archive &ar, unsigned version)
Definition: Autofire.cc:117
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(EmuTime::param time, Args &&...args)
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:20
void detach(Observer< T > &observer)
Definition: Subject.hh:56
void attach(Observer< T > &observer)
Definition: Subject.hh:50
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:998