summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/snes_snd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/audio/snes_snd.c')
-rw-r--r--src/mame/audio/snes_snd.c188
1 files changed, 93 insertions, 95 deletions
diff --git a/src/mame/audio/snes_snd.c b/src/mame/audio/snes_snd.c
index 98a5efe33fe..fba9c9cbd48 100644
--- a/src/mame/audio/snes_snd.c
+++ b/src/mame/audio/snes_snd.c
@@ -134,17 +134,17 @@ static const int mask = 0xFF;
The counter starts at 30720 (0x7800). */
static const int CNT_INIT = 0x7800;
static const int ENVCNT[0x20]
- = {
- 0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
- 0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
- 0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00,
- 0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800
- };
+ = {
+ 0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
+ 0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
+ 0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00,
+ 0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800
+ };
/* Make reading the ADSR code easier */
-#define SL( v ) (spc700->dsp_regs[((v) << 4) + 6] >> 5) /* Returns SUSTAIN level */
-#define SR( v ) (spc700->dsp_regs[((v) << 4) + 6] & 0x1f) /* Returns SUSTAIN rate */
+#define SL( v ) (spc700->dsp_regs[((v) << 4) + 6] >> 5) /* Returns SUSTAIN level */
+#define SR( v ) (spc700->dsp_regs[((v) << 4) + 6] & 0x1f) /* Returns SUSTAIN rate */
/* Handle endianness */
#define LEtoME16( x ) LITTLE_ENDIANIZE_INT16(x)
@@ -199,11 +199,11 @@ struct snes_sound_state
{
UINT8 *ram;
sound_stream *channel;
- UINT8 dsp_regs[256]; /* DSP registers */
- UINT8 ipl_region[64]; /* SPC top 64 bytes */
+ UINT8 dsp_regs[256]; /* DSP registers */
+ UINT8 ipl_region[64]; /* SPC top 64 bytes */
int keyed_on;
- int keys; /* 8-bits for 8 voices */
+ int keys; /* 8-bits for 8 voices */
voice_state_type voice_state[8];
/* Noise stuff */
@@ -224,8 +224,8 @@ struct snes_sound_state
UINT16 counter[3];
/* IO ports */
- UINT8 port_in[4]; /* SPC input ports */
- UINT8 port_out[4]; /* SPC output ports */
+ UINT8 port_in[4]; /* SPC input ports */
+ UINT8 port_out[4]; /* SPC output ports */
};
/*****************************************************************************
@@ -320,10 +320,10 @@ static void dsp_update( device_t *device, short *sound_ptr )
dsp_reset(device);
/* Here we check for keys on/off. Docs say that successive writes to KON/KOF
- must be separated by at least 2 Ts periods or risk being neglected.
- Therefore DSP only looks at these during an update, and not at the time of
- the write. Only need to do this once however, since the regs haven't
- changed over the whole period we need to catch up with. */
+ must be separated by at least 2 Ts periods or risk being neglected.
+ Therefore DSP only looks at these during an update, and not at the time of
+ the write. Only need to do this once however, since the regs haven't
+ changed over the whole period we need to catch up with. */
#ifdef DBG_KEY
spc700->dsp_regs[0x4c] &= mask;
#endif
@@ -332,8 +332,8 @@ static void dsp_update( device_t *device, short *sound_ptr )
spc700->dsp_regs[0x7c] &= ~spc700->dsp_regs[0x4c];
/* Question: what is the expected behavior when pitch modulation is enabled on
- voice 0? Jurassic Park 2 does this. For now, using outx of zero for first
- voice. */
+ voice 0? Jurassic Park 2 does this. For now, using outx of zero for first
+ voice. */
outx = 0;
/* Same table for noise and envelope */
@@ -377,10 +377,10 @@ static void dsp_update( device_t *device, short *sound_ptr )
vp->mixfrac = 3 * 4096;
/* NOTE: Real SNES does *not* appear to initialize the envelope
- counter to anything in particular. The first cycle always seems to
- come at a random time sooner than expected; as yet, I have been
- unable to find any pattern. I doubt it will matter though, so
- we'll go ahead and do the full time for now. */
+ counter to anything in particular. The first cycle always seems to
+ come at a random time sooner than expected; as yet, I have been
+ unable to find any pattern. I doubt it will matter though, so
+ we'll go ahead and do the full time for now. */
vp->envcnt = CNT_INIT;
vp->envstate = ATTACK;
}
@@ -419,7 +419,7 @@ static void dsp_update( device_t *device, short *sound_ptr )
#ifndef NO_PMOD
/* Pitch mod uses OUTX from last voice for this one. Luckily we haven't
- modified OUTX since it was used for last voice. */
+ modified OUTX since it was used for last voice. */
if (spc700->dsp_regs[0x2d] & m)
{
#ifdef DBG_PMOD
@@ -436,18 +436,18 @@ static void dsp_update( device_t *device, short *sound_ptr )
for ( ; vp->mixfrac >= 0; vp->mixfrac -= 4096)
{
/* This part performs the BRR decode 'on-the-fly'. This is more
- correct than the old way, which could be fooled if the data and/or
- the loop point changed while the sample was playing, or if the BRR
- decode didn't produce the same result every loop because of the
- filters. The event interface still has no chance of keeping up
- with those kinds of tricks, though. */
+ correct than the old way, which could be fooled if the data and/or
+ the loop point changed while the sample was playing, or if the BRR
+ decode didn't produce the same result every loop because of the
+ filters. The event interface still has no chance of keeping up
+ with those kinds of tricks, though. */
if (!vp->header_cnt)
{
if (vp->end & 1)
{
/* Docs say ENDX bit is set when decode of block with source
- end flag set is done. Does this apply to looping samples?
- Some info I've seen suggests yes. */
+ end flag set is done. Does this apply to looping samples?
+ Some info I've seen suggests yes. */
spc700->dsp_regs[0x7c] |= m;
if (vp->end & 2)
{
@@ -507,10 +507,10 @@ static void dsp_update( device_t *device, short *sound_ptr )
#endif
/* For invalid ranges (D,E,F): if the nybble is negative, the result
- is F000. If positive, 0000. Nothing else like previous range,
- etc. seems to have any effect. If range is valid, do the shift
- normally. Note these are both shifted right once to do the filters
- properly, but the output will be shifted back again at the end. */
+ is F000. If positive, 0000. Nothing else like previous range,
+ etc. seems to have any effect. If range is valid, do the shift
+ normally. Note these are both shifted right once to do the filters
+ properly, but the output will be shifted back again at the end. */
if (vp->range <= 0xc)
{
outx = (outx << vp->range) >> 1;
@@ -581,19 +581,19 @@ static void dsp_update( device_t *device, short *sound_ptr )
else
{
/* Perform 4-Point Gaussian interpolation. Take an approximation of a
- Gaussian bell-curve, and move it through the sample data at a rate
- determined by the pitch. The sample output at any given time is
- the sum of the products of each input sample point with the value
- of the bell-curve corresponding to that point. */
+ Gaussian bell-curve, and move it through the sample data at a rate
+ determined by the pitch. The sample output at any given time is
+ the sum of the products of each input sample point with the value
+ of the bell-curve corresponding to that point. */
vl = vp->mixfrac >> 4;
vr = ((G4[-vl-1] * vp->sampbuf[vp->sampptr]) >> 11 ) & ~1;
vr += ((G3[-vl] * vp->sampbuf[(vp->sampptr + 1) & 3]) >> 11) & ~1;
vr += ((G2[vl] * vp->sampbuf[(vp->sampptr + 2) & 3]) >> 11 ) & ~1;
/* This is to do the wrapping properly. Based on my tests with the
- SNES, it appears clipping is done only if it is the fourth addition
- that would cause a wrap. If it has already wrapped before the
- fourth addition, it is not clipped. */
+ SNES, it appears clipping is done only if it is the fourth addition
+ that would cause a wrap. If it has already wrapped before the
+ fourth addition, it is not clipped. */
vr = (signed short)vr;
vr += ((G1[vl] * vp->sampbuf[(vp->sampptr + 3) & 3]) >> 11) & ~1;
@@ -643,7 +643,7 @@ static void dsp_update( device_t *device, short *sound_ptr )
#ifndef NO_ECHO
/* Perform echo. First, read mem at current location, and put those samples
- into the FIR filter queue. */
+ into the FIR filter queue. */
#ifdef DBG_ECHO
logerror("Echo delay=%dms, feedback=%d%%\n", spc700->dsp_regs[0x7d] * 16,
((signed char)spc700->dsp_regs[0x0d] * 100) / 0x7f);
@@ -744,7 +744,7 @@ static void dsp_update( device_t *device, short *sound_ptr )
else
{
if (outl > 32767)
- *sound_ptr = 32767;
+ *sound_ptr = 32767;
else if (outl < -32768)
*sound_ptr = -32768;
else
@@ -753,7 +753,7 @@ static void dsp_update( device_t *device, short *sound_ptr )
sound_ptr++;
if (outr > 32767)
- *sound_ptr = 32767;
+ *sound_ptr = 32767;
else if (outr < -32768)
*sound_ptr = -32768;
else
@@ -785,11 +785,11 @@ static int advance_envelope( device_t *device, int v )
if (spc700->voice_state[v].envstate == RELEASE)
{
/* Docs: "When in the state of "key off". the "click" sound is prevented
- by the addition of the fixed value 1/256" WTF??? Alright, I'm going
- to choose to interpret that this way: When a note is keyed off, start
- the RELEASE state, which subtracts 1/256th each sample period (32kHz).
- Note there's no need for a count because it always happens every
- update. */
+ by the addition of the fixed value 1/256" WTF??? Alright, I'm going
+ to choose to interpret that this way: When a note is keyed off, start
+ the RELEASE state, which subtracts 1/256th each sample period (32kHz).
+ Note there's no need for a count because it always happens every
+ update. */
envx -= 0x8; /* 0x8 / 0x800 = 1/256th */
if (envx <= 0)
{
@@ -817,11 +817,11 @@ static int advance_envelope( device_t *device, int v )
{
case ATTACK:
/* Docs are very confusing. "AR is multiplied by the fixed value
- 1/64..." I believe it means to add 1/64th to ENVX once every
- time ATTACK is updated, and that's what I'm going to implement. */
+ 1/64..." I believe it means to add 1/64th to ENVX once every
+ time ATTACK is updated, and that's what I'm going to implement. */
t = adsr1 & 0x0f;
- if (t == 0x0f)
+ if (t == 0x0f)
{
#ifdef DBG_ENV
logerror("ENV voice %d: instant attack\n", v);
@@ -855,8 +855,8 @@ static int advance_envelope( device_t *device, int v )
case DECAY:
/* Docs: "DR... [is multiplied] by the fixed value 1-1/256."
- Well, at least that makes some sense. Multiplying ENVX by
- 255/256 every time DECAY is updated. */
+ Well, at least that makes some sense. Multiplying ENVX by
+ 255/256 every time DECAY is updated. */
cnt -= ENVCNT[((adsr1 >> 3) & 0x0e) + 0x10];
if (cnt <= 0)
@@ -877,7 +877,7 @@ static int advance_envelope( device_t *device, int v )
case SUSTAIN:
/* Docs: "SR [is multiplied] by the fixed value 1-1/256."
- Multiplying ENVX by 255/256 every time SUSTAIN is updated. */
+ Multiplying ENVX by 255/256 every time SUSTAIN is updated. */
#ifdef DBG_ENV
if (ENVCNT[SR(v)] == 0)
logerror("ENV voice %d: envx=%03X, state=SUSTAIN, zero rate\n", v, envx);
@@ -906,14 +906,14 @@ static int advance_envelope( device_t *device, int v )
else
{
/* GAIN mode is set
- Note: if the game switches between ADSR and GAIN modes partway
- through, should the count be reset, or should it continue from
- where it was? Does the DSP actually watch for that bit to
- change, or does it just go along with whatever it sees when it
- performs the update? I'm going to assume the latter and not
- update the count, unless I see a game that obviously wants the
- other behavior. The effect would be pretty subtle, in any case.
- */
+ Note: if the game switches between ADSR and GAIN modes partway
+ through, should the count be reset, or should it continue from
+ where it was? Does the DSP actually watch for that bit to
+ change, or does it just go along with whatever it sees when it
+ performs the update? I'm going to assume the latter and not
+ update the count, unless I see a game that obviously wants the
+ other behavior. The effect would be pretty subtle, in any case.
+ */
t = spc700->dsp_regs[(v << 4) + 7];
if (t < 0x80)
@@ -987,7 +987,7 @@ static int advance_envelope( device_t *device, int v )
case 7:
/* Docs: "Increase (bent line): Addition of the constant
- 1/64 up to .75 of the constaint <sic> 1/256 from .75 to 1." */
+ 1/64 up to .75 of the constaint <sic> 1/256 from .75 to 1." */
cnt -= ENVCNT[t & 0x1f];
if (cnt > 0)
@@ -1111,32 +1111,32 @@ READ8_DEVICE_HANDLER( spc_io_r )
{
snes_sound_state *spc700 = get_safe_token(device);
- switch (offset) /* Offset is from 0x00f0 */
+ switch (offset) /* Offset is from 0x00f0 */
{
case 0x0: //FIXME: Super Bomberman PBW reads from there, is it really write-only?
return 0;
case 0x1:
return 0; //Super Kick Boxing reads port 1 and wants it to be zero.
- case 0x2: /* Register address */
+ case 0x2: /* Register address */
return spc700->ram[0xf2];
- case 0x3: /* Register data */
+ case 0x3: /* Register data */
return snes_dsp_io_r(device, space, spc700->ram[0xf2]);
- case 0x4: /* Port 0 */
- case 0x5: /* Port 1 */
- case 0x6: /* Port 2 */
- case 0x7: /* Port 3 */
+ case 0x4: /* Port 0 */
+ case 0x5: /* Port 1 */
+ case 0x6: /* Port 2 */
+ case 0x7: /* Port 3 */
// mame_printf_debug("SPC: rd %02x @ %d, PC=%x\n", spc700->port_in[offset - 4], offset - 4, space.device().safe_pc());
return spc700->port_in[offset - 4];
case 0x8: //normal RAM, can be read even if the ram disabled flag ($f0 bit 1) is active
case 0x9:
return spc700->ram[0xf0 + offset];
- case 0xa: /* Timer 0 */
- case 0xb: /* Timer 1 */
- case 0xc: /* Timer 2 */
+ case 0xa: /* Timer 0 */
+ case 0xb: /* Timer 1 */
+ case 0xc: /* Timer 2 */
break;
- case 0xd: /* Counter 0 */
- case 0xe: /* Counter 1 */
- case 0xf: /* Counter 2 */
+ case 0xd: /* Counter 0 */
+ case 0xe: /* Counter 1 */
+ case 0xf: /* Counter 2 */
{
UINT8 value = spc700->ram[0xf0 + offset] & 0x0f;
spc700->ram[0xf0 + offset] = 0;
@@ -1152,12 +1152,12 @@ WRITE8_DEVICE_HANDLER( spc_io_w )
snes_sound_state *spc700 = get_safe_token(device);
int i;
- switch (offset) /* Offset is from 0x00f0 */
+ switch (offset) /* Offset is from 0x00f0 */
{
case 0x0:
printf("Warning: write to SOUND TEST register with data %02x!\n", data);
break;
- case 0x1: /* Control */
+ case 0x1: /* Control */
for (i = 0; i < 3; i++)
{
if (BIT(data, i) && !spc700->enabled[i])
@@ -1184,29 +1184,29 @@ WRITE8_DEVICE_HANDLER( spc_io_w )
/* bit 7 = IPL ROM enable */
break;
- case 0x2: /* Register address */
+ case 0x2: /* Register address */
break;
- case 0x3: /* Register data - 0x80-0xff is a read-only mirror of 0x00-0x7f */
+ case 0x3: /* Register data - 0x80-0xff is a read-only mirror of 0x00-0x7f */
if (!(spc700->ram[0xf2] & 0x80))
snes_dsp_io_w(device, space, spc700->ram[0xf2] & 0x7f, data);
break;
- case 0x4: /* Port 0 */
- case 0x5: /* Port 1 */
- case 0x6: /* Port 2 */
- case 0x7: /* Port 3 */
+ case 0x4: /* Port 0 */
+ case 0x5: /* Port 1 */
+ case 0x6: /* Port 2 */
+ case 0x7: /* Port 3 */
// mame_printf_debug("SPC: %02x to APU @ %d (PC=%x)\n", data, offset & 3, space.device().safe_pc());
spc700->port_out[offset - 4] = data;
space.machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(20));
break;
- case 0xa: /* Timer 0 */
- case 0xb: /* Timer 1 */
- case 0xc: /* Timer 2 */
+ case 0xa: /* Timer 0 */
+ case 0xb: /* Timer 1 */
+ case 0xc: /* Timer 2 */
if (data == 0)
data = 255;
break;
- case 0xd: /* Counter 0 */
- case 0xe: /* Counter 1 */
- case 0xf: /* Counter 2 */
+ case 0xd: /* Counter 0 */
+ case 0xe: /* Counter 1 */
+ case 0xf: /* Counter 2 */
return;
}
@@ -1364,7 +1364,7 @@ const device_type SNES = &device_creator<snes_sound_device>;
snes_sound_device::snes_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SNES, "SNES Custom DSP (SPC700)", tag, owner, clock),
- device_sound_interface(mconfig, *this)
+ device_sound_interface(mconfig, *this)
{
m_token = global_alloc_clear(snes_sound_state);
}
@@ -1406,5 +1406,3 @@ void snes_sound_device::sound_stream_update(sound_stream &stream, stream_sample_
// should never get here
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
}
-
-