Modernize the NiLe sound device. [Andrew Gardner]

This commit is contained in:
Andrew Gardner 2012-12-29 17:08:30 +00:00
parent ae96df6ffc
commit 1f99039570
3 changed files with 131 additions and 152 deletions

View File

@ -27,8 +27,6 @@
#include "emu.h"
#include "nile.h"
#define NILE_VOICES 8
enum
{
NILE_REG_UNK0=0,
@ -50,95 +48,37 @@ enum
};
const device_type NILE = &device_creator<nile_device>;
struct nile_state
nile_device::nile_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, NILE, "NiLe", tag, owner, clock),
device_sound_interface(mconfig, *this),
m_stream(NULL),
m_sound_ram(NULL),
m_ctrl(0)
{
sound_stream * stream;
UINT8 *sound_ram;
UINT16 sound_regs[0x80];
int vpos[NILE_VOICES], frac[NILE_VOICES], lponce[NILE_VOICES];
UINT16 ctrl;
};
INLINE nile_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == NILE);
return (nile_state *)downcast<nile_device *>(device)->token();
}
WRITE16_DEVICE_HANDLER( nile_sndctrl_w )
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void nile_device::device_start()
{
nile_state *info = get_safe_token(device);
UINT16 ctrl=info->ctrl;
info->stream->update();
COMBINE_DATA(&info->ctrl);
// printf("CTRL: %04x -> %04x (PC=%x)\n", ctrl, info->ctrl, space.device().safe_pc());
ctrl^=info->ctrl;
m_sound_ram = *region();
m_stream = stream_alloc(0, 2, 44100);
}
READ16_DEVICE_HANDLER( nile_sndctrl_r )
//-------------------------------------------------
// sound_stream_update - handle update requests
// for our sound stream
//-------------------------------------------------
void nile_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
nile_state *info = get_safe_token(device);
info->stream->update();
return info->ctrl;
}
READ16_DEVICE_HANDLER( nile_snd_r )
{
nile_state *info = get_safe_token(device);
int reg=offset&0xf;
info->stream->update();
if(reg==2 || reg==3)
{
int slot=offset/16;
int sptr = ((info->sound_regs[slot*16+3]<<16)|info->sound_regs[slot*16+2])+info->vpos[slot];
if(reg==2)
{
return sptr&0xffff;
}
else
{
return sptr>>16;
}
}
return info->sound_regs[offset];
}
WRITE16_DEVICE_HANDLER( nile_snd_w )
{
nile_state *info = get_safe_token(device);
int v, r;
info->stream->update();
COMBINE_DATA(&info->sound_regs[offset]);
v = offset / 16;
r = offset % 16;
if ((r == 2) || (r == 3))
{
info->vpos[v] = info->frac[v] = info->lponce[v] = 0;
}
//printf("v%02d: %04x to reg %02d (PC=%x)\n", v, info->sound_regs[offset], r, space.device().safe_pc());
}
static STREAM_UPDATE( nile_update )
{
nile_state *info = (nile_state *)param;
UINT8 *sound_ram = info->sound_ram;
UINT8 *sound_ram = m_sound_ram;
int v, i, snum;
UINT16 *slot;
INT32 mix[48000*2];
@ -152,9 +92,9 @@ static STREAM_UPDATE( nile_update )
for (v = 0; v < NILE_VOICES; v++)
{
slot = &info->sound_regs[v * 16];
slot = &m_sound_regs[v * 16];
if (info->ctrl&(1<<v))
if (m_ctrl&(1<<v))
{
mixp = &mix[0];
@ -167,28 +107,28 @@ static STREAM_UPDATE( nile_update )
for (snum = 0; snum < samples; snum++)
{
sample = sound_ram[sptr + info->vpos[v]]<<8;
sample = sound_ram[sptr + m_vpos[v]]<<8;
*mixp++ += (sample * (INT32)slot[NILE_REG_VOL_R]) >> 16;
*mixp++ += (sample * (INT32)slot[NILE_REG_VOL_L]) >> 16;
info->frac[v] += freq;
info->vpos[v] += info->frac[v]>>16;
info->frac[v] &= 0xffff;
m_frac[v] += freq;
m_vpos[v] += m_frac[v]>>16;
m_frac[v] &= 0xffff;
// stop if we're at the end
if (info->lponce[v])
if (m_lponce[v])
{
// we've looped once, check loop end rather than sample end
if ((info->vpos[v] + sptr) >= leptr)
if ((m_vpos[v] + sptr) >= leptr)
{
info->vpos[v] = (lsptr - sptr);
m_vpos[v] = (lsptr - sptr);
}
}
else
{
// not looped yet, check sample end
if ((info->vpos[v] + sptr) >= eptr)
if ((m_vpos[v] + sptr) >= eptr)
{
// code at 11d8c:
// if bit 2 (0x4) is set, check if loop start = loop end.
@ -197,14 +137,14 @@ static STREAM_UPDATE( nile_update )
// the loop start/end registers in the NiLe.
if ((slot[NILE_REG_FLAGS] & 0x5) == 0x5)
{
info->vpos[v] = (lsptr - sptr);
info->lponce[v] = 1;
m_vpos[v] = (lsptr - sptr);
m_lponce[v] = 1;
}
else
{
info->ctrl &= ~(1<<v);
info->vpos[v] = (eptr - sptr);
info->frac[v] = 0;
m_ctrl &= ~(1<<v);
m_vpos[v] = (eptr - sptr);
m_frac[v] = 0;
}
}
@ -220,51 +160,67 @@ static STREAM_UPDATE( nile_update )
}
}
static DEVICE_START( nile )
WRITE16_MEMBER( nile_device::nile_sndctrl_w )
{
nile_state *info = get_safe_token(device);
UINT16 ctrl=m_ctrl;
info->sound_ram = *device->region();
m_stream->update();
info->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, info, nile_update);
}
COMBINE_DATA(&m_ctrl);
const device_type NILE = &device_creator<nile_device>;
// printf("CTRL: %04x -> %04x (PC=%x)\n", ctrl, m_ctrl, space.device().safe_pc());
nile_device::nile_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, NILE, "NiLe", tag, owner, clock),
device_sound_interface(mconfig, *this)
{
m_token = global_alloc_clear(nile_state);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void nile_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void nile_device::device_start()
{
DEVICE_START_NAME( nile )(this);
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
void nile_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");
ctrl^=m_ctrl;
}
READ16_MEMBER( nile_device::nile_sndctrl_r )
{
m_stream->update();
return m_ctrl;
}
READ16_MEMBER( nile_device::nile_snd_r )
{
int reg=offset&0xf;
m_stream->update();
if(reg==2 || reg==3)
{
int slot=offset/16;
int sptr = ((m_sound_regs[slot*16+3]<<16)|m_sound_regs[slot*16+2])+m_vpos[slot];
if(reg==2)
{
return sptr&0xffff;
}
else
{
return sptr>>16;
}
}
return m_sound_regs[offset];
}
WRITE16_MEMBER( nile_device::nile_snd_w )
{
int v, r;
m_stream->update();
COMBINE_DATA(&m_sound_regs[offset]);
v = offset / 16;
r = offset % 16;
if ((r == 2) || (r == 3))
{
m_vpos[v] = m_frac[v] = m_lponce[v] = 0;
}
//printf("v%02d: %04x to reg %02d (PC=%x)\n", v, m_sound_regs[offset], r, space.device().safe_pc());
}

View File

@ -3,32 +3,55 @@
#ifndef __NILE_H__
#define __NILE_H__
#include "devlegcy.h"
DECLARE_WRITE16_DEVICE_HANDLER( nile_snd_w );
DECLARE_READ16_DEVICE_HANDLER( nile_snd_r );
DECLARE_WRITE16_DEVICE_HANDLER( nile_sndctrl_w );
DECLARE_READ16_DEVICE_HANDLER( nile_sndctrl_r );
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_NILE_ADD(_tag, _clock) \
MCFG_DEVICE_ADD(_tag, NILE, _clock) \
#define MCFG_NILE_REPLACE(_tag, _clock) \
MCFG_DEVICE_REPLACE(_tag, NILE, _clock) \
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
#define NILE_VOICES 8
// ======================> nile_device
class nile_device : public device_t,
public device_sound_interface
public device_sound_interface
{
public:
nile_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~nile_device() { global_free(m_token); }
~nile_device() { }
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
public:
DECLARE_WRITE16_MEMBER( nile_snd_w );
DECLARE_READ16_MEMBER( nile_snd_r );
DECLARE_WRITE16_MEMBER( nile_sndctrl_w );
DECLARE_READ16_MEMBER( nile_sndctrl_r );
private:
// internal state
void *m_token;
sound_stream *m_stream;
UINT8 *m_sound_ram;
UINT16 m_sound_regs[0x80];
int m_vpos[NILE_VOICES];
int m_frac[NILE_VOICES];
int m_lponce[NILE_VOICES];
UINT16 m_ctrl;
};
extern const device_type NILE;

View File

@ -563,8 +563,8 @@ static ADDRESS_MAP_START( srmp6_map, AS_PROGRAM, 16, srmp6_state )
//AM_RANGE(0x5fff00, 0x5fffff) AM_WRITE_LEGACY(dma_w) AM_SHARE("dmaram")
AM_RANGE(0x4c0000, 0x4c006f) AM_READWRITE(video_regs_r, video_regs_w) AM_SHARE("video_regs") // ? gfx regs ST-0026 NiLe
AM_RANGE(0x4e0000, 0x4e00ff) AM_DEVREADWRITE_LEGACY("nile", nile_snd_r, nile_snd_w)
AM_RANGE(0x4e0100, 0x4e0101) AM_DEVREADWRITE_LEGACY("nile", nile_sndctrl_r, nile_sndctrl_w)
AM_RANGE(0x4e0000, 0x4e00ff) AM_DEVREADWRITE("nile", nile_device, nile_snd_r, nile_snd_w)
AM_RANGE(0x4e0100, 0x4e0101) AM_DEVREADWRITE("nile", nile_device, nile_sndctrl_r, nile_sndctrl_w)
//AM_RANGE(0x4e0110, 0x4e0111) AM_NOP // ? accessed once ($268dc, written $b.w)
//AM_RANGE(0x5fff00, 0x5fff1f) AM_RAM // ? see routine $5ca8, video_regs related ???
@ -689,7 +689,7 @@ static MACHINE_CONFIG_START( srmp6, srmp6_state )
/* sound hardware */
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("nile", NILE, 0)
MCFG_NILE_ADD("nile", 0)
MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
MACHINE_CONFIG_END