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