From d950be1132b9fbe7a3b126cdeb76d674f67aae00 Mon Sep 17 00:00:00 2001 From: ValleyBell Date: Tue, 21 Jun 2022 23:19:31 +0200 Subject: fix Sega Pico PCM playback (#9965) - fix uPD775x type - enforce "slave" mode (required for manual data stream) - hook up "PCM FIFO empty" interrupt --- src/devices/sound/315-5641.cpp | 61 +++++++++++++++++++++++++++++++++++++++--- src/devices/sound/315-5641.h | 9 ++++++- src/mame/drivers/segapico.cpp | 17 +++--------- 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/src/devices/sound/315-5641.cpp b/src/devices/sound/315-5641.cpp index c028506c64a..7b5f06b0d8b 100644 --- a/src/devices/sound/315-5641.cpp +++ b/src/devices/sound/315-5641.cpp @@ -8,13 +8,19 @@ DEFINE_DEVICE_TYPE(SEGA_315_5641_PCM, sega_315_5641_pcm_device, "315_5641_pcm", "Sega 315-5641 PCM") sega_315_5641_pcm_device::sega_315_5641_pcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : upd7756_device(mconfig, SEGA_315_5641_PCM, tag, owner, clock), m_fifo_read(0), m_fifo_write(0) + : upd7759_device(mconfig, SEGA_315_5641_PCM, tag, owner, clock) + , m_fifocallback(*this) + , m_fifo_read(0) + , m_fifo_write(0) { + m_md = 0; // enforce "slave" mode } void sega_315_5641_pcm_device::device_start() { - upd7756_device::device_start(); + m_fifocallback.resolve_safe(); + + upd7759_device::device_start(); save_item(NAME(m_fifo_data), 0x40); save_item(NAME(m_fifo_read)); @@ -34,12 +40,17 @@ void sega_315_5641_pcm_device::advance_state() { m_fifo_in = m_fifo_data[fiforead]; m_fifo_read = fiforead; + if (get_fifo_space() == 0x3F) + { + m_fifo_empty = true; + m_fifocallback(1); + } } } break; } - upd7756_device::advance_state(); + upd7759_device::advance_state(); } @@ -54,10 +65,48 @@ void sega_315_5641_pcm_device::port_w(u8 data) { m_fifo_data[m_fifo_write++] = data; m_fifo_write &= 0x3F; + if (m_fifo_empty) + { + m_fifo_empty = false; + m_fifocallback(0); + } } } +void sega_315_5641_pcm_device::fifo_reset_w(u8 data) +{ + bool reset = !!(data & 1); + if (!m_fifo_reset && reset) + { + m_fifo_read = 0x3F; + m_fifo_write = 0x00; + if (m_fifo_empty) + m_fifocallback(0); + m_fifo_empty = false; + } + m_fifo_reset = reset; +} + +void sega_315_5641_pcm_device::internal_start_w(int state) +{ + uint8_t oldstart = m_start; + uint8_t newstart = (state != 0); + + if (!m_md && m_reset && !oldstart && newstart) + { + // Somewhere between "Reset Off" and the first sample data, + // we need to send a few commands to make the sample stream work. + // Doing that when rising the "start" line seems to work fine. + port_w(0xFF); // "Last Sample" value (must be >= 0x10) + port_w(0x00); // Dummy 1 + port_w(0x00); // Addr MSB + port_w(0x00); // Addr LSB + } + + upd7759_device::internal_start_w(state); +} + uint8_t sega_315_5641_pcm_device::get_fifo_space() { return (m_fifo_read - m_fifo_write) & 0x3F; @@ -65,8 +114,12 @@ uint8_t sega_315_5641_pcm_device::get_fifo_space() void sega_315_5641_pcm_device::device_reset() { - upd7756_device::device_reset(); + upd7759_device::device_reset(); m_fifo_read = 0x3F; m_fifo_write = 0x00; + m_fifo_reset = false; + if (m_fifo_empty) + m_fifocallback(0); + m_fifo_empty = false; } diff --git a/src/devices/sound/315-5641.h b/src/devices/sound/315-5641.h index f910aa7b84b..2f986a912f0 100644 --- a/src/devices/sound/315-5641.h +++ b/src/devices/sound/315-5641.h @@ -13,25 +13,32 @@ #include "upd7759.h" -class sega_315_5641_pcm_device : public upd7756_device +class sega_315_5641_pcm_device : public upd7759_device { public: sega_315_5641_pcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + auto fifo_cb() { return m_fifocallback.bind(); } virtual void port_w(u8 data) override; + void fifo_reset_w(u8 data); uint8_t get_fifo_space(); protected: // device-level overrides + virtual void internal_start_w(int state) override; + virtual void device_start() override; virtual void device_reset() override; virtual void advance_state() override; + devcb_write_line m_fifocallback; uint8_t m_fifo_data[0x40]; uint8_t m_fifo_read; // last read offset (will read in m_fifo_read+1) uint8_t m_fifo_write; // write offset + bool m_fifo_reset; + bool m_fifo_empty; }; DECLARE_DEVICE_TYPE(SEGA_315_5641_PCM, sega_315_5641_pcm_device) diff --git a/src/mame/drivers/segapico.cpp b/src/mame/drivers/segapico.cpp index a6efcfdb7d4..f95a4d75c66 100644 --- a/src/mame/drivers/segapico.cpp +++ b/src/mame/drivers/segapico.cpp @@ -319,18 +319,9 @@ void pico_base_state::pico_68k_io_write(offs_t offset, uint16_t data, uint16_t m // value 8000 resets the FIFO? (always used with low reset line) // value 0800 maps to the uPD7759's reset line (0 = reset, 1 = normal) // value 4000 maps to the uPD7759's start line (0->1 = start) + m_sega_315_5641_pcm->fifo_reset_w(BIT(data, 15)); m_sega_315_5641_pcm->reset_w(BIT(data, 11)); m_sega_315_5641_pcm->start_w(BIT(data, 14)); - if (BIT(data, 14)) - { - // Somewhere between "Reset Off" and the first sample data, - // we need to send a few commands to make the sample stream work. - // Doing that when rising the "start" line seems to work fine. - m_sega_315_5641_pcm->port_w(0xFF); // "Last Sample" value (must be >= 0x10) - m_sega_315_5641_pcm->port_w(0x00); // Dummy 1 - m_sega_315_5641_pcm->port_w(0x00); // Addr MSB - m_sega_315_5641_pcm->port_w(0x00); // Addr LSB - } } @@ -409,7 +400,7 @@ void pico_state::pico(machine_config &config) SOFTWARE_LIST(config, "cart_list").set_original("pico"); SEGA_315_5641_PCM(config, m_sega_315_5641_pcm, upd7759_device::STANDARD_CLOCK*2); - //m_sega_315_5641_pcm->drq().set(FUNC(pico_state::sound_cause_irq)); FIXME: this never worked - the MAME 315_5641 doesn't support slave mode + m_sega_315_5641_pcm->fifo_cb().set(FUNC(pico_state::sound_cause_irq)); m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "lspeaker", 0.16); m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "rspeaker", 0.16); } @@ -429,7 +420,7 @@ void pico_state::picopal(machine_config &config) SOFTWARE_LIST(config, "cart_list").set_original("pico"); SEGA_315_5641_PCM(config, m_sega_315_5641_pcm, upd7759_device::STANDARD_CLOCK*2); - //m_sega_315_5641_pcm->drq().set(FUNC(pico_state::sound_cause_irq)); FIXME: this never worked - the MAME 315_5641 doesn't support slave mode + m_sega_315_5641_pcm->fifo_cb().set(FUNC(pico_state::sound_cause_irq)); m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "lspeaker", 0.16); m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "rspeaker", 0.16); } @@ -627,7 +618,7 @@ void copera_state::copera(machine_config &config) SOFTWARE_LIST(config, "cart_list").set_original("copera"); SEGA_315_5641_PCM(config, m_sega_315_5641_pcm, upd7759_device::STANDARD_CLOCK); - //m_sega_315_5641_pcm->drq().set(FUNC(copera_state::sound_cause_irq)); FIXME: this never worked - the MAME 315_5641 doesn't support slave mode + m_sega_315_5641_pcm->fifo_cb().set(FUNC(copera_state::sound_cause_irq)); m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "lspeaker", 0.16); m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "rspeaker", 0.16); } -- cgit v1.2.3