diff options
Diffstat (limited to 'src/devices/sound/st0016.cpp')
-rw-r--r-- | src/devices/sound/st0016.cpp | 251 |
1 files changed, 167 insertions, 84 deletions
diff --git a/src/devices/sound/st0016.cpp b/src/devices/sound/st0016.cpp index d2f0653364a..420ff9955bc 100644 --- a/src/devices/sound/st0016.cpp +++ b/src/devices/sound/st0016.cpp @@ -3,6 +3,9 @@ /************************************ Seta custom ST-0016 chip sound emulation by R. Belmont, Tomasz Slanina, and David Haywood + + TODO: + - Verify keyon/off flag behavior ************************************/ #include "emu.h" @@ -27,13 +30,11 @@ DEFINE_DEVICE_TYPE(ST0016, st0016_device, "st0016", "Seta ST0016 (Audio)") st0016_device::st0016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, ST0016, tag, owner, clock) , device_sound_interface(mconfig, *this) + , device_memory_interface(mconfig, *this) + , m_data_config("data", ENDIANNESS_LITTLE, 8, 21) // shares character RAM area? , m_stream(nullptr) - , m_ram_read_cb(*this) - , m_vpos{ 0, 0, 0, 0, 0, 0, 0, 0 } - , m_frac{ 0, 0, 0, 0, 0, 0, 0, 0 } - , m_lponce{ 0, 0, 0, 0, 0, 0, 0, 0 } + , m_voice{ m_cache, m_cache, m_cache, m_cache, m_cache, m_cache, m_cache, m_cache } { - std::fill(std::begin(m_regs), std::end(m_regs), 0); } @@ -43,13 +44,25 @@ st0016_device::st0016_device(const machine_config &mconfig, const char *tag, dev void st0016_device::device_start() { - m_stream = stream_alloc(0, 2, 44100); - m_ram_read_cb.resolve_safe(0); - - save_item(NAME(m_vpos)); - save_item(NAME(m_frac)); - save_item(NAME(m_lponce)); - save_item(NAME(m_regs)); + // Find our direct access + space(0).cache(m_cache); + + // allocate stream + m_stream = stream_alloc(0, 2, clock() / 128); + + save_item(STRUCT_MEMBER(m_voice, m_regs)); + save_item(STRUCT_MEMBER(m_voice, m_start)); + save_item(STRUCT_MEMBER(m_voice, m_end)); + save_item(STRUCT_MEMBER(m_voice, m_lpstart)); + save_item(STRUCT_MEMBER(m_voice, m_lpend)); + save_item(STRUCT_MEMBER(m_voice, m_freq)); + save_item(STRUCT_MEMBER(m_voice, m_vol_l)); + save_item(STRUCT_MEMBER(m_voice, m_vol_r)); + save_item(STRUCT_MEMBER(m_voice, m_flags)); + save_item(STRUCT_MEMBER(m_voice, m_pos)); + save_item(STRUCT_MEMBER(m_voice, m_frac)); + save_item(STRUCT_MEMBER(m_voice, m_lponce)); + save_item(STRUCT_MEMBER(m_voice, m_out)); } @@ -57,108 +70,178 @@ void st0016_device::device_start() // sound_stream_update - handle a stream update //------------------------------------------------- -void st0016_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +void st0016_device::sound_stream_update(sound_stream &stream) { - int v, i, snum; - unsigned char *slot; - int32_t mix[48000*2]; - int32_t *mixp; - int16_t sample; - int sptr, eptr, freq, lsptr, leptr; - - memset(mix, 0, sizeof(mix[0])*samples*2); - - for (v = 0; v < 8; v++) + for (int sampleind = 0; sampleind < stream.samples(); sampleind++) { - slot = (unsigned char *)&m_regs[v * 32]; - - if (slot[0x16] & 0x06) + for (int v = 0; v < 8; v++) { - mixp = &mix[0]; + // check if voice is activated + if (m_voice[v].update()) + { + stream.add_int(0, sampleind, (m_voice[v].m_out * m_voice[v].m_vol_l) >> 8, 32768 << 4); + stream.add_int(1, sampleind, (m_voice[v].m_out * m_voice[v].m_vol_r) >> 8, 32768 << 4); + } + } + } +} - sptr = slot[0x02]<<16 | slot[0x01]<<8 | slot[0x00]; - eptr = slot[0x0e]<<16 | slot[0x0d]<<8 | slot[0x0c]; - freq = slot[0x11]<<8 | slot[0x10]; - lsptr = slot[0x06]<<16 | slot[0x05]<<8 | slot[0x04]; - leptr = slot[0x0a]<<16 | slot[0x09]<<8 | slot[0x08]; +//------------------------------------------------- +// memory_space_config - return a description of +// any address spaces owned by this device +//------------------------------------------------- - for (snum = 0; snum < samples; snum++) - { - sample = m_ram_read_cb((sptr + m_vpos[v]) & 0x1fffff) << 8; +device_memory_interface::space_config_vector st0016_device::memory_space_config() const +{ + return space_config_vector{ std::make_pair(0, &m_data_config) }; +} - *mixp++ += (sample * (char)slot[0x14]) >> 8; - *mixp++ += (sample * (char)slot[0x15]) >> 8; +//------------------------------------------------- +// update - update single voice +//------------------------------------------------- - m_frac[v] += freq; - m_vpos[v] += (m_frac[v]>>16); - m_frac[v] &= 0xffff; +bool st0016_device::voice_t::update() +{ + if (m_flags & 0x06) // TODO: keyon flag? + { + m_out = s16(s8(m_host.read_byte(m_pos & 0x1fffff))) << 8; + m_frac += m_freq; + m_pos += (m_frac >> 16); + m_frac &= 0xffff; - // stop if we're at the end - if (m_lponce[v]) + // stop if we're at the end + if (m_lponce) + { + // we've looped once, check loop end rather than sample end + if (m_pos >= m_lpend) + { + m_pos = m_lpstart; + } + } + else + { + // not looped yet, check sample end + if (m_pos >= m_end) + { + if (BIT(m_flags, 0)) // loop? { - // we've looped once, check loop end rather than sample end - if ((m_vpos[v] + sptr) >= leptr) - { - m_vpos[v] = (lsptr - sptr); - } + m_pos = m_lpstart; + m_lponce = true; } else { - // not looped yet, check sample end - if ((m_vpos[v] + sptr) >= eptr) - { - if (slot[0x16] & 0x01) // loop? - { - m_vpos[v] = (lsptr - sptr); - m_lponce[v] = 1; - } - else - { - slot[0x16] = 0; - m_vpos[v] = m_frac[v] = 0; - } - } + m_flags = 0; + m_pos = m_frac = 0; } } } + return true; + } + else + { + m_out = 0; + return false; + } +} + +//------------------------------------------------- +// snd_r - read sound registers +//------------------------------------------------- + +u8 st0016_device::snd_r(offs_t offset) +{ + if (offset < 0x100) + { + m_stream->update(); + return m_voice[offset >> 5].reg_r(offset & 0x1f); } + return 0; +} - mixp = &mix[0]; - for (i = 0; i < samples; i++) +//------------------------------------------------- +// snd_w - write sound registers +//------------------------------------------------- + +void st0016_device::snd_w(offs_t offset, u8 data) +{ + if (offset < 0x100) { - outputs[0][i] = (*mixp++)>>4; - outputs[1][i] = (*mixp++)>>4; + m_stream->update(); + m_voice[offset >> 5].reg_w(offset & 0x1f, data, offset >> 5); } } +//------------------------------------------------- +// reg_r - read single voice registers +//------------------------------------------------- -READ8_MEMBER( st0016_device::st0016_snd_r ) +u8 st0016_device::voice_t::reg_r(offs_t offset) { - return m_regs[offset]; + return m_regs[offset & 0x1f]; } -WRITE8_MEMBER( st0016_device::st0016_snd_w ) +//------------------------------------------------- +// reg_w - write single voice registers +//------------------------------------------------- + +void st0016_device::voice_t::reg_w(offs_t offset, u8 data, int voice) { - int voice = offset/32; - int reg = offset & 0x1f; - int oldreg = m_regs[offset]; - int vbase = offset & ~0x1f; + offset &= 0x1f; m_regs[offset] = data; - - if ((voice < 8) && (data != oldreg)) + switch (offset) { - if ((reg == 0x16) && (data != 0)) + case 0x00: // Start position bit 0-7 + case 0x01: // Start position bit 8-15 + case 0x02: // Start position bit 16-23 + m_start = (m_regs[0x02] << 16) | (m_regs[0x01] << 8) | m_regs[0x00]; + break; + case 0x04: // Loop start position bit 0-7 + case 0x05: // Loop start position bit 8-15 + case 0x06: // Loop start position bit 16-23 + m_lpstart = (m_regs[0x06] << 16) | (m_regs[0x05] << 8) | m_regs[0x04]; + break; + case 0x08: // Loop end position bit 0-7 + case 0x09: // Loop end position bit 8-15 + case 0x0a: // Loop end position bit 16-23 + m_lpend = (m_regs[0x0a] << 16) | (m_regs[0x09] << 8) | m_regs[0x08]; + break; + case 0x0c: // End position bit 0-7 + case 0x0d: // End position bit 8-15 + case 0x0e: // End position bit 16-23 + m_end = (m_regs[0x0e] << 16) | (m_regs[0x0d] << 8) | m_regs[0x0c]; + break; + case 0x10: // Frequency bit 0-7 + case 0x11: // Frequency bit 8-15 + m_freq = (m_regs[0x11] << 8) | m_regs[0x10]; + break; + case 0x14: // Left volume + m_vol_l = (char)data; + break; + case 0x15: // Right volume + m_vol_r = (char)data; + break; + case 0x16: + if (data != m_flags) { - m_vpos[voice] = m_frac[voice] = m_lponce[voice] = 0; - - LOG("Key on V%02d: st %06x-%06x lp %06x-%06x frq %x flg %x\n", voice, - m_regs[vbase+2]<<16 | m_regs[vbase+1]<<8 | m_regs[vbase+2], - m_regs[vbase+0xe]<<16 | m_regs[vbase+0xd]<<8 | m_regs[vbase+0xc], - m_regs[vbase+6]<<16 | m_regs[vbase+5]<<8 | m_regs[vbase+4], - m_regs[vbase+0xa]<<16 | m_regs[vbase+0x9]<<8 | m_regs[vbase+0x8], - m_regs[vbase+0x11]<<8 | m_regs[vbase+0x10], - m_regs[vbase+0x16]); + if (data != 0) + { + m_pos = m_start; + m_frac = 0; + m_lponce = false; + + /* + LOG("Key on V%02d: st %06x-%06x lp %06x-%06x frq %x flg %x\n", voice, + m_start, + m_end, + m_lpstart, + m_lpend, + m_freq, + m_regs[0x16]); + */ + } } + m_flags = m_regs[0x16]; + break; } } |