mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
fix Sega Pico PCM playback (#9965)
- fix uPD775x type - enforce "slave" mode (required for manual data stream) - hook up "PCM FIFO empty" interrupt
This commit is contained in:
parent
61b9ae3a5b
commit
d950be1132
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user