diff --git a/src/devices/sound/huc6230.cpp b/src/devices/sound/huc6230.cpp index 07fe59514ed..7969e1c3ae0 100644 --- a/src/devices/sound/huc6230.cpp +++ b/src/devices/sound/huc6230.cpp @@ -2,15 +2,17 @@ // copyright-holders:cam900 /* Hudson HuC6230 SoundBox - HuC6280 PSG with ADPCM + PSG part of HuC6280 with ADPCM TODO: - Volume is linear? - Make it actually working - - Implement CDDA Volume + - Implement/Correct VCA (Voltage Controlled Amplifier) behavior Related patent: - https://patents.google.com/patent/US5692099 + - https://patents.google.com/patent/US6453286 + - https://patents.google.com/patent/US5548655A */ #include "emu.h" @@ -33,8 +35,8 @@ void huc6230_device::sound_stream_update(sound_stream &stream, stream_sample_t * if (!channel->m_playing) continue; - outputs[0][i] = clamp(outputs[0][i] + ((channel->m_output * channel->m_lvol) >> 2), -32768, 32767); - outputs[1][i] = clamp(outputs[1][i] + ((channel->m_output * channel->m_rvol) >> 2), -32768, 32767); + outputs[0][i] = clamp(outputs[0][i] + ((channel->m_output * channel->m_lvol) >> 3), -32768, 32767); + outputs[1][i] = clamp(outputs[1][i] + ((channel->m_output * channel->m_rvol) >> 3), -32768, 32767); } } } @@ -83,19 +85,19 @@ WRITE8_MEMBER( huc6230_device::write ) } else if (offset < 0x16) { - m_cdda_lvol = data & 0x3f; - m_cdda_cb(0, m_cdda_lvol); + m_pcm_lvol = data & 0x3f; + m_vca_cb(0, m_pcm_lvol); } else if (offset < 0x17) { - m_cdda_rvol = data & 0x3f; - m_cdda_cb(1, m_cdda_rvol); + m_pcm_rvol = data & 0x3f; + m_vca_cb(1, m_pcm_rvol); } } TIMER_CALLBACK_MEMBER(huc6230_device::adpcm_timer) { - int frq = (1 << m_adpcm_freq); + const unsigned frq = (1 << m_adpcm_freq); for (int adpcm = 0; adpcm < 2; adpcm++) { adpcm_channel *channel = &m_adpcm_channel[adpcm]; @@ -113,7 +115,7 @@ TIMER_CALLBACK_MEMBER(huc6230_device::adpcm_timer) channel->m_pos++; channel->m_input = m_adpcm_update_cb[adpcm](); - if (channel->m_pos > frq) + if (channel->m_pos >= frq) { channel->m_pos = 0; channel->m_prev_sample = channel->m_curr_sample; @@ -143,10 +145,10 @@ huc6230_device::huc6230_device(const machine_config &mconfig, const char *tag, d , m_stream(nullptr) , m_psg(*this, "psg") , m_adpcm_freq(0) - , m_cdda_lvol(0) - , m_cdda_rvol(0) + , m_pcm_lvol(0) + , m_pcm_rvol(0) , m_adpcm_update_cb{{*this}, {*this}} - , m_cdda_cb(*this) + , m_vca_cb(*this) { } @@ -169,9 +171,9 @@ void huc6230_device::device_start() for (auto &cb : m_adpcm_update_cb) cb.resolve_safe(0); - m_cdda_cb.resolve_safe(); + m_vca_cb.resolve_safe(); - m_stream = machine().sound().stream_alloc(*this, 2, 2, clock() / 96); + m_stream = machine().sound().stream_alloc(*this, 2, 2, clock() / 6); m_adpcm_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(huc6230_device::adpcm_timer),this)); for (int i = 0; i < 2; i++) @@ -196,13 +198,13 @@ void huc6230_device::device_start() save_item(NAME(m_adpcm_channel[i].m_input), i); } save_item(NAME(m_adpcm_freq)); - save_item(NAME(m_cdda_lvol)); - save_item(NAME(m_cdda_rvol)); + save_item(NAME(m_pcm_lvol)); + save_item(NAME(m_pcm_rvol)); } void huc6230_device::device_clock_changed() { - m_stream->set_sample_rate(clock() / 96); + m_stream->set_sample_rate(clock() / 6); attotime adpcm_period = clocks_to_attotime(682); m_adpcm_timer->adjust(adpcm_period, 0, adpcm_period); } diff --git a/src/devices/sound/huc6230.h b/src/devices/sound/huc6230.h index 6cd26955191..d94c59fcb26 100644 --- a/src/devices/sound/huc6230.h +++ b/src/devices/sound/huc6230.h @@ -11,10 +11,12 @@ class huc6230_device : public device_t, public device_sound_interface { public: + static constexpr feature_type imperfect_features() { return feature::SOUND; } // Incorrect ADPCM + huc6230_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); template auto adpcm_update_cb() { return m_adpcm_update_cb[N].bind(); } - auto cdda_cb() { return m_cdda_cb.bind(); } + auto vca_callback() { return m_vca_cb.bind(); } // write only DECLARE_WRITE8_MEMBER( write ); @@ -48,13 +50,13 @@ private: required_device m_psg; adpcm_channel m_adpcm_channel[2]; uint32_t m_adpcm_freq; - uint32_t m_cdda_lvol; - uint32_t m_cdda_rvol; + uint32_t m_pcm_lvol; + uint32_t m_pcm_rvol; TIMER_CALLBACK_MEMBER(adpcm_timer); devcb_read8 m_adpcm_update_cb[2]; - devcb_write8 m_cdda_cb; + devcb_write8 m_vca_cb; }; DECLARE_DEVICE_TYPE(HuC6230, huc6230_device) diff --git a/src/devices/video/huc6272.cpp b/src/devices/video/huc6272.cpp index b091b67afb9..d1fca5708ce 100644 --- a/src/devices/video/huc6272.cpp +++ b/src/devices/video/huc6272.cpp @@ -10,6 +10,8 @@ ADPCM related patents: - https://patents.google.com/patent/US5692099 + - https://patents.google.com/patent/US6453286 + - https://patents.google.com/patent/US5548655A ***************************************************************************/ @@ -497,9 +499,9 @@ uint8_t huc6272_device::adpcm_update(int chan) if (!m_adpcm.playing[chan]) return 0; - int rate = (1 << m_adpcm.rate); + const unsigned rate = (1 << m_adpcm.rate); m_adpcm.pos[chan]++; - if (m_adpcm.pos[chan] > rate) + if (m_adpcm.pos[chan] >= rate) { if (m_adpcm.input[chan] == -1) { @@ -541,6 +543,7 @@ uint8_t huc6272_device::adpcm_update(int chan) if (m_adpcm.nibble[chan] >= 28) m_adpcm.input[chan] = -1; } + m_adpcm.pos[chan] = 0; } return (m_adpcm.input[chan] >> m_adpcm.nibble[chan]) & 0xf; diff --git a/src/devices/video/huc6272.h b/src/devices/video/huc6272.h index 8d7f0583600..8380482f38b 100644 --- a/src/devices/video/huc6272.h +++ b/src/devices/video/huc6272.h @@ -27,6 +27,8 @@ class huc6272_device : public device_t, public device_memory_interface { public: + static constexpr feature_type imperfect_features() { return feature::SOUND | feature::GRAPHICS; } // Incorrect ADPCM and Graphics + // construction/destruction huc6272_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); diff --git a/src/mame/drivers/pcfx.cpp b/src/mame/drivers/pcfx.cpp index 1af2bae8519..6a3e20ec232 100644 --- a/src/mame/drivers/pcfx.cpp +++ b/src/mame/drivers/pcfx.cpp @@ -455,7 +455,7 @@ void pcfx_state::pcfx(machine_config &config) huc6230_device &huc6230(HuC6230(config, "huc6230", XTAL(21'477'272))); huc6230.adpcm_update_cb<0>().set("huc6272", FUNC(huc6272_device::adpcm_update_0)); huc6230.adpcm_update_cb<1>().set("huc6272", FUNC(huc6272_device::adpcm_update_1)); - huc6230.cdda_cb().set("huc6272", FUNC(huc6272_device::cdda_update)); + huc6230.vca_callback().set("huc6272", FUNC(huc6272_device::cdda_update)); huc6230.add_route(0, "lspeaker", 1.0); huc6230.add_route(1, "rspeaker", 1.0); }