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