openMSX
YM2413.cc
Go to the documentation of this file.
1#include "YM2413.hh"
2#include "YM2413Okazaki.hh"
3#include "YM2413Burczynski.hh"
4#include "YM2413NukeYKT.hh"
6#include "DeviceConfig.hh"
7#include "MSXException.hh"
8#include "serialize.hh"
9#include "cstd.hh"
10#include "narrow.hh"
11#include "outer.hh"
12#include <cmath>
13#include <memory>
14
15namespace openmsx {
16
17// Debuggable
18
19YM2413::Debuggable::Debuggable(
20 MSXMotherBoard& motherBoard_, const std::string& name_)
21 : SimpleDebuggable(motherBoard_, name_ + " regs", "MSX-MUSIC", 0x40)
22{
23}
24
25byte YM2413::Debuggable::read(unsigned address)
26{
27 auto& ym2413 = OUTER(YM2413, debuggable);
28 return ym2413.core->peekReg(address);
29}
30
31void YM2413::Debuggable::write(unsigned address, byte value, EmuTime::param time)
32{
33 auto& ym2413 = OUTER(YM2413, debuggable);
34 ym2413.pokeReg(address, value, time);
35}
36
37
38// YM2413
39
40static std::unique_ptr<YM2413Core> createCore(const DeviceConfig& config)
41{
42 auto core = config.getChildData("ym2413-core", "");
43 if (core == "Okazaki") {
44 return std::make_unique<YM2413Okazaki::YM2413>();
45 } else if (core == "Burczynski") {
46 return std::make_unique<YM2413Burczynski::YM2413>();
47 } else if (core == "NukeYKT") {
48 return std::make_unique<YM2413NukeYKT::YM2413>();
49 } else if (core == "Original-NukeYKT") {
50 return std::make_unique<YM2413OriginalNukeYKT::YM2413>(); // for debug
51 } else if (core.empty()) {
52 // The preferred way to select the core is via the <core> tag.
53 // But for backwards compatibility, when that tag is missing,
54 // fallback to using the <alternative> tag.
55 if (config.getChildDataAsBool("alternative", false)) {
56 return std::make_unique<YM2413Burczynski::YM2413>();
57 } else {
58 return std::make_unique<YM2413Okazaki::YM2413>();
59 }
60 }
61 throw MSXException("Unknown YM2413 core '", core,
62 "'. Must be one of 'Okazaki', 'Burczynski', 'NukeYKT', 'Original-NukeYKT'.");
63}
64
65static constexpr auto INPUT_RATE = unsigned(cstd::round(YM2413Core::CLOCK_FREQ / 72.0));
66
67YM2413::YM2413(const std::string& name_, const DeviceConfig& config)
68 : ResampledSoundDevice(config.getMotherBoard(), name_, "MSX-MUSIC", 9 + 5, INPUT_RATE, false)
69 , core(createCore(config))
70 , debuggable(config.getMotherBoard(), getName())
71{
72 registerSound(config);
73}
74
76{
78}
79
80void YM2413::reset(EmuTime::param time)
81{
82 updateStream(time);
83 core->reset();
84}
85
86void YM2413::writePort(bool port, byte value, EmuTime::param time)
87{
88 updateStream(time);
89
90 auto [integral, fractional] = getEmuClock().getTicksTillAsIntFloat(time);
91 auto offset = narrow_cast<int>(18 * fractional);
92 assert(integral == 0);
93 assert(offset >= 0);
94 assert(offset < 18);
95
96 core->writePort(port, value, offset);
97}
98
99void YM2413::pokeReg(byte reg, byte value, EmuTime::param time)
100{
101 updateStream(time);
102 core->pokeReg(reg, value);
103}
104
105void YM2413::setOutputRate(unsigned hostSampleRate, double speed)
106{
107 ResampledSoundDevice::setOutputRate(hostSampleRate, speed);
108 core->setSpeed(speed);
109}
110
111void YM2413::generateChannels(std::span<float*> bufs, unsigned num)
112{
113 assert(bufs.size() == 9 + 5);
114 core->generateChannels(bufs.first<9 + 5>(), num);
115}
116
117float YM2413::getAmplificationFactorImpl() const
118{
119 return core->getAmplificationFactor();
120}
121
122
123template<typename Archive>
124void YM2413::serialize(Archive& ar, unsigned /*version*/)
125{
126 ar.serializePolymorphic("ym2413", *core);
127}
129
130} // namespace openmsx
IntegralFractional getTicksTillAsIntFloat(EmuTime::param e) const
Definition: DynamicClock.hh:67
void setOutputRate(unsigned hostSampleRate, double speed) override
When a SoundDevice registers itself with the Mixer, the Mixer sets the required sampleRate through th...
void updateStream(EmuTime::param time)
Definition: SoundDevice.cc:138
void unregisterSound()
Unregisters this sound device with the Mixer.
Definition: SoundDevice.cc:133
void registerSound(const DeviceConfig &config)
Registers this sound device with the Mixer.
Definition: SoundDevice.cc:88
void pokeReg(byte reg, byte value, EmuTime::param time)
Definition: YM2413.cc:99
void writePort(bool port, byte value, EmuTime::param time)
Definition: YM2413.cc:86
void serialize(Archive &ar, unsigned version)
Definition: YM2413.cc:124
void reset(EmuTime::param time)
Definition: YM2413.cc:80
constexpr double round(double x)
Definition: cstd.hh:247
std::string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:730
This file implemented 3 utility functions:
Definition: Autofire.cc:9
#define OUTER(type, member)
Definition: outer.hh:41
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1021