diff options
Diffstat (limited to 'src/devices/sound/upd934g.cpp')
-rw-r--r-- | src/devices/sound/upd934g.cpp | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/devices/sound/upd934g.cpp b/src/devices/sound/upd934g.cpp new file mode 100644 index 00000000000..090fb98d725 --- /dev/null +++ b/src/devices/sound/upd934g.cpp @@ -0,0 +1,161 @@ +// license: BSD-3-Clause +// copyright-holders: Dirk Best +/*************************************************************************** + + NEC μPD934G + + Percussion Generator + + TODO: + - Play MUTED and ACCENTED + - T1 input + - 8 channels? + +***************************************************************************/ + +#include "emu.h" +#include "upd934g.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(UPD934G, upd934g_device, "upd934g", "NEC uPD934G") + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// upd934g_device - constructor +//------------------------------------------------- + +upd934g_device::upd934g_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, UPD934G, tag, owner, clock), + device_sound_interface(mconfig, *this), + m_data_cb(*this), + m_stream(nullptr), + m_sample(0), + m_ready(false) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void upd934g_device::device_start() +{ + // create sound stream + m_stream = machine().sound().stream_alloc(*this, 0, 4, 20000); + + // resolve callbacks + m_data_cb.resolve_safe(0); + + // register for save states + save_pointer(NAME(m_addr), 16); + + for (unsigned i = 0; i < 4; i++) + { + save_item(NAME(m_channel[i].pos), i); + save_item(NAME(m_channel[i].playing), i); + save_item(NAME(m_channel[i].volume), i); + } + + save_item(NAME(m_sample)); + save_item(NAME(m_ready)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void upd934g_device::device_reset() +{ + m_ready = false; + + for (unsigned i = 0; i < 4; i++) + m_channel[i].playing = -1; +} + +//------------------------------------------------- +// sound_stream_update - handle update requests for +// our sound stream +//------------------------------------------------- + +void upd934g_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +{ + for (unsigned ch = 0; ch < 4; ch++) + { + std::fill(&outputs[ch][0], &outputs[ch][samples], 0); + + if (m_ready && m_channel[ch].playing != -1) + { + uint16_t end = m_addr[m_channel[ch].playing + 1] - 1; + + for (unsigned i = 0; i < samples; i++) + { + int8_t raw = static_cast<int8_t>(m_data_cb(m_channel[ch].pos)); + outputs[ch][i] = raw * (m_channel[ch].volume + 1) * 64; + + if (++m_channel[ch].pos >= end) + { + m_channel[ch].playing = -1; + break; + } + } + } + } +} + + +//************************************************************************** +// INTERFACE +//************************************************************************** + +WRITE8_MEMBER( upd934g_device::write ) +{ + switch (offset) + { + case 0: + // format of data written here is: + // 76------ command + // --5432-- sample number + // ------10 volume? + m_sample = (data >> 2) & 0x0f; + switch (data >> 6) + { + case 0: + logerror("CMD STORE ADDRESS sample %x\n", m_sample); + break; + case 1: + logerror("CMD PLAY sample %x (channel %d)\n", m_sample, m_sample >> 1); + if (m_sample < 8) + { + m_channel[m_sample >> 1].pos = m_addr[m_sample]; + m_channel[m_sample >> 1].playing = m_sample; + m_channel[m_sample >> 1].volume = data & 0x03; + } + break; + case 2: + logerror("CMD PLAY MUTED sample %x (channel %d)\n", m_sample, m_sample >> 1); + break; + case 3: + logerror("CMD PLAY ACCENTED sample %x (channel %d)\n", m_sample, m_sample >> 1); + break; + } + break; + case 1: + m_addr[m_sample] = (m_addr[m_sample] & 0xff00) | (data << 0); + break; + case 2: + m_addr[m_sample] = (m_addr[m_sample] & 0x00ff) | (data << 8); + logerror(" sample %x address = %04x\n", m_sample, m_addr[m_sample]); + break; + case 3: + m_ready = true; + break; + } +} |