summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/ym3812.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/ym3812.cpp')
-rw-r--r--src/devices/sound/ym3812.cpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/devices/sound/ym3812.cpp b/src/devices/sound/ym3812.cpp
new file mode 100644
index 00000000000..07da3b73b3b
--- /dev/null
+++ b/src/devices/sound/ym3812.cpp
@@ -0,0 +1,151 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+
+#include "emu.h"
+#include "ym3812.h"
+
+
+DEFINE_DEVICE_TYPE(YM3812, ym3812_device, "ym3812", "YM3812 OPL2")
+
+
+//*********************************************************
+// YM3812 DEVICE
+//*********************************************************
+
+//-------------------------------------------------
+// ym3812_device - constructor
+//-------------------------------------------------
+
+ym3812_device::ym3812_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, device_type type) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_sound_interface(mconfig, *this),
+ m_address(0),
+ m_stream(nullptr),
+ m_fm(*this)
+{
+}
+
+
+//-------------------------------------------------
+// status_r - return the status port (A0=0)
+//-------------------------------------------------
+
+u8 ym3812_device::status_r()
+{
+ return m_fm.status() | 0x06;
+}
+
+
+//-------------------------------------------------
+// read - handle a read from the device
+//-------------------------------------------------
+
+u8 ym3812_device::read(offs_t offset)
+{
+ // datasheet says status only reads when A0=0
+ if ((offset & 1) == 0)
+ return status_r();
+ logerror("Unexpected read from YM3812 offset %d\n", offset & 1);
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// address_w - write to the address port (A0=0)
+//-------------------------------------------------
+
+void ym3812_device::address_w(u8 value)
+{
+ m_address = value;
+}
+
+
+//-------------------------------------------------
+// data_w - write to the data port (A0=1)
+//-------------------------------------------------
+
+void ym3812_device::data_w(u8 value)
+{
+ // force an update
+ m_stream->update();
+
+ // write to FM
+ m_fm.write(m_address, value);
+}
+
+
+//-------------------------------------------------
+// write - handle a write to the register
+// interface
+//-------------------------------------------------
+
+void ym3812_device::write(offs_t offset, u8 value)
+{
+ // A0 selects between address/data
+ if ((offset & 1) == 0)
+ address_w(value);
+ else
+ data_w(value);
+}
+
+
+//-------------------------------------------------
+// device_start - start of emulation
+//-------------------------------------------------
+
+void ym3812_device::device_start()
+{
+ // create our stream
+ m_stream = stream_alloc(0, fm_engine::OUTPUTS, m_fm.sample_rate(clock()));
+
+ // save our data
+ save_item(YMFM_NAME(m_address));
+
+ // save the engines
+ m_fm.save(*this);
+}
+
+
+//-------------------------------------------------
+// device_reset - start of emulation
+//-------------------------------------------------
+
+void ym3812_device::device_reset()
+{
+ // reset the engines
+ m_fm.reset();
+}
+
+
+//-------------------------------------------------
+// device_clock_changed - update if clock changes
+//-------------------------------------------------
+
+void ym3812_device::device_clock_changed()
+{
+ m_stream->set_sample_rate(m_fm.sample_rate(clock()));
+}
+
+
+//-------------------------------------------------
+// sound_stream_update - update the sound stream
+//-------------------------------------------------
+
+void ym3812_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
+{
+ // iterate over all target samples
+ for (int sampindex = 0; sampindex < outputs[0].samples(); sampindex++)
+ {
+ // clock the system
+ m_fm.clock(fm_engine::ALL_CHANNELS);
+
+ // update the FM content; clipping is unknown
+ s32 sums[fm_engine::OUTPUTS] = { 0 };
+ m_fm.output(sums, 1, 32767, fm_engine::ALL_CHANNELS);
+
+ // convert to 10.3 floating point value for the DAC and back
+ // YM3812 is mono
+ for (int index = 0; index < fm_engine::OUTPUTS; index++)
+ outputs[index].put_int(sampindex, ymfm_roundtrip_fp(sums[index]), 32768);
+ }
+}