From 0a2caa105dafac435294f9f33fa56c35c299d004 Mon Sep 17 00:00:00 2001 From: cam900 Date: Tue, 23 Feb 2021 21:12:22 +0900 Subject: Refactored Seta sound, adding preliminary ST0032 sound support. (#7800) * Renamed sound/nile.cpp to sound/setapcm.cpp. * Added preliminary support for 16-voice ST0032 variant. * jclub2.cpp: Hooked up ST0032 sound. * jclub2.cpp, srmp6.cpp: Derive sound clocks from crystal frequencies. --- scripts/src/sound.lua | 8 +- scripts/target/mame/arcade.lua | 2 +- scripts/target/mame/mess.lua | 2 +- src/devices/sound/nile.cpp | 233 ---------------------- src/devices/sound/nile.h | 48 ----- src/devices/sound/setapcm.cpp | 429 +++++++++++++++++++++++++++++++++++++++++ src/devices/sound/setapcm.h | 103 ++++++++++ src/mame/drivers/jclub2.cpp | 28 ++- src/mame/drivers/srmp6.cpp | 9 +- 9 files changed, 562 insertions(+), 300 deletions(-) delete mode 100644 src/devices/sound/nile.cpp delete mode 100644 src/devices/sound/nile.h create mode 100644 src/devices/sound/setapcm.cpp create mode 100644 src/devices/sound/setapcm.h diff --git a/scripts/src/sound.lua b/scripts/src/sound.lua index 9844605eeae..a9b35f65675 100644 --- a/scripts/src/sound.lua +++ b/scripts/src/sound.lua @@ -853,7 +853,7 @@ end --------------------------------------------------- -- Seta custom sound chips --@src/devices/sound/st0016.h,SOUNDS["ST0016"] = true ---@src/devices/sound/nile.h,SOUNDS["NILE"] = true +--@src/devices/sound/setapcm.h,SOUNDS["SETAPCM"] = true --@src/devices/sound/x1_010.h,SOUNDS["X1_010"] = true --------------------------------------------------- @@ -864,10 +864,10 @@ if (SOUNDS["ST0016"]~=null) then } end -if (SOUNDS["NILE"]~=null) then +if (SOUNDS["SETAPCM"]~=null) then files { - MAME_DIR .. "src/devices/sound/nile.cpp", - MAME_DIR .. "src/devices/sound/nile.h", + MAME_DIR .. "src/devices/sound/setapcm.cpp", + MAME_DIR .. "src/devices/sound/setapcm.h", } end diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 913f7ad63e2..9e304c44ac4 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -239,7 +239,7 @@ SOUNDS["CDDA"] = true SOUNDS["ICS2115"] = true SOUNDS["I5000_SND"] = true SOUNDS["ST0016"] = true -SOUNDS["NILE"] = true +SOUNDS["SETAPCM"] = true SOUNDS["X1_010"] = true SOUNDS["VRENDER0"] = true SOUNDS["VOTRAX"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 1baf05ce3e2..f81851af8ee 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -259,7 +259,7 @@ SOUNDS["CDDA"] = true --SOUNDS["ICS2115"] = true --SOUNDS["I5000_SND"] = true --SOUNDS["ST0016"] = true ---SOUNDS["NILE"] = true +--SOUNDS["SETAPCM"] = true --SOUNDS["X1_010"] = true --SOUNDS["VRENDER0"] = true SOUNDS["VOTRAX"] = true diff --git a/src/devices/sound/nile.cpp b/src/devices/sound/nile.cpp deleted file mode 100644 index ef05b670e57..00000000000 --- a/src/devices/sound/nile.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tomasz Slanina -/************************************ - Seta custom Nile ST-0026 chip - sound emulation by Tomasz Slanina - based on ST-0016 emulation - -8 voices, 16 words of config data for each: - - 00 - 01 - sptr ?? (always 0) - 02 - sptr LO - 03 - sptr HI - 04 - 05 - flags? 00000000 0000?L0? - bit 0 loops, other bits appear to be not used by the chip - 06 - freq - 07 - lsptr LO - 08 - 09 - lsptr HI - 0a - leptr LO - 0b - leptr HI - 0c - eptr LO - 0d - eptr HI - 0e - vol R - 0f - vol L - -************************************/ - -#include "emu.h" -#include "nile.h" - -enum -{ - NILE_REG_UNK0=0, - NILE_REG_SPTR_TOP, - NILE_REG_SPTR_LO, - NILE_REG_SPTR_HI, - NILE_REG_UNK_4, - NILE_REG_FLAGS, - NILE_REG_FREQ, - NILE_REG_LSPTR_LO, - MILE_REG_UNK_8, - NILE_REG_LSPTR_HI, - NILE_REG_LEPTR_LO, - NILE_REG_LEPTR_HI, - NILE_REG_EPTR_LO, - NILE_REG_EPTR_HI, - NILE_REG_VOL_R, - NILE_REG_VOL_L -}; - - -DEFINE_DEVICE_TYPE(NILE, nile_device, "nile", "Seta ST-0026 NiLe") - -nile_device::nile_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, NILE, tag, owner, clock), - device_sound_interface(mconfig, *this), - m_stream(nullptr), - m_sound_ram(*this, DEVICE_SELF), - m_ctrl(0) -{ -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void nile_device::device_start() -{ - m_stream = stream_alloc(0, 2, 44100); - save_item(NAME(m_sound_regs)); - save_item(NAME(m_vpos)); - save_item(NAME(m_frac)); - save_item(NAME(m_lponce)); - save_item(NAME(m_ctrl)); -} - - -//------------------------------------------------- -// sound_stream_update - handle update requests -// for our sound stream -//------------------------------------------------- - -void nile_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) -{ - uint8_t *sound_ram = &m_sound_ram[0]; - int v, i, snum; - uint16_t *slot; - int32_t mix[4800*2]; - int32_t *mixp; - int16_t sample; - int sptr, eptr, freq, lsptr, leptr; - - lsptr=leptr=0; - - sound_assert(outputs[0].samples() * 2 < std::size(mix)); - std::fill_n(&mix[0], outputs[0].samples()*2, 0); - - for (v = 0; v < NILE_VOICES; v++) - { - slot = &m_sound_regs[v * 16]; - - if (m_ctrl&(1<> 16; - *mixp++ += (sample * (int32_t)slot[NILE_REG_VOL_L]) >> 16; - - m_frac[v] += freq; - m_vpos[v] += m_frac[v]>>16; - m_frac[v] &= 0xffff; - - // stop if we're at the end - if (m_lponce[v]) - { - // we've looped once, check loop end rather than sample end - if ((m_vpos[v] + sptr) >= leptr) - { - m_vpos[v] = (lsptr - sptr); - } - } - else - { - // not looped yet, check sample end - if ((m_vpos[v] + sptr) >= eptr) - { - // code at 11d8c: - // if bit 2 (0x4) is set, check if loop start = loop end. - // if they are equal, clear bit 0 and don't set the loop start/end - // registers in the NiLe. if they aren't, set bit 0 and set - // the loop start/end registers in the NiLe. - if ((slot[NILE_REG_FLAGS] & 0x5) == 0x5) - { - m_vpos[v] = (lsptr - sptr); - m_lponce[v] = 1; - } - else - { - m_ctrl &= ~(1<update(); - - COMBINE_DATA(&m_ctrl); - -// logerror("CTRL: %04x -> %04x %s\n", ctrl, m_ctrl, machine().describe_context()); - - ctrl^=m_ctrl; -} - - -uint16_t nile_device::nile_sndctrl_r() -{ - m_stream->update(); - return m_ctrl; -} - - -uint16_t nile_device::nile_snd_r(offs_t offset) -{ - int reg=offset&0xf; - - m_stream->update(); - - if(reg==2 || reg==3) - { - int slot=offset/16; - int sptr = ((m_sound_regs[slot*16+3]<<16)|m_sound_regs[slot*16+2])+m_vpos[slot]; - - if(reg==2) - { - return sptr&0xffff; - } - else - { - return sptr>>16; - } - } - return m_sound_regs[offset]; -} - - -void nile_device::nile_snd_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - int v, r; - - m_stream->update(); - - COMBINE_DATA(&m_sound_regs[offset]); - - v = offset / 16; - r = offset % 16; - - if ((r == 2) || (r == 3)) - { - m_vpos[v] = m_frac[v] = m_lponce[v] = 0; - } - - //logerror("v%02d: %04x to reg %02d (PC=%x)\n", v, m_sound_regs[offset], r, machine().describe_context()); -} diff --git a/src/devices/sound/nile.h b/src/devices/sound/nile.h deleted file mode 100644 index 61add38d44e..00000000000 --- a/src/devices/sound/nile.h +++ /dev/null @@ -1,48 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tomasz Slanina -#ifndef MAME_SOUND_NILE_H -#define MAME_SOUND_NILE_H - -#pragma once - - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> nile_device - -class nile_device : public device_t, - public device_sound_interface -{ -public: - nile_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - // device-level overrides - virtual void device_start() override; - - // sound stream update overrides - virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; - -public: - void nile_snd_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t nile_snd_r(offs_t offset); - void nile_sndctrl_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t nile_sndctrl_r(); - -private: - static constexpr unsigned NILE_VOICES = 8; - - sound_stream *m_stream; - required_region_ptr m_sound_ram; - uint16_t m_sound_regs[0x80]; - int m_vpos[NILE_VOICES]; - int m_frac[NILE_VOICES]; - int m_lponce[NILE_VOICES]; - uint16_t m_ctrl; -}; - -DECLARE_DEVICE_TYPE(NILE, nile_device) - -#endif // MAME_SOUND_NILE_H diff --git a/src/devices/sound/setapcm.cpp b/src/devices/sound/setapcm.cpp new file mode 100644 index 00000000000..a97e0ded106 --- /dev/null +++ b/src/devices/sound/setapcm.cpp @@ -0,0 +1,429 @@ +// license:BSD-3-Clause +// copyright-holders:Tomasz Slanina,cam900 +/************************************ + Seta PCM emulation + sound emulation by Tomasz Slanina + based on ST-0016 emulation + + used by + - ST-0026 NiLe (srmp6, 8 voices) + - ST-0032 (jclub2, 16 voices) + - Capcom CPS3 sound hardware has similarity? + + Register Format (32 byte per voices) + + 00-1f: Voice 0 + Offset Bit Description + fedcba98 76543210 + 04 xxxxxxxx xxxxxxxx Start position LSB + 06 xxxxxxxx xxxxxxxx Start position MSB + 0a -------- ----xxx- Used but unknown + -------- -----x-- See below for NiLe specific? notes + -------- -------x Loop enable + 0c xxxxxxxx xxxxxxxx Frequency + 0e xxxxxxxx xxxxxxxx Loop Start position LSB + 12 xxxxxxxx xxxxxxxx Loop Start position MSB + 14 xxxxxxxx xxxxxxxx Loop End position LSB + 16 xxxxxxxx xxxxxxxx Loop End position MSB + 18 xxxxxxxx xxxxxxxx End position LSB + 1a xxxxxxxx xxxxxxxx End position MSB + 1c xxxxxxxx xxxxxxxx Right Volume + 1e xxxxxxxx xxxxxxxx Left Volume + + 20-3f: Voice 1 + ... + e0-ff: Voice 7 + + 100: Keyon/off, Bit 0-7 means Voice 0-7 + 110: Used but unknown + + below for 16 voice configurations: + 100-11f: Voice 8 + 120-13f: Voice 9 + ... + 1e0-1ff: Voice 15 + + 200: Keyon/off, Bit 0-15 means Voice 0-15 + 210: Used but unknown + + Other registers are unknown/unused + + TODO: + - Verify loop and flag bit behavior from real hardware + +************************************/ + +#include "emu.h" +#include "setapcm.h" + +// constants +template +constexpr unsigned setapcm_device::MAX_VOICES; +template +constexpr unsigned setapcm_device::CLOCK_DIVIDER; + +// device type definition +DEFINE_DEVICE_TYPE(NILE_SOUND, nile_sound_device, "nile_sound", "Seta ST-0026 NiLe (Sound)") +DEFINE_DEVICE_TYPE(ST0032_SOUND, st0032_sound_device, "st0032_sound", "Seta ST-0032 (Sound)") + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// setapcm_device - constructor +//------------------------------------------------- + +template +setapcm_device::setapcm_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, type, tag, owner, clock) + , device_sound_interface(mconfig, *this) + , device_rom_interface(mconfig, *this) + , m_stream(nullptr) + , m_keyctrl(0) +{ +} + +nile_sound_device::nile_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : setapcm_device<8, 160>(mconfig, NILE_SOUND, tag, owner, clock) +{ +} + +st0032_sound_device::st0032_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : setapcm_device<16, 384>(mconfig, ST0032_SOUND, tag, owner, clock) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +template +void setapcm_device::device_start() +{ + // allocate stream + m_stream = stream_alloc(0, 2, clock() / CLOCK_DIVIDER); + + // set host device to each voices + for (auto & elem : m_voice) + elem.m_host = this; + + save_item(STRUCT_MEMBER(m_voice, m_start)); + save_item(STRUCT_MEMBER(m_voice, m_flags)); + save_item(STRUCT_MEMBER(m_voice, m_freq)); + save_item(STRUCT_MEMBER(m_voice, m_lpstart)); + save_item(STRUCT_MEMBER(m_voice, m_lpend)); + save_item(STRUCT_MEMBER(m_voice, m_end)); + save_item(STRUCT_MEMBER(m_voice, m_vol_r)); + save_item(STRUCT_MEMBER(m_voice, m_vol_l)); + 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_keyon)); + save_item(STRUCT_MEMBER(m_voice, m_out)); + + save_item(NAME(m_keyctrl)); +} + +//------------------------------------------------- +// device_clock_changed - called if the clock +// changes +//------------------------------------------------- + +template +void setapcm_device::device_clock_changed() +{ + m_stream->set_sample_rate(clock() / CLOCK_DIVIDER); +} + +//------------------------------------------------- +// sound_stream_update - handle update requests +// for our sound stream +//------------------------------------------------- + +template +void setapcm_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) +{ + outputs[0].fill(0); + outputs[1].fill(0); + + for (int sampleind = 0; sampleind < outputs[0].samples(); sampleind++) + { + for (int v = 0; v < MAX_VOICES; v++) + { + // check if voice is activated + if (m_voice[v].update()) + { + outputs[0].add_int(sampleind, (m_voice[v].m_out * m_voice[v].m_vol_l) >> 16, 32768 * MAX_VOICES); + outputs[1].add_int(sampleind, (m_voice[v].m_out * m_voice[v].m_vol_r) >> 16, 32768 * MAX_VOICES); + } + } + } +} + +//------------------------------------------------- +// rom_bank_updated - the rom bank has changed +//------------------------------------------------- + +template +void setapcm_device::rom_bank_updated() +{ + m_stream->update(); +} + +//------------------------------------------------- +// update - update single voice +//------------------------------------------------- + +template +bool setapcm_device::voice_t::update() +{ + if (m_keyon) + { + // fetch sample + m_out = s16(s8(m_host->read_byte(m_pos))) << 8; + + // advance + m_frac += m_freq; + m_pos += m_frac >> 12; + m_frac &= 0xfff; + + // 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) + { + // code at 11d8c: + // if bit 2 (0x4) is set, check if loop start = loop end. + // if they are equal, clear bit 0 and don't set the loop start/end + // registers in the NiLe. if they aren't, set bit 0 and set + // the loop start/end registers in the NiLe. + // TODO: ST-0032 has same behavior? + if (BIT(m_flags, 0)) + { + m_pos = m_lpstart; + m_lponce = true; + } + else + { + m_keyon = false; + } + } + } + return true; + } + // clear output + m_out = 0; + return false; +} + +//------------------------------------------------- +// keyon - set keyon flag for single voice +//------------------------------------------------- + +template +void setapcm_device::voice_t::keyon() +{ + m_keyon = true; + m_pos = m_start; + m_frac = 0; + m_lponce = false; +} + +//------------------------------------------------- +// keyoff - set keyoff flag for single voice +//------------------------------------------------- + +template +void setapcm_device::voice_t::keyoff() +{ + m_keyon = false; +} + +//------------------------------------------------- +// reg_r - read single voice registers +//------------------------------------------------- + +template +u16 setapcm_device::voice_t::reg_r(offs_t reg) +{ + u16 ret = 0; + switch (reg & 0xf) + { + case 0x02: // Current position LSB + ret = m_pos & 0xffff; + break; + case 0x03: // Current position MSB + ret = m_pos >> 16; + break; + case 0x05: // Flags + ret = m_flags; + break; + case 0x06: // Frequency + ret = m_freq; + break; + case 0x07: // Loop start position LSB + ret = m_lpstart & 0xffff; + break; + case 0x09: // Loop start position MSB + ret = m_lpstart >> 16; + break; + case 0x0a: // Loop end position LSB + ret = m_lpend & 0xffff; + break; + case 0x0b: // Loop end position MSB + ret = m_lpend >> 16; + break; + case 0x0c: // End position LSB + ret = m_end & 0xffff; + break; + case 0x0d: // End position MSB + ret = m_end >> 16; + break; + case 0x0e: // Right volume + ret = m_vol_r; + break; + case 0x0f: // Left volume + ret = m_vol_l; + break; + } + return ret; +} + +//------------------------------------------------- +// reg_w - write single voice registers +//------------------------------------------------- + +template +void setapcm_device::voice_t::reg_w(offs_t reg, u16 data, u16 mem_mask) +{ + switch (reg & 0xf) + { + case 0x02: // Start position LSB, also affected current position? + m_start = m_pos = (m_start & ~mem_mask) | (data & mem_mask); + break; + case 0x03: // Start position MSB + m_start = m_pos = (m_start & ~(u32(mem_mask) << 16)) | (u32(data & mem_mask) << 16); + break; + case 0x05: // Flags + COMBINE_DATA(&m_flags); + break; + case 0x06: // Frequency + COMBINE_DATA(&m_freq); + break; + case 0x07: // Loop start position LSB + m_lpstart = (m_lpstart & ~mem_mask) | (data & mem_mask); + break; + case 0x09: // Loop start position MSB + m_lpstart = (m_lpstart & ~(u32(mem_mask) << 16)) | (u32(data & mem_mask) << 16); + break; + case 0x0a: // Loop end position LSB + m_lpend = (m_lpend & ~mem_mask) | (data & mem_mask); + break; + case 0x0b: // Loop end position MSB + m_lpend = (m_lpend & ~(u32(mem_mask) << 16)) | (u32(data & mem_mask) << 16); + break; + case 0x0c: // End position LSB + m_end = (m_end & ~mem_mask) | (data & mem_mask); + break; + case 0x0d: // End position MSB + m_end = (m_end & ~(u32(mem_mask) << 16)) | (u32(data & mem_mask) << 16); + break; + case 0x0e: // Right volume + COMBINE_DATA(&m_vol_r); + break; + case 0x0f: // Left volume + COMBINE_DATA(&m_vol_l); + break; + } +} + +//------------------------------------------------- +// snd_w - write each voice registers +//------------------------------------------------- + +template +void setapcm_device::snd_w(offs_t offset, u16 data, u16 mem_mask) +{ + m_stream->update(); + + const int v = (offset >> 4); + + if (v >= MAX_VOICES) + return; + + m_voice[v].reg_w(offset & 0xf, data, mem_mask); + //logerror("v%02d: %04x & %04x to reg %02d (PC=%x)\n", v, data, mem_mask, r, machine().describe_context()); +} + + +//------------------------------------------------- +// snd_r - read each voice registers +//------------------------------------------------- + +template +u16 setapcm_device::snd_r(offs_t offset) +{ + const int v = (offset >> 4); + + if (v >= MAX_VOICES) + return 0; + + m_stream->update(); + + return m_voice[v].reg_r(offset & 0xf); +} + + +//------------------------------------------------- +// key_w - set keyon/off flags for each voices +//------------------------------------------------- + +template +void setapcm_device::key_w(offs_t offset, u16 data, u16 mem_mask) +{ + const u16 prev = m_keyctrl; + + m_stream->update(); + + COMBINE_DATA(&m_keyctrl); + + //logerror("KEYCTRL: %04x -> %04x %s\n", prev, m_keyctrl, machine().describe_context()); + + for (int v = 0; v < MAX_VOICES; v++) + { + if (BIT(m_keyctrl, v) && (!(BIT(prev, v)))) // keyon + { + m_voice[v].keyon(); + } + else if ((!(BIT(m_keyctrl, v))) && BIT(prev, v)) // keyoff + { + m_voice[v].keyoff(); + } + } +} + + +//------------------------------------------------- +// key_r - get keyon/off status from each voices +//------------------------------------------------- + +template +u16 setapcm_device::key_r() +{ + m_stream->update(); + return m_keyctrl; +} + +// template class definition +template class setapcm_device<8, 160>; +template class setapcm_device<16, 384>; diff --git a/src/devices/sound/setapcm.h b/src/devices/sound/setapcm.h new file mode 100644 index 00000000000..8c406c7076f --- /dev/null +++ b/src/devices/sound/setapcm.h @@ -0,0 +1,103 @@ +// license:BSD-3-Clause +// copyright-holders:Tomasz Slanina,cam900 +#ifndef MAME_SOUND_SETAPCM_H +#define MAME_SOUND_SETAPCM_H + +#pragma once + +#include "dirom.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// device type definition +DECLARE_DEVICE_TYPE(NILE_SOUND, nile_sound_device) +DECLARE_DEVICE_TYPE(ST0032_SOUND, st0032_sound_device) + +// ======================> setapcm_device + +// TODO: unknown address bus width +template +class setapcm_device : public device_t, + public device_sound_interface, + public device_rom_interface<32> +{ +public: + void snd_w(offs_t offset, u16 data, u16 mem_mask = ~0); + u16 snd_r(offs_t offset); + + void key_w(offs_t offset, u16 data, u16 mem_mask = ~0); + u16 key_r(); + +protected: + setapcm_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_clock_changed() override; + + // sound stream update overrides + virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; + + // device_rom_interface implementation + virtual void rom_bank_updated() override; + + static constexpr unsigned MAX_VOICES = MaxVoices; // max voices + static constexpr unsigned CLOCK_DIVIDER = Divider; // clock divider for generate output rate +private: + struct voice_t + { + bool update(); + void keyon(); + void keyoff(); + + u16 reg_r(offs_t reg); + void reg_w(offs_t reg, u16 data, u16 mem_mask = ~0); + + device_rom_interface<32> *m_host; // host device + u32 m_start = 0; // Start position + u16 m_flags = 0; // Flags (Bit 0 = loop) + u16 m_freq = 0; // Frequency (4.12 fixed point) + u32 m_lpstart = 0; // Loop start position + u32 m_lpend = 0; // Loop end position + u32 m_end = 0; // End position + s32 m_vol_r = 0; // Right volume + s32 m_vol_l = 0; // Left volume + u32 m_pos = 0; // Current position + u32 m_frac = 0; // Position fraction + bool m_lponce = false; // Is looped once? + bool m_keyon = false; // Keyon status + s32 m_out = 0; // output value + }; + + sound_stream *m_stream; + + voice_t m_voice[MaxVoices]; // 8 or 16 Voice engines + u16 m_keyctrl; // Key on/off control bit +}; + +// ======================> nile_sound_device + +class nile_sound_device : public setapcm_device<8, 160> +{ +public: + nile_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +// ======================> st0032_sound_device + +class st0032_sound_device : public setapcm_device<16, 384> +{ +public: + st0032_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +//************************************************************************** +// EXTERNAL TEMPLATE INSTANTIATIONS +//************************************************************************** + +extern template class setapcm_device<8, 160>; +extern template class setapcm_device<16, 384>; + +#endif // MAME_SOUND_SETAPCM_H diff --git a/src/mame/drivers/jclub2.cpp b/src/mame/drivers/jclub2.cpp index b79042aecdf..c7a58f95912 100644 --- a/src/mame/drivers/jclub2.cpp +++ b/src/mame/drivers/jclub2.cpp @@ -105,6 +105,7 @@ #include "machine/ticket.h" #include "machine/timer.h" #include "machine/watchdog.h" +#include "sound/setapcm.h" #include "sound/okim6295.h" #include "video/st0020.h" #include "emupal.h" @@ -751,9 +752,9 @@ void jclub2_state::jclub2_map(address_map &map) map(0x880000, 0x89ffff).ram().w(m_palette, FUNC(palette_device::write32)).share("palette"); map(0x8a0000, 0x8bffff).ram(); // this should still be palette ram! map(0x8c0000, 0x8c00ff).rw(m_st0020, FUNC(st0020_device::regs_r), FUNC(st0020_device::regs_w)); - map(0x8e0000, 0x8e01ff).ram(); // sound? - map(0x8e0200, 0x8e0203).ram(); - map(0x8e0210, 0x8e0213).ram(); + map(0x8e0000, 0x8e01ff).rw("st0032_snd", FUNC(st0032_sound_device::snd_r), FUNC(st0032_sound_device::snd_w)); + map(0x8e0200, 0x8e0201).rw("st0032_snd", FUNC(st0032_sound_device::key_r), FUNC(st0032_sound_device::key_w)); + map(0x8e0210, 0x8e0213).ram(); // sound? map(0x900000, 0x9fffff).rw(m_st0020, FUNC(st0020_device::gfxram_r), FUNC(st0020_device::gfxram_w)); } @@ -1212,6 +1213,15 @@ void jclub2_state::jclub2(machine_config &config) // layout config.set_default_layout(layout_jclub2o); + + // sound hardware + // TODO: Mono? + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + st0032_sound_device &st0032_snd(ST0032_SOUND(config, "st0032_snd", XTAL(42'954'545) / 3)); // 14.318181MHz (42.954545MHz / 3) + st0032_snd.add_route(ALL_OUTPUTS, "lspeaker", 1.0); + st0032_snd.add_route(ALL_OUTPUTS, "rspeaker", 1.0); } @@ -1387,7 +1397,7 @@ Provided to you by Belgium Dump Team Gerald (COY) on 18/01/2007. ***************************************************************************/ #define JCLUB2_OTHER_ROMS \ - ROM_REGION( 0x100000, "samples", 0 ) \ + ROM_REGION( 0x100000, "st0032_snd", 0 ) \ ROM_LOAD( "m88-02.u6", 0x00000, 0x100000, CRC(0dd3436a) SHA1(809d3b7a26d36f71da04036fd8ab5d0c5089392a) ) \ \ ROM_REGION( 0x117, "pld", 0 ) \ @@ -1548,10 +1558,10 @@ GAME( 1996, jclub2v110, jclub2v112, jclub2o, jclub2v100, jclub2o_state, init_j GAME( 1996, jclub2v112, 0, jclub2o, jclub2v112, jclub2o_state, init_jclub2o, ROT0, "Seta", "Jockey Club II (v1.12X, older hardware)", MACHINE_IMPERFECT_GRAPHICS ) GAME( 1997, jclub2v203, jclub2v112, jclub2o, jclub2v112, jclub2o_state, init_jclub2o, ROT0, "Seta", "Jockey Club II (v2.03X RC, older hardware, prototype)", MACHINE_IMPERFECT_GRAPHICS ) // Newer hardware (ST-0032) -GAME( 1996, jclub2v200, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.00, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND ) -GAME( 1996, jclub2v201, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.01X, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND ) -GAME( 1997, jclub2v204, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.04, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND ) -GAME( 1997, jclub2v205, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.05, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND ) -GAME( 1998, jclub2v220, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.20X, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND ) +GAME( 1996, jclub2v200, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.00, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) +GAME( 1996, jclub2v201, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.01X, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) +GAME( 1997, jclub2v204, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.04, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) +GAME( 1997, jclub2v205, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.05, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) +GAME( 1998, jclub2v220, jclub2v112, jclub2, jclub2v112, jclub2_state, empty_init, ROT0, "Seta", "Jockey Club II (v2.20X, newer hardware)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // Bootleg hardware GAME( 2001, darkhors, jclub2v112, darkhors, darkhors, darkhors_state, init_darkhors, ROT0, "bootleg", "Dark Horse (USA v4.00, bootleg of Jockey Club II)", MACHINE_IMPERFECT_GRAPHICS ) diff --git a/src/mame/drivers/srmp6.cpp b/src/mame/drivers/srmp6.cpp index 6fc96e6f31e..df8257e30f7 100644 --- a/src/mame/drivers/srmp6.cpp +++ b/src/mame/drivers/srmp6.cpp @@ -73,7 +73,7 @@ Dumped 06/15/2000 #include "emu.h" #include "cpu/m68000/m68000.h" #include "video/bufsprite.h" -#include "sound/nile.h" +#include "sound/setapcm.h" #include "emupal.h" #include "screen.h" #include "speaker.h" @@ -568,8 +568,8 @@ void srmp6_state::srmp6_map(address_map &map) map(0x4c0000, 0x4c006f).rw(FUNC(srmp6_state::video_regs_r), FUNC(srmp6_state::video_regs_w)).share(m_video_regs); // ? gfx regs ST-0026 NiLe map(0x4d0000, 0x4d0001).r(FUNC(srmp6_state::irq_ack_r)); - map(0x4e0000, 0x4e00ff).rw("nile", FUNC(nile_device::nile_snd_r), FUNC(nile_device::nile_snd_w)); - map(0x4e0100, 0x4e0101).rw("nile", FUNC(nile_device::nile_sndctrl_r), FUNC(nile_device::nile_sndctrl_w)); + map(0x4e0000, 0x4e00ff).rw("nile", FUNC(nile_sound_device::snd_r), FUNC(nile_sound_device::snd_w)); + map(0x4e0100, 0x4e0101).rw("nile", FUNC(nile_sound_device::key_r), FUNC(nile_sound_device::key_w)); //map(0x4e0110, 0x4e0111).noprw(); // ? accessed once ($268dc, written $b.w) // CHR RAM: checked [$500000-$5fffff] @@ -704,7 +704,8 @@ void srmp6_state::srmp6(machine_config &config) SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); - nile_device &nile(NILE(config, "nile", 0)); + // matches video, needs to verified; playback rate: (42.9545Mhz / 7) / 160 or (42.9545Mhz / 5) / 224 or (42.9545Mhz / 4) / 280? + nile_sound_device &nile(NILE_SOUND(config, "nile", XTAL(42'954'545) / 7)); nile.add_route(0, "lspeaker", 1.0); nile.add_route(1, "rspeaker", 1.0); } -- cgit v1.2.3