From b8c8f9423aac5ea785f5e67df996c97392db2509 Mon Sep 17 00:00:00 2001 From: cam900 Date: Mon, 3 Sep 2018 11:31:52 +0900 Subject: huc6230.cpp : Fix PSG, Timer'd ADPCM update, Implement CD-DA Volume (#3919) huc6272.cpp : Make CD-DA Playable --- src/devices/sound/huc6230.cpp | 88 ++++++++++++++++++++++++++++++------------- src/devices/sound/huc6230.h | 6 +++ src/devices/video/huc6272.cpp | 21 +++++++++++ src/devices/video/huc6272.h | 8 ++++ src/mame/drivers/pcfx.cpp | 1 + 5 files changed, 97 insertions(+), 27 deletions(-) diff --git a/src/devices/sound/huc6230.cpp b/src/devices/sound/huc6230.cpp index 9b77d1f83c0..ce5ee4b3e2e 100644 --- a/src/devices/sound/huc6230.cpp +++ b/src/devices/sound/huc6230.cpp @@ -18,17 +18,11 @@ constexpr int clamp(int val, int min, int max) { return std::min(max, std::max(m void huc6230_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { - int frq = (1 << m_adpcm_freq); for (int i = 0; i < samples; i++) { outputs[0][i] = inputs[0][i]; outputs[1][i] = inputs[1][i]; - int cdda_l = inputs[2][i]; - int cdda_r = inputs[3][i]; - outputs[0][i] = clamp(outputs[0][i] + ((cdda_l * m_cdda_lvol) >> 6), -32768, 32767); - outputs[1][i] = clamp(outputs[1][i] + ((cdda_r * m_cdda_rvol) >> 6), -32768, 32767); - for (int adpcm = 0; adpcm < 2; adpcm++) { adpcm_channel *channel = &m_adpcm_channel[adpcm]; @@ -36,25 +30,8 @@ void huc6230_device::sound_stream_update(sound_stream &stream, stream_sample_t * if (!channel->m_playing) continue; - int32_t sample; - - channel->m_pos++; - channel->m_input = m_adpcm_update_cb[adpcm](); - - if (channel->m_pos > frq) - { - channel->m_pos = 0; - channel->m_prev_sample = channel->m_curr_sample; - channel->m_curr_sample = channel->m_adpcm.clock(channel->m_input & 0xf); - } - if (!channel->m_interpolate) - sample = channel->m_curr_sample; - else - sample = ((channel->m_prev_sample * (frq - channel->m_pos)) + - (channel->m_curr_sample * channel->m_pos)) >> m_adpcm_freq; - - outputs[0][i] = clamp(outputs[0][i] + ((sample * channel->m_lvol) >> 2), -32768, 32767); - outputs[1][i] = clamp(outputs[1][i] + ((sample * channel->m_rvol) >> 2), -32768, 32767); + 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); } } } @@ -84,6 +61,7 @@ WRITE8_MEMBER( huc6230_device::write ) m_adpcm_channel[i].m_playing = 0; m_adpcm_channel[i].m_prev_sample = 0; m_adpcm_channel[i].m_curr_sample = 0; + m_adpcm_channel[i].m_output = 0; m_adpcm_channel[i].m_pos = 0; } else @@ -101,9 +79,57 @@ WRITE8_MEMBER( huc6230_device::write ) m_adpcm_channel[offset >> 1].m_rvol = data & 0x3f; } else if (offset < 0x16) + { m_cdda_lvol = data & 0x3f; + m_cdda_cb(0, m_cdda_lvol); + } else if (offset < 0x17) + { m_cdda_rvol = data & 0x3f; + m_cdda_cb(1, m_cdda_rvol); + } +} + +TIMER_CALLBACK_MEMBER(huc6230_device::adpcm_timer) +{ + int frq = (1 << m_adpcm_freq); + for (int adpcm = 0; adpcm < 2; adpcm++) + { + adpcm_channel *channel = &m_adpcm_channel[adpcm]; + + if (!channel->m_playing) + { + if (channel->m_output != 0) + { + m_stream->update(); + channel->m_output = 0; + } + continue; + } + + channel->m_pos++; + channel->m_input = m_adpcm_update_cb[adpcm](); + + if (channel->m_pos > frq) + { + channel->m_pos = 0; + channel->m_prev_sample = channel->m_curr_sample; + channel->m_curr_sample = channel->m_adpcm.clock(channel->m_input & 0xf); + } + + int32_t new_output; + if (!channel->m_interpolate) + new_output = channel->m_curr_sample; + else + new_output = ((channel->m_prev_sample * (frq - channel->m_pos)) + + (channel->m_curr_sample * channel->m_pos)) >> m_adpcm_freq; + + if (channel->m_output != new_output) + { + m_stream->update(); + channel->m_output = new_output; + } + } } DEFINE_DEVICE_TYPE(HuC6230, huc6230_device, "huc6230", "Hudson Soft HuC6230 SoundBox") @@ -117,6 +143,7 @@ huc6230_device::huc6230_device(const machine_config &mconfig, const char *tag, d , m_cdda_lvol(0) , m_cdda_rvol(0) , m_adpcm_update_cb{{*this}, {*this}} + , m_cdda_cb(*this) { } @@ -139,13 +166,17 @@ void huc6230_device::device_start() for (auto &cb : m_adpcm_update_cb) cb.resolve_safe(0); - m_stream = machine().sound().stream_alloc(*this, 4, 2, clock() / 682); // or /672? + m_cdda_cb.resolve_safe(); + + m_stream = machine().sound().stream_alloc(*this, 2, 2, clock() / 96); + m_adpcm_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(huc6230_device::adpcm_timer),this)); for (int i = 0; i < 2; i++) { m_adpcm_channel[i].m_playing = 0; m_adpcm_channel[i].m_prev_sample = 0; m_adpcm_channel[i].m_curr_sample = 0; + m_adpcm_channel[i].m_output = 0; m_adpcm_channel[i].m_pos = 0; m_adpcm_channel[i].m_input = 0; @@ -157,6 +188,7 @@ void huc6230_device::device_start() save_item(NAME(m_adpcm_channel[i].m_playing), i); save_item(NAME(m_adpcm_channel[i].m_prev_sample), i); save_item(NAME(m_adpcm_channel[i].m_curr_sample), i); + save_item(NAME(m_adpcm_channel[i].m_output), i); save_item(NAME(m_adpcm_channel[i].m_pos), i); save_item(NAME(m_adpcm_channel[i].m_input), i); } @@ -167,5 +199,7 @@ void huc6230_device::device_start() void huc6230_device::device_clock_changed() { - m_stream->set_sample_rate(clock() / 682); + m_stream->set_sample_rate(clock() / 96); + 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 632dbee80de..6cd26955191 100644 --- a/src/devices/sound/huc6230.h +++ b/src/devices/sound/huc6230.h @@ -14,6 +14,7 @@ public: 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(); } // write only DECLARE_WRITE8_MEMBER( write ); @@ -36,19 +37,24 @@ private: uint8_t m_playing; int32_t m_prev_sample; int32_t m_curr_sample; + int32_t m_output; uint32_t m_pos; uint8_t m_input; }; // internal state sound_stream *m_stream; + emu_timer *m_adpcm_timer; 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; + TIMER_CALLBACK_MEMBER(adpcm_timer); + devcb_read8 m_adpcm_update_cb[2]; + devcb_write8 m_cdda_cb; }; DECLARE_DEVICE_TYPE(HuC6230, huc6230_device) diff --git a/src/devices/video/huc6272.cpp b/src/devices/video/huc6272.cpp index 8fd271afc0a..c6e94bb9810 100644 --- a/src/devices/video/huc6272.cpp +++ b/src/devices/video/huc6272.cpp @@ -47,6 +47,8 @@ huc6272_device::huc6272_device(const machine_config &mconfig, const char *tag, d : device_t(mconfig, HUC6272, tag, owner, clock), device_memory_interface(mconfig, *this), m_huc6271(*this, finder_base::DUMMY_TAG), + m_cdda_l(*this, "cdda_l"), + m_cdda_r(*this, "cdda_r"), m_program_space_config("microprg", ENDIANNESS_LITTLE, 16, 4, 0, address_map_constructor(), address_map_constructor(FUNC(huc6272_device::microprg_map), this)), m_data_space_config("kram", ENDIANNESS_LITTLE, 32, 21, 0, address_map_constructor(), address_map_constructor(FUNC(huc6272_device::kram_map), this)), m_microprg_ram(*this, "microprg_ram"), @@ -547,6 +549,14 @@ READ8_MEMBER(huc6272_device::adpcm_update_1) return adpcm_update(1); } +WRITE8_MEMBER(huc6272_device::cdda_update) +{ + if (offset) + m_cdda_r->set_output_gain(ALL_OUTPUTS, float(data) / 63.0); + else + m_cdda_l->set_output_gain(ALL_OUTPUTS, float(data) / 63.0); +} + void huc6272_device::interrupt_update() { if (m_adpcm.interrupt) @@ -555,12 +565,22 @@ void huc6272_device::interrupt_update() m_irq_changed_cb(CLEAR_LINE); } +void huc6272_device::cdrom_config(device_t *device) +{ + device = device->subdevice("cdda"); + MCFG_SOUND_ROUTE(0, "^^cdda_l", 1.0) + MCFG_SOUND_ROUTE(1, "^^cdda_r", 1.0) +} + //------------------------------------------------- // device_add_mconfig - add device configuration //------------------------------------------------- void huc6272_device::device_add_mconfig(machine_config &config) { + SPEAKER(config, m_cdda_l).front_left(); + SPEAKER(config, m_cdda_r).front_right(); + scsi_port_device &scsibus(SCSI_PORT(config, "scsi")); scsibus.set_data_input_buffer("scsi_data_in"); scsibus.rst_handler().set("scsi_ctrl_in", FUNC(input_buffer_device::write_bit7)); @@ -578,4 +598,5 @@ void huc6272_device::device_add_mconfig(machine_config &config) INPUT_BUFFER(config, "scsi_data_in"); scsibus.set_slot_device(1, "cdrom", SCSICD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_1)); + scsibus.slot(1).set_option_machine_config("cdrom", cdrom_config); } diff --git a/src/devices/video/huc6272.h b/src/devices/video/huc6272.h index a20b94e530e..cd931a1dae9 100644 --- a/src/devices/video/huc6272.h +++ b/src/devices/video/huc6272.h @@ -14,6 +14,7 @@ #include "bus/scsi/scsi.h" #include "bus/scsi/scsicd.h" #include "video/huc6271.h" +#include "speaker.h" //************************************************************************** @@ -51,6 +52,11 @@ public: DECLARE_READ8_MEMBER( adpcm_update_0 ); DECLARE_READ8_MEMBER( adpcm_update_1 ); + // CD-DA operations + DECLARE_WRITE8_MEMBER( cdda_update ); + + static void cdrom_config(device_t *device); + protected: // device-level overrides virtual void device_validity_check(validity_checker &valid) const override; @@ -61,6 +67,8 @@ protected: private: required_device m_huc6271; + required_device m_cdda_l; + required_device m_cdda_r; uint8_t m_register; uint32_t m_kram_addr_r, m_kram_addr_w; diff --git a/src/mame/drivers/pcfx.cpp b/src/mame/drivers/pcfx.cpp index 5a38480311f..4562f434752 100644 --- a/src/mame/drivers/pcfx.cpp +++ b/src/mame/drivers/pcfx.cpp @@ -454,6 +454,7 @@ MACHINE_CONFIG_START(pcfx_state::pcfx) 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.add_route(0, "lspeaker", 1.0); huc6230.add_route(1, "rspeaker", 1.0); MACHINE_CONFIG_END -- cgit v1.2.3