mirror of
https://github.com/holub/mame
synced 2025-05-30 17:41:47 +03:00
Modernize the NiLe sound device. [Andrew Gardner]
This commit is contained in:
parent
ae96df6ffc
commit
1f99039570
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user