OXYGENHUB
◆ main openmsx / src / Autofire.cc
2.1 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "Autofire.hh"
2
3
#include "MSXMotherBoard.hh"
4
#include "Scheduler.hh"
5
#include "StateChange.hh"
6
#include "StateChangeDistributor.hh"
7
8
#include <algorithm>
9
#include <cassert>
10
11
namespace openmsx {
12
13
Autofire::Autofire(MSXMotherBoard& motherBoard,
14
                   unsigned newMinInts, unsigned newMaxInts, AutofireID id_)
15
	: scheduler(motherBoard.getScheduler())
16
	, stateChangeDistributor(motherBoard.getStateChangeDistributor())
17
	, min_ints(std::max(newMinInts, 1u))
18
	, max_ints(std::max(newMaxInts, min_ints + 1))
19
	, speedSetting(motherBoard.getCommandController(), nameForId(id_),
20
		"controls autofire speed (0 = disabled)", 0, 0, 100)
21
	, clock(scheduler.getCurrentTime())
22
	, id(id_)
23
{
24
	setClock(speedSetting.getInt());
25
26
	stateChangeDistributor.registerListener(*this);
27
	speedSetting.attach(*this);
28
}
29
30
Autofire::~Autofire()
31
{
32
	speedSetting.detach(*this);
33
	stateChangeDistributor.unregisterListener(*this);
34
}
35
36
void Autofire::setSpeed(EmuTime time)
37
{
38
	stateChangeDistributor.distributeNew<AutofireStateChange>(
39
		time, id, speedSetting.getInt());
40
}
41
42
void Autofire::setClock(int speed)
43
{
44
	if (speed) {
45
		clock.setFreq(
46
		    (2 * 50 * 60) / (max_ints - (speed * (max_ints - min_ints)) / 100));
47
	} else {
48
		clock.setPeriod(EmuDuration::zero()); // special value: disabled
49
	}
50
}
51
52
void Autofire::update(const Setting& setting) noexcept
53
{
54
	(void)setting;
55
	assert(&setting == &speedSetting);
56
	setSpeed(scheduler.getCurrentTime());
57
}
58
59
void Autofire::signalStateChange(const StateChange& event)
60
{
61
	const auto* as = std::get_if<AutofireStateChange>(&event);
62
	if (!as) return;
63
	if (as->getId() != id) return;
64
65
	setClock(as->getValue());
66
}
67
68
void Autofire::stopReplay(EmuTime time) noexcept
69
{
70
	setSpeed(time); // re-sync with current value of the setting
71
}
72
73
bool Autofire::getSignal(EmuTime time) const
74
{
75
	return (clock.getPeriod() == EmuDuration::zero())
76
		? false // special value: disabled
77
		: (clock.getTicksTill(time) & 1);
78
}
79
80
template<typename Archive>
81
void Autofire::serialize(Archive& ar, unsigned /*version*/)
82
{
83
	ar.serialize("clock", clock);
84
}
85
INSTANTIATE_SERIALIZE_METHODS(Autofire)
86
87
} // namespace openmsx