Modernize rf5c68 and tms36xx sound devices. [Andrew Gardner]

Out of whatsnew.txt:
Thanks for the fix to my last changes Micko.  I got the MESS stuff this time :-).
This commit is contained in:
Andrew Gardner 2013-02-20 04:37:53 +00:00
parent 29f3537853
commit d69cada9e0
14 changed files with 396 additions and 378 deletions

View file

@ -6,49 +6,59 @@
#include "rf5c68.h"
#define NUM_CHANNELS (8)
// device type definition
const device_type RF5C68 = &device_creator<rf5c68_device>;
struct pcm_channel
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// rf5c68_device - constructor
//-------------------------------------------------
rf5c68_device::rf5c68_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, RF5C68, "RF5C68", tag, owner, clock),
device_sound_interface(mconfig, *this),
m_stream(NULL),
m_cbank(0),
m_wbank(0),
m_enable(0),
m_sample_callback(NULL)
{
UINT8 enable;
UINT8 env;
UINT8 pan;
UINT8 start;
UINT32 addr;
UINT16 step;
UINT16 loopst;
};
struct rf5c68_state
{
sound_stream * stream;
pcm_channel chan[NUM_CHANNELS];
UINT8 cbank;
UINT8 wbank;
UINT8 enable;
UINT8 data[0x10000];
void (*sample_callback)(device_t* device,int channel);
device_t* device;
};
INLINE rf5c68_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == RF5C68);
return (rf5c68_state *)downcast<rf5c68_device *>(device)->token();
memset(m_data, 0, sizeof(UINT8)*0x10000);
}
/************************************************/
/* RF5C68 stream update */
/************************************************/
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
static STREAM_UPDATE( rf5c68_update )
void rf5c68_device::device_start()
{
const rf5c68_interface* intf = (const rf5c68_interface*)static_config();
/* allocate memory for the chip */
memset(m_data, 0xff, sizeof(m_data));
/* allocate the stream */
m_stream = stream_alloc(0, 2, clock() / 384);
/* set up callback */
if(intf != NULL)
m_sample_callback = intf->sample_end_callback;
else
m_sample_callback = NULL;
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
void rf5c68_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
rf5c68_state *chip = (rf5c68_state *)param;
stream_sample_t *left = outputs[0];
stream_sample_t *right = outputs[1];
int i, j;
@ -58,13 +68,13 @@ static STREAM_UPDATE( rf5c68_update )
memset(right, 0, samples * sizeof(*right));
/* bail if not enabled */
if (!chip->enable)
if (!m_enable)
return;
/* loop over channels */
for (i = 0; i < NUM_CHANNELS; i++)
for (i = 0; i < RF5C68_NUM_CHANNELS; i++)
{
pcm_channel *chan = &chip->chan[i];
rf5c68_pcm_channel *chan = &m_chan[i];
/* if this channel is active, accumulate samples */
if (chan->enable)
@ -78,18 +88,18 @@ static STREAM_UPDATE( rf5c68_update )
int sample;
/* trigger sample callback */
if(chip->sample_callback)
if(m_sample_callback)
{
if(((chan->addr >> 11) & 0xfff) == 0xfff)
chip->sample_callback(chip->device,((chan->addr >> 11)/0x2000));
m_sample_callback(this, ((chan->addr >> 11)/0x2000));
}
/* fetch the sample and handle looping */
sample = chip->data[(chan->addr >> 11) & 0xffff];
sample = m_data[(chan->addr >> 11) & 0xffff];
if (sample == 0xff)
{
chan->addr = chan->loopst << 11;
sample = chip->data[(chan->addr >> 11) & 0xffff];
sample = m_data[(chan->addr >> 11) & 0xffff];
/* if we loop to a loop point, we're effectively dead */
if (sample == 0xff)
@ -131,56 +141,29 @@ static STREAM_UPDATE( rf5c68_update )
}
/************************************************/
/* RF5C68 start */
/************************************************/
//-------------------------------------------------
// RF5C68 write register
//-------------------------------------------------
static DEVICE_START( rf5c68 )
READ8_MEMBER( rf5c68_device::rf5c68_r )
{
const rf5c68_interface* intf = (const rf5c68_interface*)device->static_config();
/* allocate memory for the chip */
rf5c68_state *chip = get_safe_token(device);
memset(chip->data, 0xff, sizeof(chip->data));
/* allocate the stream */
chip->stream = device->machine().sound().stream_alloc(*device, 0, 2, device->clock() / 384, chip, rf5c68_update);
chip->device = device;
/* set up callback */
if(intf != NULL)
chip->sample_callback = intf->sample_end_callback;
else
chip->sample_callback = NULL;
}
/************************************************/
/* RF5C68 write register */
/************************************************/
READ8_DEVICE_HANDLER( rf5c68_r )
{
rf5c68_state *chip = get_safe_token(device);
UINT8 shift;
chip->stream->update();
m_stream->update();
shift = (offset & 1) ? 11 + 8 : 11;
// printf("%08x\n",(chip->chan[(offset & 0x0e) >> 1].addr));
// printf("%08x\n",(m_chan[(offset & 0x0e) >> 1].addr));
return (chip->chan[(offset & 0x0e) >> 1].addr) >> (shift);
return (m_chan[(offset & 0x0e) >> 1].addr) >> (shift);
}
WRITE8_DEVICE_HANDLER( rf5c68_w )
WRITE8_MEMBER( rf5c68_device::rf5c68_w )
{
rf5c68_state *chip = get_safe_token(device);
pcm_channel *chan = &chip->chan[chip->cbank];
rf5c68_pcm_channel *chan = &m_chan[m_cbank];
int i;
/* force the stream to update first */
chip->stream->update();
m_stream->update();
/* switch off the address */
switch (offset)
@ -216,80 +199,40 @@ WRITE8_DEVICE_HANDLER( rf5c68_w )
break;
case 0x07: /* control reg */
chip->enable = (data >> 7) & 1;
m_enable = (data >> 7) & 1;
if (data & 0x40)
chip->cbank = data & 7;
m_cbank = data & 7;
else
chip->wbank = data & 15;
m_wbank = data & 15;
break;
case 0x08: /* channel on/off reg */
for (i = 0; i < 8; i++)
{
chip->chan[i].enable = (~data >> i) & 1;
if (!chip->chan[i].enable)
chip->chan[i].addr = chip->chan[i].start << (8 + 11);
m_chan[i].enable = (~data >> i) & 1;
if (!m_chan[i].enable)
m_chan[i].addr = m_chan[i].start << (8 + 11);
}
break;
}
}
/************************************************/
/* RF5C68 read memory */
/************************************************/
//-------------------------------------------------
// RF5C68 read memory
//-------------------------------------------------
READ8_DEVICE_HANDLER( rf5c68_mem_r )
READ8_MEMBER( rf5c68_device::rf5c68_mem_r )
{
rf5c68_state *chip = get_safe_token(device);
return chip->data[chip->wbank * 0x1000 + offset];
return m_data[m_wbank * 0x1000 + offset];
}
/************************************************/
/* RF5C68 write memory */
/************************************************/
//-------------------------------------------------
// RF5C68 write memory
//-------------------------------------------------
WRITE8_DEVICE_HANDLER( rf5c68_mem_w )
WRITE8_MEMBER( rf5c68_device::rf5c68_mem_w )
{
rf5c68_state *chip = get_safe_token(device);
chip->data[chip->wbank * 0x1000 + offset] = data;
}
const device_type RF5C68 = &device_creator<rf5c68_device>;
rf5c68_device::rf5c68_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, RF5C68, "RF5C68", tag, owner, clock),
device_sound_interface(mconfig, *this)
{
m_token = global_alloc_clear(rf5c68_state);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void rf5c68_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void rf5c68_device::device_start()
{
DEVICE_START_NAME( rf5c68 )(this);
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
void rf5c68_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");
m_data[m_wbank * 0x1000 + offset] = data;
}

View file

@ -7,39 +7,82 @@
#ifndef __RF5C68_H__
#define __RF5C68_H__
#include "devlegcy.h"
#define RF5C68_NUM_CHANNELS (8)
/******************************************/
DECLARE_READ8_DEVICE_HANDLER( rf5c68_r );
DECLARE_WRITE8_DEVICE_HANDLER( rf5c68_w );
DECLARE_READ8_DEVICE_HANDLER( rf5c68_mem_r );
DECLARE_WRITE8_DEVICE_HANDLER( rf5c68_mem_w );
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_RF5C68_ADD(_tag, _clock) \
MCFG_DEVICE_ADD(_tag, RF5C68, _clock)
#define MCFG_RF5C68_REPLACE(_tag, _clock) \
MCFG_DEVICE_REPLACE(_tag, RF5C68, _clock)
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
struct rf5c68_interface
{
void (*sample_end_callback)(device_t* device, int channel);
};
struct rf5c68_pcm_channel
{
rf5c68_pcm_channel() :
enable(0),
env(0),
pan(0),
start(0),
addr(0),
step(0),
loopst(0) {}
UINT8 enable;
UINT8 env;
UINT8 pan;
UINT8 start;
UINT32 addr;
UINT16 step;
UINT16 loopst;
};
// ======================> rf5c68_device
class rf5c68_device : public device_t,
public device_sound_interface
public device_sound_interface
{
public:
rf5c68_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~rf5c68_device() { global_free(m_token); }
~rf5c68_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_READ8_MEMBER( rf5c68_r );
DECLARE_WRITE8_MEMBER( rf5c68_w );
DECLARE_READ8_MEMBER( rf5c68_mem_r );
DECLARE_WRITE8_MEMBER( rf5c68_mem_w );
private:
// internal state
void *m_token;
sound_stream* m_stream;
rf5c68_pcm_channel m_chan[RF5C68_NUM_CHANNELS];
UINT8 m_cbank;
UINT8 m_wbank;
UINT8 m_enable;
UINT8 m_data[0x10000];
void (*m_sample_callback)(device_t* device,int channel);
};
extern const device_type RF5C68;

View file

@ -11,37 +11,6 @@
/* the frequencies are later adjusted by "* clock / FSCALE" */
#define FSCALE 1024
struct tms_state {
char *subtype; /* subtype name MM6221AA, TMS3615 or TMS3617 */
sound_stream * channel; /* returned by stream_create() */
int samplerate; /* output sample rate */
int basefreq; /* chip's base frequency */
int octave; /* octave select of the TMS3615 */
int speed; /* speed of the tune */
int tune_counter; /* tune counter */
int note_counter; /* note counter */
int voices; /* active voices */
int shift; /* shift toggles between 0 and 6 to allow decaying voices */
int vol[12]; /* (decaying) volume of harmonics notes */
int vol_counter[12];/* volume adjustment counter */
int decay[12]; /* volume adjustment rate - dervied from decay */
int counter[12]; /* tone frequency counter */
int frequency[12]; /* tone frequency */
int output; /* output signal bits */
int enable; /* mask which harmoics */
int tune_num; /* tune currently playing */
int tune_ofs; /* note currently playing */
int tune_max; /* end of tune */
const tms36xx_interface *intf;
};
#define C(n) (int)((FSCALE<<(n-1))*1.18921) /* 2^(3/12) */
#define Cx(n) (int)((FSCALE<<(n-1))*1.25992) /* 2^(4/12) */
#define D(n) (int)((FSCALE<<(n-1))*1.33484) /* 2^(5/12) */
@ -299,62 +268,133 @@ static const int tune4[13*6] = {
static const int *const tunes[] = {NULL,tune1,tune2,tune3,tune4};
#define DECAY(voice) \
if( tms->vol[voice] > VMIN ) \
if( m_vol[voice] > VMIN ) \
{ \
/* decay of first voice */ \
tms->vol_counter[voice] -= tms->decay[voice]; \
while( tms->vol_counter[voice] <= 0 ) \
m_vol_counter[voice] -= m_decay[voice]; \
while( m_vol_counter[voice] <= 0 ) \
{ \
tms->vol_counter[voice] += samplerate; \
if( tms->vol[voice]-- <= VMIN ) \
m_vol_counter[voice] += samplerate; \
if( m_vol[voice]-- <= VMIN ) \
{ \
tms->frequency[voice] = 0; \
tms->vol[voice] = VMIN; \
m_frequency[voice] = 0; \
m_vol[voice] = VMIN; \
break; \
} \
} \
}
#define RESTART(voice) \
if( tunes[tms->tune_num][tms->tune_ofs*6+voice] ) \
if( tunes[m_tune_num][m_tune_ofs*6+voice] ) \
{ \
tms->frequency[tms->shift+voice] = \
tunes[tms->tune_num][tms->tune_ofs*6+voice] * \
(tms->basefreq << tms->octave) / FSCALE; \
tms->vol[tms->shift+voice] = VMAX; \
m_frequency[m_shift+voice] = \
tunes[m_tune_num][m_tune_ofs*6+voice] * \
(m_basefreq << m_octave) / FSCALE; \
m_vol[m_shift+voice] = VMAX; \
}
#define TONE(voice) \
if( (tms->enable & (1<<voice)) && tms->frequency[voice] ) \
if( (m_enable & (1<<voice)) && m_frequency[voice] ) \
{ \
/* first note */ \
tms->counter[voice] -= tms->frequency[voice]; \
while( tms->counter[voice] <= 0 ) \
m_counter[voice] -= m_frequency[voice]; \
while( m_counter[voice] <= 0 ) \
{ \
tms->counter[voice] += samplerate; \
tms->output ^= 1 << voice; \
m_counter[voice] += samplerate; \
m_output ^= 1 << voice; \
} \
if (tms->output & tms->enable & (1 << voice)) \
sum += tms->vol[voice]; \
if (m_output & m_enable & (1 << voice)) \
sum += m_vol[voice]; \
}
INLINE tms_state *get_safe_token(device_t *device)
// device type definition
const device_type TMS36XX = &device_creator<tms36xx_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tms36xx_device - constructor
//-------------------------------------------------
tms36xx_device::tms36xx_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, TMS36XX, "TMS36XX", tag, owner, clock),
device_sound_interface(mconfig, *this),
m_subtype(NULL),
m_channel(NULL),
m_samplerate(0),
m_basefreq(0),
m_octave(0),
m_speed(0),
m_tune_counter(0),
m_note_counter(0),
m_voices(0),
m_shift(0),
m_output(0),
m_enable(0),
m_tune_num(0),
m_tune_ofs(0),
m_tune_max(0),
m_intf(NULL)
{
assert(device != NULL);
assert(device->type() == TMS36XX);
return (tms_state *)downcast<tms36xx_device *>(device)->token();
memset(m_vol, 0, sizeof(int)*12);
memset(m_vol_counter, 0, sizeof(int)*12);
memset(m_decay, 0, sizeof(int)*12);
memset(m_counter, 0, sizeof(int)*12);
memset(m_frequency, 0, sizeof(int)*12);
}
static STREAM_UPDATE( tms36xx_sound_update )
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tms36xx_device::device_start()
{
tms_state *tms = (tms_state *)param;
int samplerate = tms->samplerate;
int j;
int enable;
m_intf = (const tms36xx_interface *)static_config();
m_channel = stream_alloc(0, 1, clock() * 64);
m_samplerate = clock() * 64;
m_basefreq = clock();
enable = 0;
for (j = 0; j < 6; j++)
{
if( m_intf->decay[j] > 0 )
{
m_decay[j+0] = m_decay[j+6] = VMAX / m_intf->decay[j];
enable |= 0x41 << j;
}
}
m_speed = (m_intf->speed > 0) ? VMAX / m_intf->speed : VMAX;
tms3617_enable(enable);
LOG(("TMS36xx samplerate %d\n", m_samplerate));
LOG(("TMS36xx basefreq %d\n", m_basefreq));
LOG(("TMS36xx decay %d,%d,%d,%d,%d,%d\n",
m_decay[0], m_decay[1], m_decay[2],
m_decay[3], m_decay[4], m_decay[5]));
LOG(("TMS36xx speed %d\n", m_speed));
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
void tms36xx_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
int samplerate = m_samplerate;
stream_sample_t *buffer = outputs[0];
/* no tune played? */
if( !tunes[tms->tune_num] || tms->voices == 0 )
if( !tunes[m_tune_num] || m_voices == 0 )
{
while (--samples >= 0)
buffer[samples] = 0;
@ -370,23 +410,23 @@ static STREAM_UPDATE( tms36xx_sound_update )
DECAY( 6) DECAY( 7) DECAY( 8) DECAY( 9) DECAY(10) DECAY(11)
/* musical note timing */
tms->tune_counter -= tms->speed;
if( tms->tune_counter <= 0 )
m_tune_counter -= m_speed;
if( m_tune_counter <= 0 )
{
int n = (-tms->tune_counter / samplerate) + 1;
tms->tune_counter += n * samplerate;
int n = (-m_tune_counter / samplerate) + 1;
m_tune_counter += n * samplerate;
if( (tms->note_counter -= n) <= 0 )
if( (m_note_counter -= n) <= 0 )
{
tms->note_counter += VMAX;
if (tms->tune_ofs < tms->tune_max)
m_note_counter += VMAX;
if (m_tune_ofs < m_tune_max)
{
/* shift to the other 'bank' of voices */
tms->shift ^= 6;
m_shift ^= 6;
/* restart one 'bank' of voices */
RESTART(0) RESTART(1) RESTART(2)
RESTART(3) RESTART(4) RESTART(5)
tms->tune_ofs++;
m_tune_ofs++;
}
}
}
@ -395,73 +435,95 @@ static STREAM_UPDATE( tms36xx_sound_update )
TONE( 0) TONE( 1) TONE( 2) TONE( 3) TONE( 4) TONE( 5)
TONE( 6) TONE( 7) TONE( 8) TONE( 9) TONE(10) TONE(11)
*buffer++ = sum / tms->voices;
*buffer++ = sum / m_voices;
}
}
static void tms36xx_reset_counters(tms_state *tms)
{
tms->tune_counter = 0;
tms->note_counter = 0;
memset(tms->vol_counter, 0, sizeof(tms->vol_counter));
memset(tms->counter, 0, sizeof(tms->counter));
}
void mm6221aa_tune_w(device_t *device, int tune)
{
tms_state *tms = get_safe_token(device);
//-------------------------------------------------
// MM6221AA interface functions
//-------------------------------------------------
void tms36xx_device::mm6221aa_tune_w(int tune)
{
/* which tune? */
tune &= 3;
if( tune == tms->tune_num )
if( tune == m_tune_num )
return;
LOG(("%s tune:%X\n", tms->subtype, tune));
LOG(("%s tune:%X\n", m_subtype, tune));
/* update the stream before changing the tune */
tms->channel->update();
m_channel->update();
tms->tune_num = tune;
tms->tune_ofs = 0;
tms->tune_max = 96; /* fixed for now */
m_tune_num = tune;
m_tune_ofs = 0;
m_tune_max = 96; /* fixed for now */
}
void tms36xx_note_w(device_t *device, int octave, int note)
{
tms_state *tms = get_safe_token(device);
//-------------------------------------------------
// TMS3615/17 interface functions
//-------------------------------------------------
void tms36xx_device::tms36xx_note_w(int octave, int note)
{
octave &= 3;
note &= 15;
if (note > 12)
return;
LOG(("%s octave:%X note:%X\n", tms->subtype, octave, note));
LOG(("%s octave:%X note:%X\n", m_subtype, octave, note));
/* update the stream before changing the tune */
tms->channel->update();
m_channel->update();
/* play a single note from 'tune 4', a list of the 13 tones */
tms36xx_reset_counters(tms);
tms->octave = octave;
tms->tune_num = 4;
tms->tune_ofs = note;
tms->tune_max = note + 1;
tms36xx_reset_counters();
m_octave = octave;
m_tune_num = 4;
m_tune_ofs = note;
m_tune_max = note + 1;
}
static void tms3617_enable(tms_state *tms, int enable)
//-------------------------------------------------
// TMS3617 interface functions
//-------------------------------------------------
void tms36xx_device::tms3617_enable_w(int enable)
{
tms3617_enable(enable);
}
//-------------------------------------------------
// Locals
//-------------------------------------------------
void tms36xx_device::tms36xx_reset_counters()
{
m_tune_counter = 0;
m_note_counter = 0;
memset(m_vol_counter, 0, sizeof(m_vol_counter));
memset(m_counter, 0, sizeof(m_counter));
}
void tms36xx_device::tms3617_enable(int enable)
{
int i, bits = 0;
/* duplicate the 6 voice enable bits */
enable = (enable & 0x3f) | ((enable & 0x3f) << 6);
if (enable == tms->enable)
if (enable == m_enable)
return;
/* update the stream before changing the tune */
tms->channel->update();
m_channel->update();
LOG(("%s enable voices", tms->subtype));
LOG(("%s enable voices", m_subtype));
for (i = 0; i < 6; i++)
{
if (enable & (1 << i))
@ -480,83 +542,7 @@ static void tms3617_enable(tms_state *tms, int enable)
}
}
/* set the enable mask and number of active voices */
tms->enable = enable;
tms->voices = bits;
m_enable = enable;
m_voices = bits;
LOG(("%s\n", bits ? "" : " none"));
}
void tms3617_enable_w(device_t *device, int enable)
{
tms_state *tms = get_safe_token(device);
tms3617_enable(tms, enable);
}
static DEVICE_START( tms36xx )
{
int j;
tms_state *tms = get_safe_token(device);
int enable;
tms->intf = (const tms36xx_interface *)device->static_config();
tms->channel = device->machine().sound().stream_alloc(*device, 0, 1, device->clock() * 64, tms, tms36xx_sound_update);
tms->samplerate = device->clock() * 64;
tms->basefreq = device->clock();
enable = 0;
for (j = 0; j < 6; j++)
{
if( tms->intf->decay[j] > 0 )
{
tms->decay[j+0] = tms->decay[j+6] = VMAX / tms->intf->decay[j];
enable |= 0x41 << j;
}
}
tms->speed = (tms->intf->speed > 0) ? VMAX / tms->intf->speed : VMAX;
tms3617_enable(tms,enable);
LOG(("TMS36xx samplerate %d\n", tms->samplerate));
LOG(("TMS36xx basefreq %d\n", tms->basefreq));
LOG(("TMS36xx decay %d,%d,%d,%d,%d,%d\n",
tms->decay[0], tms->decay[1], tms->decay[2],
tms->decay[3], tms->decay[4], tms->decay[5]));
LOG(("TMS36xx speed %d\n", tms->speed));
}
const device_type TMS36XX = &device_creator<tms36xx_device>;
tms36xx_device::tms36xx_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, TMS36XX, "TMS36XX", tag, owner, clock),
device_sound_interface(mconfig, *this)
{
m_token = global_alloc_clear(tms_state);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void tms36xx_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tms36xx_device::device_start()
{
DEVICE_START_NAME( tms36xx )(this);
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
void tms36xx_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

@ -3,49 +3,95 @@
#ifndef __TMS36XX_H__
#define __TMS36XX_H__
#include "devlegcy.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
/* subtypes */
#define MM6221AA 21 /* Phoenix (fixed melodies) */
#define TMS3615 15 /* Naughty Boy, Pleiads (13 notes, one output) */
#define TMS3617 17 /* Monster Bash (13 notes, six outputs) */
#define MCFG_TMS36XX_ADD(_tag, _clock) \
MCFG_DEVICE_ADD(_tag, TMS36XX, _clock)
#define MCFG_TMS36XX_REPLACE(_tag, _clock) \
MCFG_DEVICE_REPLACE(_tag, TMS36XX, _clock)
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// subtypes
#define MM6221AA 21 // Phoenix (fixed melodies)
#define TMS3615 15 // Naughty Boy, Pleiads (13 notes, one output)
#define TMS3617 17 // Monster Bash (13 notes, six outputs)
// ======================> tms36xx_interface
/* The interface structure */
struct tms36xx_interface
{
int subtype;
double decay[6]; /* decay times for the six harmonic notes */
double speed; /* tune speed (meaningful for the TMS3615 only) */
double decay[6]; // decay times for the six harmonic notes
double speed; // tune speed (meaningful for the TMS3615 only)
};
/* MM6221AA interface functions */
extern void mm6221aa_tune_w(device_t *device, int tune);
/* TMS3615/17 interface functions */
extern void tms36xx_note_w(device_t *device, int octave, int note);
/* TMS3617 interface functions */
extern void tms3617_enable_w(device_t *device, int enable);
// ======================> tms36xx_device
class tms36xx_device : public device_t,
public device_sound_interface
public device_sound_interface
{
public:
tms36xx_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~tms36xx_device() { global_free(m_token); }
~tms36xx_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:
// MM6221AA interface functions
void mm6221aa_tune_w(int tune);
// TMS3615/17 interface functions
void tms36xx_note_w(int octave, int note);
// TMS3617 interface functions
void tms3617_enable_w(int enable);
private:
// internal state
void *m_token;
void tms36xx_reset_counters();
void tms3617_enable(int enable);
private:
char *m_subtype; // subtype name MM6221AA, TMS3615 or TMS3617
sound_stream *m_channel; // returned by stream_create()
int m_samplerate; // output sample rate
int m_basefreq; // chip's base frequency
int m_octave; // octave select of the TMS3615
int m_speed; // speed of the tune
int m_tune_counter; // tune counter
int m_note_counter; // note counter
int m_voices; // active voices
int m_shift; // shift toggles between 0 and 6 to allow decaying voices
int m_vol[12]; // (decaying) volume of harmonics notes
int m_vol_counter[12];// volume adjustment counter
int m_decay[12]; // volume adjustment rate - dervied from decay
int m_counter[12]; // tone frequency counter
int m_frequency[12]; // tone frequency
int m_output; // output signal bits
int m_enable; // mask which harmoics
int m_tune_num; // tune currently playing
int m_tune_ofs; // note currently playing
int m_tune_max; // end of tune
const tms36xx_interface *m_intf;
};
extern const device_type TMS36XX;

View file

@ -69,7 +69,7 @@ struct phoenix_sound_state
sound_stream * m_channel;
UINT32 * m_poly18;
device_t *m_discrete;
device_t *m_tms;
tms36xx_device *m_tms;
};
INLINE phoenix_sound_state *get_safe_token( device_t *device )
@ -531,7 +531,7 @@ WRITE8_DEVICE_HANDLER( phoenix_sound_control_b_w )
discrete_sound_w(state->m_discrete, space, PHOENIX_EFFECT_1_FREQ, data & 0x10);
/* update the tune that the MM6221AA is playing */
mm6221aa_tune_w(state->m_tms, data >> 6);
state->m_tms->mm6221aa_tune_w(data >> 6);
}
static DEVICE_START( phoenix_sound )
@ -546,7 +546,7 @@ static DEVICE_START( phoenix_sound )
memset(&state->m_noise_state, 0, sizeof(state->m_noise_state));
state->m_discrete = device->machine().device("discrete");
state->m_tms = device->machine().device("tms");
state->m_tms = device->machine().device<tms36xx_device>("tms");
state->m_poly18 = auto_alloc_array(device->machine(), UINT32, 1ul << (18-5));

View file

@ -40,7 +40,7 @@ struct n_state
struct pleiads_sound_state
{
device_t *m_tms;
tms36xx_device *m_tms;
sound_stream *m_channel;
int m_sound_latch_a;
@ -451,7 +451,7 @@ WRITE8_DEVICE_HANDLER( pleiads_sound_control_b_w )
if (pitch == 3)
pitch = 2; /* 2 and 3 are the same */
tms36xx_note_w(state->m_tms, pitch, note);
state->m_tms->tms36xx_note_w(pitch, note);
state->m_channel->update();
state->m_sound_latch_b = data;
@ -477,7 +477,7 @@ static DEVICE_START( common_sh_start )
UINT32 shiftreg;
state->m_pc4.level = PC4_MIN;
state->m_tms = device->machine().device("tms");
state->m_tms = device->machine().device<tms36xx_device>("tms");
state->m_poly18 = auto_alloc_array(device->machine(), UINT32, 1ul << (18-5));
shiftreg = 0;

View file

@ -865,7 +865,7 @@ MACHINE_CONFIG_FRAGMENT( monsterb_sound_board )
MCFG_SAMPLES_ADD("samples", monsterb_samples_interface)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
MCFG_SOUND_ADD("music", TMS36XX, 247)
MCFG_TMS36XX_ADD("music", 247)
MCFG_SOUND_CONFIG(monsterb_tms3617_interface)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
@ -900,15 +900,15 @@ static SOUND_START( monsterb )
WRITE8_MEMBER(segag80r_state::monsterb_sound_a_w)
{
device_t *tms = machine().device("music");
tms36xx_device *tms = machine().device<tms36xx_device>("music");
int enable_val;
/* Lower four data lines get decoded into 13 control lines */
tms36xx_note_w(tms, 0, data & 15);
tms->tms36xx_note_w(0, data & 15);
/* Top four data lines address an 82S123 ROM that enables/disables voices */
enable_val = machine().root_device().memregion("prom")->base()[(data & 0xF0) >> 4];
tms3617_enable_w(tms, enable_val >> 2);
tms->tms3617_enable_w(enable_val >> 2);
}

View file

@ -441,7 +441,7 @@ static MACHINE_CONFIG_START( naughtyb, naughtyb_state )
/* uses the TMS3615NS for sound */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("tms", TMS36XX, 350)
MCFG_TMS36XX_ADD("tms", 350)
MCFG_SOUND_CONFIG(tms3615_interface)
MCFG_SOUND_ROUTE(0, "mono", 0.60)
@ -472,7 +472,7 @@ static MACHINE_CONFIG_START( popflame, naughtyb_state )
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("tms", TMS36XX, 350)
MCFG_TMS36XX_ADD("tms", 350)
MCFG_SOUND_CONFIG(tms3615_interface)
MCFG_SOUND_ROUTE(0, "mono", 0.60)

View file

@ -472,7 +472,7 @@ static MACHINE_CONFIG_START( phoenix, phoenix_state )
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("tms", TMS36XX, 372)
MCFG_TMS36XX_ADD("tms", 372)
MCFG_SOUND_CONFIG(phoenix_tms36xx_interface)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
@ -497,7 +497,7 @@ static MACHINE_CONFIG_DERIVED( pleiads, phoenix )
MCFG_PALETTE_INIT_OVERRIDE(phoenix_state,pleiads)
/* sound hardware */
MCFG_SOUND_REPLACE("tms", TMS36XX, 247)
MCFG_TMS36XX_REPLACE("tms", 247)
MCFG_SOUND_CONFIG(pleiads_tms36xx_interface)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75)

View file

@ -615,8 +615,8 @@ static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, segas18_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0x9fff) AM_ROM AM_REGION("soundcpu", 0x10000)
AM_RANGE(0xa000, 0xbfff) AM_ROMBANK("bank1")
AM_RANGE(0xc000, 0xc00f) AM_MIRROR(0x0ff0) AM_DEVWRITE_LEGACY("rfsnd", rf5c68_w)
AM_RANGE(0xd000, 0xdfff) AM_DEVREADWRITE_LEGACY("rfsnd", rf5c68_mem_r, rf5c68_mem_w)
AM_RANGE(0xc000, 0xc00f) AM_MIRROR(0x0ff0) AM_DEVWRITE("rfsnd", rf5c68_device, rf5c68_w)
AM_RANGE(0xd000, 0xdfff) AM_DEVREADWRITE("rfsnd", rf5c68_device, rf5c68_mem_r, rf5c68_mem_w)
AM_RANGE(0xe000, 0xffff) AM_RAM
ADDRESS_MAP_END
@ -1285,7 +1285,7 @@ static MACHINE_CONFIG_START( system18, segas18_state )
MCFG_SOUND_ADD("ym2", YM3438, 8000000)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
MCFG_SOUND_ADD("rfsnd", RF5C68, 10000000)
MCFG_RF5C68_ADD("rfsnd", 10000000)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
MACHINE_CONFIG_END

View file

@ -1224,8 +1224,8 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( system32_sound_map, AS_PROGRAM, 8, segas32_state )
AM_RANGE(0x0000, 0x9fff) AM_ROM AM_REGION("soundcpu", 0x100000)
AM_RANGE(0xa000, 0xbfff) AM_ROMBANK("bank1")
AM_RANGE(0xc000, 0xc00f) AM_MIRROR(0x0ff0) AM_DEVWRITE_LEGACY("rfsnd", rf5c68_w)
AM_RANGE(0xd000, 0xdfff) AM_DEVREADWRITE_LEGACY("rfsnd", rf5c68_mem_r, rf5c68_mem_w)
AM_RANGE(0xc000, 0xc00f) AM_MIRROR(0x0ff0) AM_DEVWRITE("rfsnd", rf5c68_device, rf5c68_w)
AM_RANGE(0xd000, 0xdfff) AM_DEVREADWRITE("rfsnd", rf5c68_device, rf5c68_mem_r, rf5c68_mem_w)
AM_RANGE(0xe000, 0xffff) AM_RAM AM_SHARE("z80_shared_ram")
ADDRESS_MAP_END
@ -2222,7 +2222,7 @@ static MACHINE_CONFIG_START( system32, segas32_state )
MCFG_SOUND_ROUTE(0, "lspeaker", 0.40)
MCFG_SOUND_ROUTE(1, "rspeaker", 0.40)
MCFG_SOUND_ADD("rfsnd", RF5C68, RFC_CLOCK/4)
MCFG_RF5C68_ADD("rfsnd", RFC_CLOCK/4)
MCFG_SOUND_ROUTE(0, "lspeaker", 0.55)
MCFG_SOUND_ROUTE(1, "rspeaker", 0.55)
MACHINE_CONFIG_END

View file

@ -1014,8 +1014,8 @@ static ADDRESS_MAP_START( sound_18_map, AS_PROGRAM, 8, segas1x_bootleg_state )
AM_RANGE(0x0000, 0x9fff) AM_ROM
AM_RANGE(0xa000, 0xbfff) AM_READ(system18_bank_r)
/**** D/A register ****/
AM_RANGE(0xc000, 0xc008) AM_DEVWRITE_LEGACY("5c68", rf5c68_w)
AM_RANGE(0xd000, 0xdfff) AM_DEVREADWRITE_LEGACY("5c68", rf5c68_mem_r, rf5c68_mem_w)
AM_RANGE(0xc000, 0xc008) AM_DEVWRITE("5c68", rf5c68_device, rf5c68_w)
AM_RANGE(0xd000, 0xdfff) AM_DEVREADWRITE("5c68", rf5c68_device, rf5c68_mem_r, rf5c68_mem_w)
AM_RANGE(0xe000, 0xffff) AM_RAM //??
ADDRESS_MAP_END
@ -2312,7 +2312,7 @@ static MACHINE_CONFIG_START( system18, segas1x_bootleg_state )
MCFG_SOUND_ROUTE(2, "lspeaker", 0.40)
MCFG_SOUND_ROUTE(3, "rspeaker", 0.40)
MCFG_SOUND_ADD("5c68", RF5C68, 8000000)
MCFG_RF5C68_ADD("5c68", 8000000)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0)
MACHINE_CONFIG_END

View file

@ -85,9 +85,9 @@ ADDRESS_MAP_START( segacd_map, AS_PROGRAM, 16, sega_segacd_device )
AM_RANGE(0xfe0000, 0xfe3fff) AM_READWRITE(segacd_backupram_r,segacd_backupram_w) AM_SHARE("backupram") // backup RAM, odd bytes only!
AM_RANGE(0xff0000, 0xff001f) AM_DEVWRITE8_LEGACY("rfsnd", rf5c68_w, 0x00ff) // PCM, RF5C164
AM_RANGE(0xff0020, 0xff003f) AM_DEVREAD8_LEGACY("rfsnd", rf5c68_r, 0x00ff)
AM_RANGE(0xff2000, 0xff3fff) AM_DEVREADWRITE8_LEGACY("rfsnd", rf5c68_mem_r, rf5c68_mem_w,0x00ff) // PCM, RF5C164
AM_RANGE(0xff0000, 0xff001f) AM_DEVWRITE8("rfsnd", rf5c68_device, rf5c68_w, 0x00ff) // PCM, RF5C164
AM_RANGE(0xff0020, 0xff003f) AM_DEVREAD8("rfsnd", rf5c68_device, rf5c68_r, 0x00ff)
AM_RANGE(0xff2000, 0xff3fff) AM_DEVREADWRITE8("rfsnd", rf5c68_device, rf5c68_mem_r, rf5c68_mem_w,0x00ff) // PCM, RF5C164
AM_RANGE(0xff8000 ,0xff8001) AM_READWRITE(segacd_sub_led_ready_r, segacd_sub_led_ready_w)
@ -147,7 +147,7 @@ static MACHINE_CONFIG_FRAGMENT( segacd_fragment )
MCFG_SOUND_ADD("rfsnd", RF5C68, SEGACD_CLOCK) // RF5C164!
MCFG_RF5C68_ADD("rfsnd", SEGACD_CLOCK) // RF5C164!
MCFG_SOUND_ROUTE( 0, ":lspeaker", 0.50 )
MCFG_SOUND_ROUTE( 1, ":rspeaker", 0.50 )

View file

@ -2181,7 +2181,7 @@ static ADDRESS_MAP_START(towns_mem, AS_PROGRAM, 32, towns_state)
AM_RANGE(0xc2100000, 0xc213ffff) AM_ROM AM_REGION("user",0x180000) // FONT ROM
AM_RANGE(0xc2140000, 0xc2141fff) AM_READWRITE8(towns_cmos_r,towns_cmos_w,0xffffffff) // CMOS (mirror?)
AM_RANGE(0xc2180000, 0xc21fffff) AM_ROM AM_REGION("user",0x080000) // F20 ROM
AM_RANGE(0xc2200000, 0xc220ffff) AM_DEVREADWRITE8_LEGACY("pcm",rf5c68_mem_r,rf5c68_mem_w,0xffffffff) // WAVE RAM
AM_RANGE(0xc2200000, 0xc220ffff) AM_DEVREADWRITE8("pcm", rf5c68_device, rf5c68_mem_r, rf5c68_mem_w, 0xffffffff) // WAVE RAM
AM_RANGE(0xfffc0000, 0xffffffff) AM_ROM AM_REGION("user",0x200000) // SYSTEM ROM
ADDRESS_MAP_END
@ -2207,7 +2207,7 @@ static ADDRESS_MAP_START(marty_mem, AS_PROGRAM, 32, towns_state)
AM_RANGE(0x00d00000, 0x00dfffff) AM_RAM // IC Memory Card (is this usable on the Marty?)
AM_RANGE(0x00e80000, 0x00efffff) AM_ROM AM_REGION("user",0x100000) // DIC ROM
AM_RANGE(0x00f00000, 0x00f7ffff) AM_ROM AM_REGION("user",0x180000) // FONT
AM_RANGE(0x00f80000, 0x00f8ffff) AM_DEVREADWRITE8_LEGACY("pcm",rf5c68_mem_r,rf5c68_mem_w,0xffffffff) // WAVE RAM
AM_RANGE(0x00f80000, 0x00f8ffff) AM_DEVREADWRITE8("pcm", rf5c68_device, rf5c68_mem_r, rf5c68_mem_w, 0xffffffff) // WAVE RAM
AM_RANGE(0x00fc0000, 0x00ffffff) AM_ROM AM_REGION("user",0x200000) // SYSTEM ROM
AM_RANGE(0xfffc0000, 0xffffffff) AM_ROM AM_REGION("user",0x200000) // SYSTEM ROM
ADDRESS_MAP_END
@ -2234,7 +2234,7 @@ static ADDRESS_MAP_START(ux_mem, AS_PROGRAM, 32, towns_state)
AM_RANGE(0x00e00000, 0x00e7ffff) AM_ROM AM_REGION("user",0x000000) // OS
AM_RANGE(0x00e80000, 0x00efffff) AM_ROM AM_REGION("user",0x100000) // DIC ROM
AM_RANGE(0x00f00000, 0x00f7ffff) AM_ROM AM_REGION("user",0x180000) // FONT
AM_RANGE(0x00f80000, 0x00f8ffff) AM_DEVREADWRITE8_LEGACY("pcm",rf5c68_mem_r,rf5c68_mem_w,0xffffffff) // WAVE RAM
AM_RANGE(0x00f80000, 0x00f8ffff) AM_DEVREADWRITE8("pcm", rf5c68_device, rf5c68_mem_r, rf5c68_mem_w, 0xffffffff) // WAVE RAM
AM_RANGE(0x00fc0000, 0x00ffffff) AM_ROM AM_REGION("user",0x200000) // SYSTEM ROM
AM_RANGE(0xfffc0000, 0xffffffff) AM_ROM AM_REGION("user",0x200000) // SYSTEM ROM
ADDRESS_MAP_END
@ -2274,7 +2274,7 @@ static ADDRESS_MAP_START( towns_io , AS_IO, 32, towns_state)
AM_RANGE(0x04d8,0x04df) AM_DEVREADWRITE8_LEGACY("fm",ym3438_r,ym3438_w,0x00ff00ff)
AM_RANGE(0x04e0,0x04e3) AM_READWRITE8(towns_volume_r,towns_volume_w,0xffffffff) // R/W -- volume ports
AM_RANGE(0x04e8,0x04ef) AM_READWRITE8(towns_sound_ctrl_r,towns_sound_ctrl_w,0xffffffff)
AM_RANGE(0x04f0,0x04fb) AM_DEVWRITE8_LEGACY("pcm",rf5c68_w,0xffffffff)
AM_RANGE(0x04f0,0x04fb) AM_DEVWRITE8("pcm", rf5c68_device, rf5c68_w, 0xffffffff)
// CRTC / Video
AM_RANGE(0x05c8,0x05cb) AM_READWRITE8(towns_video_5c8_r, towns_video_5c8_w, 0xffffffff)
// System ports
@ -2793,7 +2793,7 @@ static MACHINE_CONFIG_FRAGMENT( towns_base )
MCFG_SOUND_ADD("fm", YM3438, 53693100 / 7) // actual clock speed unknown
MCFG_SOUND_CONFIG(ym3438_intf)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MCFG_SOUND_ADD("pcm", RF5C68, 53693100 / 7) // actual clock speed unknown
MCFG_RF5C68_ADD("pcm", 53693100 / 7) // actual clock speed unknown
MCFG_SOUND_CONFIG(rf5c68_intf)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.50)
MCFG_SOUND_ADD("cdda",CDDA,0)