mirror of
https://github.com/holub/mame
synced 2025-05-17 11:15:06 +03:00
Merge pull request #4836 from DavidHaywood/300319
basic audio for SPG110 titles
This commit is contained in:
commit
a14285494f
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 )
|
||||
|
Loading…
Reference in New Issue
Block a user