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
9namespace openmsx {
10
11static 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
19class AutofireStateChange final : public StateChange
20{
21public:
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
42private:
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
72void Autofire::setSpeed(EmuTime::param time)
73{
74 stateChangeDistributor.distributeNew<AutofireStateChange>(
75 time, id, speedSetting.getInt());
76}
77
78void 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
88void Autofire::update(const Setting& setting) noexcept
89{
90 (void)setting;
91 assert(&setting == &speedSetting);
92 setSpeed(scheduler.getCurrentTime());
93}
94
95void 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
104void Autofire::stopReplay(EmuTime::param time) noexcept
105{
106 setSpeed(time); // re-sync with current value of the setting
107}
108
109bool Autofire::getSignal(EmuTime::param time)
110{
111 return (clock.getPeriod() == EmuDuration::zero())
112 ? false // special value: disabled
113 : (clock.getTicksTill(time) & 1);
114}
115
116template<typename Archive>
117void 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:106
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:283
This file implemented 3 utility functions:
Definition: Autofire.cc:9
REGISTER_POLYMORPHIC_CLASS(StateChange, AutofireStateChange, "AutofireStateChange")
STL namespace.
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1009