Modernized the Amiga sound device. (nw)

This commit is contained in:
Ivan Vangelista 2013-08-05 15:20:36 +00:00
parent 645fe0f762
commit fd66b2953f
3 changed files with 89 additions and 138 deletions

View File

@ -11,7 +11,6 @@
#include "emu.h" #include "emu.h"
#include "includes/amiga.h" #include "includes/amiga.h"
#include "cpu/m68000/m68000.h" #include "cpu/m68000/m68000.h"
#include "devlegcy.h"
/************************************* /*************************************
@ -34,50 +33,53 @@
#define CLOCK_DIVIDER 16 #define CLOCK_DIVIDER 16
const device_type AMIGA = &device_creator<amiga_sound_device>;
/************************************* amiga_sound_device::amiga_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
* : device_t(mconfig, AMIGA, "Amiga Paula", tag, owner, clock, "amiga_paula", __FILE__),
* Type definitions device_sound_interface(mconfig, *this),
* m_stream(NULL)
*************************************/
struct audio_channel
{ {
emu_timer * irq_timer;
UINT32 curlocation;
UINT16 curlength;
UINT16 curticks;
UINT8 index;
UINT8 dmaenabled;
UINT8 manualmode;
INT8 latched;
};
struct amiga_audio
{
audio_channel channel[4];
sound_stream * stream;
};
INLINE amiga_audio *get_safe_token( device_t *device )
{
assert(device != NULL);
assert(device->type() == AMIGA);
return (amiga_audio *)downcast<amiga_sound_device *>(device)->token();
} }
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void amiga_sound_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void amiga_sound_device::device_start()
{
int i;
for (i = 0; i < 4; i++)
{
m_channel[i].index = i;
m_channel[i].irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(amiga_sound_device::signal_irq), this));
}
/* create the stream */
m_stream = machine().sound().stream_alloc(*this, 0, 4, clock() / CLOCK_DIVIDER, this);
}
/************************************* /*************************************
* *
* DMA reload/IRQ signalling * DMA reload/IRQ signalling
* *
*************************************/ *************************************/
static TIMER_CALLBACK( signal_irq ) TIMER_CALLBACK_MEMBER( amiga_sound_device::signal_irq )
{ {
amiga_state *state = machine.driver_data<amiga_state>(); amiga_state *state = machine().driver_data<amiga_state>();
state->amiga_custom_w(*state->m_maincpu_program_space, REG_INTREQ, 0x8000 | (0x80 << param), 0xffff); state->amiga_custom_w(*state->m_maincpu_program_space, REG_INTREQ, 0x8000 | (0x80 << param), 0xffff);
} }
@ -98,11 +100,9 @@ static void dma_reload(amiga_state *state, audio_channel *chan)
* *
*************************************/ *************************************/
void amiga_audio_data_w(device_t *device, int which, UINT16 data) void amiga_sound_device::data_w(int which, UINT16 data)
{ {
amiga_audio *audio_state = get_safe_token(device); m_channel[which].manualmode = TRUE;
audio_state->channel[which].manualmode = TRUE;
} }
@ -113,28 +113,28 @@ void amiga_audio_data_w(device_t *device, int which, UINT16 data)
* *
*************************************/ *************************************/
void amiga_audio_update(device_t *device) void amiga_sound_device::update()
{ {
amiga_audio *audio_state = get_safe_token(device); m_stream->update();
audio_state->stream->update();
} }
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
static STREAM_UPDATE( amiga_stream_update ) void amiga_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{ {
amiga_state *state = device->machine().driver_data<amiga_state>(); amiga_state *state = machine().driver_data<amiga_state>();
amiga_audio *audio = (amiga_audio *)param;
int channum, sampoffs = 0; int channum, sampoffs = 0;
/* if all DMA off, disable all channels */ /* if all DMA off, disable all channels */
if (!(CUSTOM_REG(REG_DMACON) & 0x0200)) if (!(CUSTOM_REG(REG_DMACON) & 0x0200))
{ {
audio->channel[0].dmaenabled = m_channel[0].dmaenabled =
audio->channel[1].dmaenabled = m_channel[1].dmaenabled =
audio->channel[2].dmaenabled = m_channel[2].dmaenabled =
audio->channel[3].dmaenabled = FALSE; m_channel[3].dmaenabled = FALSE;
/* clear the sample data to 0 */ /* clear the sample data to 0 */
for (channum = 0; channum < 4; channum++) for (channum = 0; channum < 4; channum++)
@ -147,7 +147,7 @@ static STREAM_UPDATE( amiga_stream_update )
/* update the DMA states on each channel and reload if fresh */ /* update the DMA states on each channel and reload if fresh */
for (channum = 0; channum < 4; channum++) for (channum = 0; channum < 4; channum++)
{ {
audio_channel *chan = &audio->channel[channum]; audio_channel *chan = &m_channel[channum];
if (!chan->dmaenabled && ((CUSTOM_REG(REG_DMACON) >> channum) & 1)) if (!chan->dmaenabled && ((CUSTOM_REG(REG_DMACON) >> channum) & 1))
dma_reload(state, chan); dma_reload(state, chan);
chan->dmaenabled = (CUSTOM_REG(REG_DMACON) >> channum) & 1; chan->dmaenabled = (CUSTOM_REG(REG_DMACON) >> channum) & 1;
@ -160,14 +160,14 @@ static STREAM_UPDATE( amiga_stream_update )
int ticks = samples; int ticks = samples;
/* determine the number of ticks we can do in this chunk */ /* determine the number of ticks we can do in this chunk */
if (ticks > audio->channel[0].curticks) if (ticks > m_channel[0].curticks)
ticks = audio->channel[0].curticks; ticks = m_channel[0].curticks;
if (ticks > audio->channel[1].curticks) if (ticks > m_channel[1].curticks)
ticks = audio->channel[1].curticks; ticks = m_channel[1].curticks;
if (ticks > audio->channel[2].curticks) if (ticks > m_channel[2].curticks)
ticks = audio->channel[2].curticks; ticks = m_channel[2].curticks;
if (ticks > audio->channel[3].curticks) if (ticks > m_channel[3].curticks)
ticks = audio->channel[3].curticks; ticks = m_channel[3].curticks;
/* loop over channels */ /* loop over channels */
nextper = nextvol = -1; nextper = nextvol = -1;
@ -175,7 +175,7 @@ static STREAM_UPDATE( amiga_stream_update )
{ {
int volume = (nextvol == -1) ? CUSTOM_REG(REG_AUD0VOL + channum * 8) : nextvol; int volume = (nextvol == -1) ? CUSTOM_REG(REG_AUD0VOL + channum * 8) : nextvol;
int period = (nextper == -1) ? CUSTOM_REG(REG_AUD0PER + channum * 8) : nextper; int period = (nextper == -1) ? CUSTOM_REG(REG_AUD0PER + channum * 8) : nextper;
audio_channel *chan = &audio->channel[channum]; audio_channel *chan = &m_channel[channum];
stream_sample_t sample; stream_sample_t sample;
int i; int i;
@ -242,7 +242,7 @@ static STREAM_UPDATE( amiga_stream_update )
/* if we're in manual mode, signal an interrupt once we latch the low byte */ /* if we're in manual mode, signal an interrupt once we latch the low byte */
if (!chan->dmaenabled && chan->manualmode && (chan->curlocation & 1)) if (!chan->dmaenabled && chan->manualmode && (chan->curlocation & 1))
{ {
signal_irq(device->machine(), NULL, channum); signal_irq(NULL, channum);
chan->manualmode = FALSE; chan->manualmode = FALSE;
} }
} }
@ -253,65 +253,3 @@ static STREAM_UPDATE( amiga_stream_update )
samples -= ticks; samples -= ticks;
} }
} }
/*************************************
*
* Sound system startup
*
*************************************/
static DEVICE_START( amiga_sound )
{
amiga_audio *audio_state = get_safe_token(device);
int i;
for (i = 0; i < 4; i++)
{
audio_state->channel[i].index = i;
audio_state->channel[i].irq_timer = device->machine().scheduler().timer_alloc(FUNC(signal_irq));
}
/* create the stream */
audio_state->stream = device->machine().sound().stream_alloc(*device, 0, 4, device->clock() / CLOCK_DIVIDER, audio_state, amiga_stream_update);
}
const device_type AMIGA = &device_creator<amiga_sound_device>;
amiga_sound_device::amiga_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, AMIGA, "Amiga Paula", tag, owner, clock, "amiga_paula", __FILE__),
device_sound_interface(mconfig, *this)
{
m_token = global_alloc_clear(amiga_audio);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void amiga_sound_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void amiga_sound_device::device_start()
{
DEVICE_START_NAME( amiga_sound )(this);
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
void amiga_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
// should never get here
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
}

View File

@ -370,6 +370,8 @@ struct autoconfig_device
offs_t base; offs_t base;
}; };
class amiga_sound_device;
class amiga_state : public driver_device class amiga_state : public driver_device
{ {
public: public:
@ -386,6 +388,7 @@ public:
m_maincpu(*this, "maincpu"), /* accelerator cards may present an interesting challenge because the maincpu will be the one on the card instead */ m_maincpu(*this, "maincpu"), /* accelerator cards may present an interesting challenge because the maincpu will be the one on the card instead */
m_cia_0(*this, "cia_0"), m_cia_0(*this, "cia_0"),
m_cia_1(*this, "cia_1"), m_cia_1(*this, "cia_1"),
m_sound(*this, "amiga"),
m_fdc(*this, "fdc"), m_fdc(*this, "fdc"),
m_chip_ram(*this, "chip_ram", 0), m_chip_ram(*this, "chip_ram", 0),
m_custom_regs(*this, "custom_regs", 0), m_custom_regs(*this, "custom_regs", 0),
@ -403,6 +406,7 @@ public:
required_device<m68000_base_device> m_maincpu; required_device<m68000_base_device> m_maincpu;
required_device<legacy_mos6526_device> m_cia_0; required_device<legacy_mos6526_device> m_cia_0;
required_device<legacy_mos6526_device> m_cia_1; required_device<legacy_mos6526_device> m_cia_1;
required_device<amiga_sound_device> m_sound;
optional_device<amiga_fdc> m_fdc; optional_device<amiga_fdc> m_fdc;
required_shared_ptr<UINT16> m_chip_ram; required_shared_ptr<UINT16> m_chip_ram;
UINT16 (*m_chip_ram_r)(amiga_state *state, offs_t offset); UINT16 (*m_chip_ram_r)(amiga_state *state, offs_t offset);
@ -425,7 +429,6 @@ public:
autoconfig_device *m_cur_autoconfig; autoconfig_device *m_cur_autoconfig;
emu_timer * m_irq_timer; emu_timer * m_irq_timer;
emu_timer * m_blitter_timer; emu_timer * m_blitter_timer;
device_t *m_sound_device;
/* sprite states */ /* sprite states */
UINT8 m_sprite_comparitor_enable_mask; UINT8 m_sprite_comparitor_enable_mask;
@ -528,15 +531,28 @@ const amiga_machine_interface *amiga_get_interface(running_machine &machine);
/*----------- defined in audio/amiga.c -----------*/ /*----------- defined in audio/amiga.c -----------*/
struct audio_channel
{
emu_timer * irq_timer;
UINT32 curlocation;
UINT16 curlength;
UINT16 curticks;
UINT8 index;
UINT8 dmaenabled;
UINT8 manualmode;
INT8 latched;
};
class amiga_sound_device : public device_t, class amiga_sound_device : public device_t,
public device_sound_interface public device_sound_interface
{ {
public: public:
amiga_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); amiga_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~amiga_sound_device() { global_free(m_token); } ~amiga_sound_device() {}
void update();
void data_w(int which, UINT16 data);
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
protected: protected:
// device-level overrides // device-level overrides
virtual void device_config_complete(); virtual void device_config_complete();
@ -546,16 +562,14 @@ protected:
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private: private:
// internal state // internal state
void *m_token; audio_channel m_channel[4];
sound_stream * m_stream;
TIMER_CALLBACK_MEMBER( signal_irq );
}; };
extern const device_type AMIGA; extern const device_type AMIGA;
void amiga_audio_update(device_t *device);
void amiga_audio_data_w(device_t *device, int which, UINT16 data);
/*----------- defined in video/amiga.c -----------*/ /*----------- defined in video/amiga.c -----------*/
extern const UINT16 amiga_expand_byte[256]; extern const UINT16 amiga_expand_byte[256];

View File

@ -253,7 +253,6 @@ void amiga_machine_config(running_machine &machine, const amiga_machine_interfac
state->m_irq_timer = state->timer_alloc(amiga_state::TIMER_AMIGA_IRQ); state->m_irq_timer = state->timer_alloc(amiga_state::TIMER_AMIGA_IRQ);
state->m_blitter_timer = state->timer_alloc(amiga_state::TIMER_AMIGA_BLITTER); state->m_blitter_timer = state->timer_alloc(amiga_state::TIMER_AMIGA_BLITTER);
state->m_sound_device = machine.device("amiga");
} }
@ -367,7 +366,7 @@ TIMER_CALLBACK_MEMBER(amiga_state::scanline_callback)
} }
/* force a sound update */ /* force a sound update */
amiga_audio_update(m_sound_device); m_sound->update();
/* set timer for next line */ /* set timer for next line */
scanline = (scanline + 1) % m_screen->height(); scanline = (scanline + 1) % m_screen->height();
@ -1427,7 +1426,7 @@ WRITE16_MEMBER( amiga_state::amiga_custom_w )
break; break;
case REG_DMACON: case REG_DMACON:
amiga_audio_update(state->m_sound_device); m_sound->update();
/* bits BBUSY (14) and BZERO (13) are read-only */ /* bits BBUSY (14) and BZERO (13) are read-only */
data &= 0x9fff; data &= 0x9fff;
@ -1470,7 +1469,7 @@ WRITE16_MEMBER( amiga_state::amiga_custom_w )
break; break;
case REG_ADKCON: case REG_ADKCON:
amiga_audio_update(state->m_sound_device); m_sound->update();
data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff)); data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
state->m_fdc->adkcon_set(data); state->m_fdc->adkcon_set(data);
break; break;
@ -1479,11 +1478,11 @@ WRITE16_MEMBER( amiga_state::amiga_custom_w )
case REG_AUD1LCL: case REG_AUD1LCH: case REG_AUD1LEN: case REG_AUD1PER: case REG_AUD1VOL: case REG_AUD1LCL: case REG_AUD1LCH: case REG_AUD1LEN: case REG_AUD1PER: case REG_AUD1VOL:
case REG_AUD2LCL: case REG_AUD2LCH: case REG_AUD2LEN: case REG_AUD2PER: case REG_AUD2VOL: case REG_AUD2LCL: case REG_AUD2LCH: case REG_AUD2LEN: case REG_AUD2PER: case REG_AUD2VOL:
case REG_AUD3LCL: case REG_AUD3LCH: case REG_AUD3LEN: case REG_AUD3PER: case REG_AUD3VOL: case REG_AUD3LCL: case REG_AUD3LCH: case REG_AUD3LEN: case REG_AUD3PER: case REG_AUD3VOL:
amiga_audio_update(state->m_sound_device); m_sound->update();
break; break;
case REG_AUD0DAT: case REG_AUD1DAT: case REG_AUD2DAT: case REG_AUD3DAT: case REG_AUD0DAT: case REG_AUD1DAT: case REG_AUD2DAT: case REG_AUD3DAT:
amiga_audio_data_w(state->m_sound_device, (offset - REG_AUD0DAT) / 8, data); m_sound->data_w((offset - REG_AUD0DAT) / 8, data);
break; break;
case REG_BPL1PTH: case REG_BPL2PTH: case REG_BPL3PTH: case REG_BPL4PTH: case REG_BPL1PTH: case REG_BPL2PTH: case REG_BPL3PTH: case REG_BPL4PTH: