diff --git a/src/devices/machine/spg110.cpp b/src/devices/machine/spg110.cpp index 060ae511f0c..81cc5e53c23 100644 --- a/src/devices/machine/spg110.cpp +++ b/src/devices/machine/spg110.cpp @@ -18,10 +18,12 @@ DEFINE_DEVICE_TYPE(SPG110, spg110_device, "spg110", "SPG110 System-on-a-Chip") spg110_device::spg110_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) + , device_mixer_interface(mconfig, *this, 2) , m_cpu(*this, finder_base::DUMMY_TAG) , m_screen(*this, finder_base::DUMMY_TAG) , m_spg_io(*this, "spg_io") , m_spg_video(*this, "spg_video") + , m_spg_audio(*this, "spgaudio") , m_porta_out(*this) , m_portb_out(*this) , m_portc_out(*this) @@ -63,6 +65,18 @@ void spg110_device::configure_spg_io(spg2xx_io_device* io) // io->write_ffrq_tmr2_irq_callback().set(FUNC(spg110_device::ffreq2_w)); } +READ16_MEMBER(spg110_device::space_r) +{ + address_space &cpuspace = m_cpu->space(AS_PROGRAM); + return cpuspace.read_word(offset); +} + +WRITE_LINE_MEMBER(spg110_device::audioirq_w) +{ + m_cpu->set_state_unsynced(UNSP_FIQ_LINE, state); +} + + void spg110_device::device_add_mconfig(machine_config &config) { SPG24X_IO(config, m_spg_io, DERIVED_CLOCK(1, 1), m_cpu, m_screen); @@ -70,23 +84,16 @@ void spg110_device::device_add_mconfig(machine_config &config) SPG110_VIDEO(config, m_spg_video, DERIVED_CLOCK(1, 1), m_cpu, m_screen); m_spg_video->write_video_irq_callback().set(FUNC(spg110_device::videoirq_w)); + + SPG110_AUDIO(config, m_spg_audio, DERIVED_CLOCK(1, 1)); + m_spg_audio->write_irq_callback().set(FUNC(spg110_device::audioirq_w)); + m_spg_audio->space_read_callback().set(FUNC(spg110_device::space_r)); + + m_spg_audio->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0); + m_spg_audio->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1); + } -WRITE16_MEMBER(spg110_device::spg110_3100_w) { } -WRITE16_MEMBER(spg110_device::spg110_3101_w) { } -WRITE16_MEMBER(spg110_device::spg110_3102_w) { } -WRITE16_MEMBER(spg110_device::spg110_3104_w) { } -WRITE16_MEMBER(spg110_device::spg110_3105_w) { } -WRITE16_MEMBER(spg110_device::spg110_3106_w) { } -WRITE16_MEMBER(spg110_device::spg110_3107_w) { } -WRITE16_MEMBER(spg110_device::spg110_3108_w) { } -WRITE16_MEMBER(spg110_device::spg110_3109_w) { } -WRITE16_MEMBER(spg110_device::spg110_310b_w) { } -WRITE16_MEMBER(spg110_device::spg110_310c_w) { } -WRITE16_MEMBER(spg110_device::spg110_310d_w) { } - -READ16_MEMBER(spg110_device::spg110_310f_r) { return 0x0000; } - void spg110_device::map(address_map &map) { map(0x000000, 0x000fff).ram(); @@ -139,27 +146,12 @@ void spg110_device::map(address_map &map) map(0x002100, 0x0021ff).ram(); // jak_spdmo only map(0x002200, 0x0022ff).ram(); // looks like per-pen brightness or similar? strange because palette isn't memory mapped here (maybe rowscroll?) -#if 1 // sound registers? seems to be 8 long entries, only uses up to 0x7f? (register mapping seems similar to spg2xx, maybe with less channels?) - map(0x003000, 0x00307f).ram(); - map(0x003080, 0x0030ff).ram(); + /// sound registers? seems to be 8 long entries, only uses up to 0x7f? (register mapping seems similar to spg2xx, maybe with less channels?) + map(0x003000, 0x00307f).rw(m_spg_audio, FUNC(spg110_audio_device::audio_r), FUNC(spg110_audio_device::audio_w)); + map(0x003080, 0x0030ff).ram(); // extra ram? doesn't seem to be phase, and there only appear to be 8 channels on SPG110 - map(0x003100, 0x003100).w(FUNC(spg110_device::spg110_3100_w)); - map(0x003101, 0x003101).w(FUNC(spg110_device::spg110_3101_w)); - map(0x003102, 0x003102).w(FUNC(spg110_device::spg110_3102_w)); + map(0x003100, 0x00310f).rw(m_spg_audio, FUNC(spg110_audio_device::audio_ctrl_r), FUNC(spg2xx_audio_device::audio_ctrl_w)); - map(0x003104, 0x003104).w(FUNC(spg110_device::spg110_3104_w)); - map(0x003105, 0x003105).w(FUNC(spg110_device::spg110_3105_w)); - map(0x003106, 0x003106).w(FUNC(spg110_device::spg110_3106_w)); - map(0x003107, 0x003107).w(FUNC(spg110_device::spg110_3107_w)); - map(0x003108, 0x003108).w(FUNC(spg110_device::spg110_3108_w)); - map(0x003109, 0x003109).w(FUNC(spg110_device::spg110_3109_w)); - - map(0x00310b, 0x00310b).w(FUNC(spg110_device::spg110_310b_w)); - map(0x00310c, 0x00310c).w(FUNC(spg110_device::spg110_310c_w)); - map(0x00310d, 0x00310d).w(FUNC(spg110_device::spg110_310d_w)); - - map(0x00310f, 0x00310f).r(FUNC(spg110_device::spg110_310f_r)); -#endif // 0032xx looks like it could be the same as 003d00 on spg2xx map(0x003200, 0x00322f).rw(m_spg_io, FUNC(spg2xx_io_device::io_r), FUNC(spg2xx_io_device::io_w)); diff --git a/src/devices/machine/spg110.h b/src/devices/machine/spg110.h index 91a715fc755..01019d538cf 100644 --- a/src/devices/machine/spg110.h +++ b/src/devices/machine/spg110.h @@ -11,8 +11,9 @@ #include "emupal.h" #include "spg2xx_io.h" #include "spg110_video.h" +#include "spg2xx_audio.h" -class spg110_device : public device_t +class spg110_device : public device_t, public device_mixer_interface { public: @@ -35,7 +36,7 @@ public: auto porta_in() { return m_porta_in.bind(); } auto portb_in() { return m_portb_in.bind(); } auto portc_in() { return m_portc_in.bind(); } - + template auto adc_in() { return m_adc_in[Line].bind(); } auto chip_select() { return m_chip_sel.bind(); } @@ -56,23 +57,10 @@ private: required_device m_spg_io; required_device m_spg_video; + required_device m_spg_audio; - DECLARE_WRITE16_MEMBER(spg110_3100_w); - - DECLARE_WRITE16_MEMBER(spg110_3101_w); - DECLARE_WRITE16_MEMBER(spg110_3102_w); - DECLARE_WRITE16_MEMBER(spg110_3104_w); - DECLARE_WRITE16_MEMBER(spg110_3105_w); - DECLARE_WRITE16_MEMBER(spg110_3106_w); - DECLARE_WRITE16_MEMBER(spg110_3107_w); - DECLARE_WRITE16_MEMBER(spg110_3108_w); - DECLARE_WRITE16_MEMBER(spg110_3109_w); - - DECLARE_WRITE16_MEMBER(spg110_310b_w); - DECLARE_WRITE16_MEMBER(spg110_310c_w); - DECLARE_WRITE16_MEMBER(spg110_310d_w); - - DECLARE_READ16_MEMBER(spg110_310f_r); + DECLARE_READ16_MEMBER(space_r); + DECLARE_WRITE_LINE_MEMBER(audioirq_w); devcb_write16 m_porta_out; devcb_write16 m_portb_out; diff --git a/src/devices/machine/spg2xx_audio.cpp b/src/devices/machine/spg2xx_audio.cpp index a09eb907694..5c488c2f1eb 100644 --- a/src/devices/machine/spg2xx_audio.cpp +++ b/src/devices/machine/spg2xx_audio.cpp @@ -4,12 +4,21 @@ SunPlus SPG2xx-series SoC peripheral emulation (Audio) + This is also used for SPG110, although that should be limited to + just 8 channels and has some things shifted around (phase appears + to be in the regular register set instead, formats might be fixed + or at least not per-channel) + + SPG110 Beat interrupt frequency might be different too, seems to + trigger an FIQ, but music is very slow in jak_spdmo + **********************************************************************/ #include "emu.h" #include "spg2xx_audio.h" -DEFINE_DEVICE_TYPE(SPG2XX_AUDIO, spg2xx_audio_device, "spg2xx", "SPG2xx-series System-on-a-Chip Audio") +DEFINE_DEVICE_TYPE(SPG2XX_AUDIO, spg2xx_audio_device, "spg2xx_audio", "SPG2xx-series System-on-a-Chip Audio") +DEFINE_DEVICE_TYPE(SPG110_AUDIO, spg110_audio_device, "spg110_audio", "SPG110-series System-on-a-Chip Audio") #define LOG_SPU_READS (1U << 0) #define LOG_SPU_WRITES (1U << 1) @@ -43,6 +52,12 @@ spg2xx_audio_device::spg2xx_audio_device(const machine_config &mconfig, const ch { } +spg110_audio_device::spg110_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : spg2xx_audio_device(mconfig, SPG110_AUDIO, tag, owner, clock) +{ +} + + void spg2xx_audio_device::device_start() { @@ -1256,3 +1271,22 @@ bool spg2xx_audio_device::audio_envelope_tick(const uint32_t channel) LOGMASKED(LOG_ENVELOPES, "envelope %d post-tick, count is now %04x, register is %04x\n", channel, new_count, m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA]); return edd_changed; } + + + +WRITE16_MEMBER(spg110_audio_device::audio_w) +{ + const uint16_t channel = (offset & 0x00f0) >> 4; + + switch (offset & AUDIO_CHAN_OFFSET_MASK) + { + case 0x0e: + m_audio_regs[offset] = data; + m_channel_rate[channel] = ((double)get_phase(channel) * 140625.0 * 2.0) / (double)(1 << 19); + m_channel_rate_accum[channel] = 0.0; + LOGMASKED(LOG_CHANNEL_WRITES, "spg110_audio_device::audio_w: Channel %d: Phase: %04x (rate: %f)\n", channel, data, m_channel_rate[channel]); + return; + } + + spg2xx_audio_device::audio_w(space,offset,data,mem_mask); +} diff --git a/src/devices/machine/spg2xx_audio.h b/src/devices/machine/spg2xx_audio.h index 22f5108e405..88d21fb1ecf 100644 --- a/src/devices/machine/spg2xx_audio.h +++ b/src/devices/machine/spg2xx_audio.h @@ -24,7 +24,7 @@ public: auto write_irq_callback() { return m_irq_cb.bind(); } DECLARE_READ16_MEMBER(audio_r); - DECLARE_WRITE16_MEMBER(audio_w); + virtual DECLARE_WRITE16_MEMBER(audio_w); DECLARE_READ16_MEMBER(audio_ctrl_r); DECLARE_WRITE16_MEMBER(audio_ctrl_w); DECLARE_READ16_MEMBER(audio_phase_r); @@ -52,8 +52,8 @@ protected: uint16_t get_wave_addr_high(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_WADDR_HIGH_MASK; } uint16_t get_loop_addr_high(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_LADDR_HIGH_MASK) >> AUDIO_LADDR_HIGH_SHIFT; } uint16_t get_tone_mode(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_TONE_MODE_MASK) >> AUDIO_TONE_MODE_SHIFT; } - uint16_t get_16bit_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_16M_MASK) ? 1 : 0; } - uint16_t get_adpcm_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_ADPCM_MASK) ? 1 : 0; } + virtual uint16_t get_16bit_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_16M_MASK) ? 1 : 0; } + virtual uint16_t get_adpcm_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_ADPCM_MASK) ? 1 : 0; } // Audio Pan getters uint16_t get_volume(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_PAN_VOL] & AUDIO_VOLUME_MASK; } @@ -103,7 +103,7 @@ protected: uint16_t get_phase_time_step(const offs_t channel) const { return (m_audio_phase_regs[(channel << 4) | AUDIO_PHASE_CTRL] & AUDIO_PHASE_TIME_STEP_MASK) >> AUDIO_PHASE_TIME_STEP_SHIFT; } // Audio combined getters - uint32_t get_phase(const offs_t channel) const { return ((uint32_t)get_phase_high(channel) << 16) | m_audio_phase_regs[(channel << 4) | AUDIO_PHASE]; } + virtual uint32_t get_phase(const offs_t channel) const { return ((uint32_t)get_phase_high(channel) << 16) | m_audio_phase_regs[(channel << 4) | AUDIO_PHASE]; } uint32_t get_phase_accum(const offs_t channel) const { return ((uint32_t)get_phase_accum_high(channel) << 16) | m_audio_phase_regs[(channel << 4) | AUDIO_PHASE_ACCUM]; } uint32_t get_target_phase(const offs_t channel) const { return ((uint32_t)get_target_phase_high(channel) << 16) | m_audio_phase_regs[(channel << 4) | AUDIO_TARGET_PHASE]; } @@ -367,6 +367,21 @@ private: }; +class spg110_audio_device : public spg2xx_audio_device +{ +public: + spg110_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual DECLARE_WRITE16_MEMBER(audio_w) override; + + // these either come from somewhere else on spg110 or are hardcoded + virtual uint16_t get_16bit_bit(const offs_t channel) const override { return 1; } + virtual uint16_t get_adpcm_bit(const offs_t channel) const override { return 0; } + + virtual uint32_t get_phase(const offs_t channel) const override { return m_audio_regs[(channel << 4) | 0xe]; } +}; + DECLARE_DEVICE_TYPE(SPG2XX_AUDIO, spg2xx_audio_device) +DECLARE_DEVICE_TYPE(SPG110_AUDIO, spg110_audio_device) #endif // MAME_MACHINE_SPG2XX_AUDIO_H diff --git a/src/mame/drivers/spg110.cpp b/src/mame/drivers/spg110.cpp index dd65883129c..8ac0de20dfa 100644 --- a/src/mame/drivers/spg110.cpp +++ b/src/mame/drivers/spg110.cpp @@ -346,17 +346,17 @@ void spg110_game_state::spg110_base(machine_config &config) m_screen->set_screen_update("spg", FUNC(spg110_device::screen_update)); m_screen->screen_vblank().set(m_spg, FUNC(spg110_device::vblank)); - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); -// m_spg->add_route(ALL_OUTPUTS, "lspeaker", 0.5); -// m_spg->add_route(ALL_OUTPUTS, "rspeaker", 0.5); - SPG110(config, m_spg, XTAL(27'000'000), m_maincpu, m_screen); m_spg->porta_in().set_ioport("PA"); m_spg->portb_in().set_ioport("PB"); m_spg->portc_in().set_ioport("PC"); m_spg->adc_in<0>().set_ioport("JOYX"); m_spg->adc_in<1>().set_ioport("JOYY"); + + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + m_spg->add_route(ALL_OUTPUTS, "lspeaker", 0.5); + m_spg->add_route(ALL_OUTPUTS, "rspeaker", 0.5); } ROM_START( jak_capb )