Merge pull request #4836 from DavidHaywood/300319

basic audio for SPG110 titles
This commit is contained in:
ajrhacker 2019-03-31 14:04:02 -04:00 committed by GitHub
commit a14285494f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 62 deletions

View File

@ -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));

View File

@ -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 <size_t Line> auto adc_in() { return m_adc_in[Line].bind(); }
auto chip_select() { return m_chip_sel.bind(); }
@ -56,23 +57,10 @@ private:
required_device<spg2xx_io_device> m_spg_io;
required_device<spg110_video_device> m_spg_video;
required_device<spg110_audio_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;

View File

@ -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);
}

View File

@ -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

View File

@ -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 )