diff options
Diffstat (limited to 'src/mame/audio/snes_snd.c')
-rw-r--r-- | src/mame/audio/snes_snd.c | 188 |
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"); } - - |