aboutsummaryrefslogtreecommitdiff
path: root/source/apu.c
diff options
context:
space:
mode:
authorJoão Silva2017-01-24 20:32:46 +0000
committerJoão Silva2017-01-24 20:34:46 +0000
commitd8b66ac6d0524b3538ad595825651b28329f9033 (patch)
treeadfe26e0b4277bae4a3c4f8219c5912d4fcba830 /source/apu.c
parent47d3fc8ce090ec6ca06ff4e27dcf7db09588dae0 (diff)
downloadsnes9x2005-d8b66ac6d0524b3538ad595825651b28329f9033.tar.gz
snes9x2005-d8b66ac6d0524b3538ad595825651b28329f9033.tar.bz2
snes9x2005-d8b66ac6d0524b3538ad595825651b28329f9033.zip
Sound improvements - some by me, most from snes9x2002 and snes9x 1.51.
Diffstat (limited to 'source/apu.c')
-rw-r--r--source/apu.c299
1 files changed, 62 insertions, 237 deletions
diff --git a/source/apu.c b/source/apu.c
index 500a884..efbd4b5 100644
--- a/source/apu.c
+++ b/source/apu.c
@@ -8,7 +8,9 @@
#include "soundux.h"
#include "cpuexec.h"
-extern int32_t NoiseFreq [32];
+extern int32_t NoiseFreq [32];
+extern uint16_t DecreaseRateExp [32];
+extern uint16_t IncreaseRate [32];
bool S9xInitAPU()
{
@@ -20,8 +22,6 @@ bool S9xInitAPU()
return (false);
}
- memset(IAPU.RAM, 0, 0x10000);
-
return (true);
}
@@ -40,7 +40,7 @@ void S9xResetAPU()
{
int i, j;
- Settings.APUEnabled = Settings.NextAPUEnabled;
+ Settings.APUEnabled = true;
memset(IAPU.RAM, 0, 0x100);
memset(IAPU.RAM + 0x20, 0xFF, 0x20);
@@ -125,13 +125,11 @@ void S9xSetAPUDSP(uint8_t byte)
else
{
S9xSetEchoWriteEnable(!(byte & APU_ECHO_DISABLED));
-
+ so.mute_sound = !!(byte & APU_MUTE);
SoundData.noise_hertz = NoiseFreq [byte & 0x1f];
for (i = 0; i < 8; i++)
- {
if (SoundData.channels [i].type == SOUND_NOISE)
S9xSetSoundFrequency(i, SoundData.noise_hertz);
- }
}
break;
case APU_NON:
@@ -154,36 +152,23 @@ void S9xSetAPUDSP(uint8_t byte)
break;
case APU_MVOL_LEFT:
if (byte != APU.DSP [APU_MVOL_LEFT])
- {
- S9xSetMasterVolume((signed char) byte,
- (signed char) APU.DSP [APU_MVOL_RIGHT]);
- }
+ S9xSetMasterVolume((int8_t) byte, (int8_t) APU.DSP [APU_MVOL_RIGHT]);
break;
case APU_MVOL_RIGHT:
if (byte != APU.DSP [APU_MVOL_RIGHT])
- {
- S9xSetMasterVolume((signed char) APU.DSP [APU_MVOL_LEFT],
- (signed char) byte);
- }
+ S9xSetMasterVolume((int8_t) APU.DSP [APU_MVOL_LEFT], (int8_t) byte);
break;
case APU_EVOL_LEFT:
if (byte != APU.DSP [APU_EVOL_LEFT])
- {
- S9xSetEchoVolume((signed char) byte,
- (signed char) APU.DSP [APU_EVOL_RIGHT]);
- }
+ S9xSetEchoVolume((int8_t) byte, (int8_t) APU.DSP [APU_EVOL_RIGHT]);
break;
case APU_EVOL_RIGHT:
if (byte != APU.DSP [APU_EVOL_RIGHT])
- {
- S9xSetEchoVolume((signed char) APU.DSP [APU_EVOL_LEFT],
- (signed char) byte);
- }
+ S9xSetEchoVolume((int8_t) APU.DSP [APU_EVOL_LEFT], (int8_t) byte);
break;
case APU_ENDX:
byte = 0;
break;
-
case APU_KOFF:
{
int c;
@@ -194,12 +179,10 @@ void S9xSetAPUDSP(uint8_t byte)
{
if (APU.KeyedChannels & mask)
{
- {
- KeyOnPrev &= ~mask;
- APU.KeyedChannels &= ~mask;
- APU.DSP [APU_KON] &= ~mask;
- S9xSetSoundKeyOff(c);
- }
+ KeyOnPrev &= ~mask;
+ APU.KeyedChannels &= ~mask;
+ APU.DSP [APU_KON] &= ~mask;
+ S9xSetSoundKeyOff(c);
}
}
else if ((KeyOnPrev & mask) != 0)
@@ -211,9 +194,10 @@ void S9xSetAPUDSP(uint8_t byte)
S9xPlaySample(c);
}
}
+
+ APU.DSP [APU_KOFF] = byte;
+ return;
}
- APU.DSP [APU_KOFF] = byte;
- return;
case APU_KON:
if (byte)
{
@@ -237,7 +221,6 @@ void S9xSetAPUDSP(uint8_t byte)
}
}
return;
-
case APU_VOL_LEFT + 0x00:
case APU_VOL_LEFT + 0x10:
case APU_VOL_LEFT + 0x20:
@@ -246,11 +229,8 @@ void S9xSetAPUDSP(uint8_t byte)
case APU_VOL_LEFT + 0x50:
case APU_VOL_LEFT + 0x60:
case APU_VOL_LEFT + 0x70:
- {
- S9xSetSoundVolume(reg >> 4, (signed char) byte,
- (signed char) APU.DSP [reg + 1]);
- }
- break;
+ S9xSetSoundVolume(reg >> 4, (int8_t) byte, (int8_t) APU.DSP [reg + 1]);
+ break;
case APU_VOL_RIGHT + 0x00:
case APU_VOL_RIGHT + 0x10:
case APU_VOL_RIGHT + 0x20:
@@ -259,12 +239,8 @@ void S9xSetAPUDSP(uint8_t byte)
case APU_VOL_RIGHT + 0x50:
case APU_VOL_RIGHT + 0x60:
case APU_VOL_RIGHT + 0x70:
- {
- S9xSetSoundVolume(reg >> 4, (signed char) APU.DSP [reg - 1],
- (signed char) byte);
- }
- break;
-
+ S9xSetSoundVolume(reg >> 4, (int8_t) APU.DSP [reg - 1], (int8_t) byte);
+ break;
case APU_P_LOW + 0x00:
case APU_P_LOW + 0x10:
case APU_P_LOW + 0x20:
@@ -273,10 +249,8 @@ void S9xSetAPUDSP(uint8_t byte)
case APU_P_LOW + 0x50:
case APU_P_LOW + 0x60:
case APU_P_LOW + 0x70:
- S9xSetSoundHertz(reg >> 4,
- (((byte + (APU.DSP [reg + 1] << 8)) & FREQUENCY_MASK) * 32000) >> 12);
+ S9xSetSoundHertz(reg >> 4, ((byte + (APU.DSP [reg + 1] << 8)) & FREQUENCY_MASK) / 8);
break;
-
case APU_P_HIGH + 0x00:
case APU_P_HIGH + 0x10:
case APU_P_HIGH + 0x20:
@@ -285,20 +259,8 @@ void S9xSetAPUDSP(uint8_t byte)
case APU_P_HIGH + 0x50:
case APU_P_HIGH + 0x60:
case APU_P_HIGH + 0x70:
- S9xSetSoundHertz(reg >> 4,
- (((byte << 8) + APU.DSP [reg - 1]) & FREQUENCY_MASK) * 8);
- break;
-
- case APU_SRCN + 0x00:
- case APU_SRCN + 0x10:
- case APU_SRCN + 0x20:
- case APU_SRCN + 0x30:
- case APU_SRCN + 0x40:
- case APU_SRCN + 0x50:
- case APU_SRCN + 0x60:
- case APU_SRCN + 0x70:
+ S9xSetSoundHertz(reg >> 4, (((byte << 8) + APU.DSP [reg - 1]) & FREQUENCY_MASK) * 8);
break;
-
case APU_ADSR1 + 0x00:
case APU_ADSR1 + 0x10:
case APU_ADSR1 + 0x20:
@@ -307,15 +269,9 @@ void S9xSetAPUDSP(uint8_t byte)
case APU_ADSR1 + 0x50:
case APU_ADSR1 + 0x60:
case APU_ADSR1 + 0x70:
- if (byte != APU.DSP [reg])
- {
- {
- S9xFixEnvelope(reg >> 4, APU.DSP [reg + 2], byte,
- APU.DSP [reg + 1]);
- }
- }
+ if(byte != APU.DSP [reg])
+ S9xFixEnvelope(reg >> 4, APU.DSP [reg + 2], byte, APU.DSP [reg + 1]);
break;
-
case APU_ADSR2 + 0x00:
case APU_ADSR2 + 0x10:
case APU_ADSR2 + 0x20:
@@ -324,15 +280,9 @@ void S9xSetAPUDSP(uint8_t byte)
case APU_ADSR2 + 0x50:
case APU_ADSR2 + 0x60:
case APU_ADSR2 + 0x70:
- if (byte != APU.DSP [reg])
- {
- {
- S9xFixEnvelope(reg >> 4, APU.DSP [reg + 1], APU.DSP [reg - 1],
- byte);
- }
- }
+ if(byte != APU.DSP [reg])
+ S9xFixEnvelope(reg >> 4, APU.DSP [reg + 1], APU.DSP [reg - 1], byte);
break;
-
case APU_GAIN + 0x00:
case APU_GAIN + 0x10:
case APU_GAIN + 0x20:
@@ -341,59 +291,23 @@ void S9xSetAPUDSP(uint8_t byte)
case APU_GAIN + 0x50:
case APU_GAIN + 0x60:
case APU_GAIN + 0x70:
- if (byte != APU.DSP [reg])
- {
- {
- S9xFixEnvelope(reg >> 4, byte, APU.DSP [reg - 2],
- APU.DSP [reg - 1]);
- }
- }
- break;
-
- case APU_ENVX + 0x00:
- case APU_ENVX + 0x10:
- case APU_ENVX + 0x20:
- case APU_ENVX + 0x30:
- case APU_ENVX + 0x40:
- case APU_ENVX + 0x50:
- case APU_ENVX + 0x60:
- case APU_ENVX + 0x70:
- break;
-
- case APU_OUTX + 0x00:
- case APU_OUTX + 0x10:
- case APU_OUTX + 0x20:
- case APU_OUTX + 0x30:
- case APU_OUTX + 0x40:
- case APU_OUTX + 0x50:
- case APU_OUTX + 0x60:
- case APU_OUTX + 0x70:
+ if(byte != APU.DSP [reg])
+ S9xFixEnvelope(reg >> 4, byte, APU.DSP [reg - 2], APU.DSP [reg - 1]);
break;
-
- case APU_DIR:
- break;
-
case APU_PMON:
- if (byte != APU.DSP [APU_PMON])
+ if(byte != APU.DSP [APU_PMON])
S9xSetFrequencyModulationEnable(byte);
break;
-
case APU_EON:
- if (byte != APU.DSP [APU_EON])
+ if(byte != APU.DSP [APU_EON])
S9xSetEchoEnable(byte);
break;
-
case APU_EFB:
- S9xSetEchoFeedback((signed char) byte);
- break;
-
- case APU_ESA:
+ S9xSetEchoFeedback((int8_t) byte);
break;
-
case APU_EDL:
S9xSetEchoDelay(byte & 0xf);
break;
-
case APU_C0:
case APU_C1:
case APU_C2:
@@ -402,7 +316,7 @@ void S9xSetAPUDSP(uint8_t byte)
case APU_C5:
case APU_C6:
case APU_C7:
- S9xSetFilterCoefficient(reg >> 4, (signed char) byte);
+ S9xSetFilterCoefficient(reg >> 4, (int8_t) byte);
break;
default:
break;
@@ -417,93 +331,39 @@ void S9xSetAPUDSP(uint8_t byte)
void S9xFixEnvelope(int channel, uint8_t gain, uint8_t adsr1, uint8_t adsr2)
{
- if (adsr1 & 0x80)
+ if (adsr1 & 0x80) // ADSR mode
{
- // ADSR mode
- static unsigned long AttackRate [16] =
- {
- 4100u, 2600u, 1500u, 1000u, 640u, 380u, 260u, 160u,
- 96u, 64u, 40u, 24u, 16u, 10u, 6u, 1u
- };
- static unsigned long DecayRate [8] =
- {
- 1200u, 740u, 440u, 290u, 180u, 110u, 74u, 37u
- };
- static unsigned long SustainRate [32] =
- {
- ~0u, 38000u, 28000u, 24000u, 19000u, 14000u, 12000u, 9400u,
- 7100u, 5900u, 4700u, 3500u, 2900u, 2400u, 1800u, 1500u,
- 1200u, 880u, 740u, 590u, 440u, 370u, 290u, 220u,
- 180u, 150u, 110u, 92u, 74u, 55u, 37u, 18u
- };
// XXX: can DSP be switched to ADSR mode directly from GAIN/INCREASE/
// DECREASE mode? And if so, what stage of the sequence does it start
// at?
- if (S9xSetSoundMode(channel, MODE_ADSR))
+ if(S9xSetSoundMode(channel, MODE_ADSR))
+ S9xSetSoundADSR(channel, adsr1 & 0xf, (adsr1 >> 4) & 7, adsr2 & 0x1f, (adsr2 >> 5) & 7, 8);
+ } // Gain mode
+ else if ((gain & 0x80) == 0)
+ {
+ if (S9xSetSoundMode(channel, MODE_GAIN))
{
- // Hack for ROMs that use a very short attack rate, key on a
- // channel, then switch to decay mode. e.g. Final Fantasy II.
-
- int attack = AttackRate [adsr1 & 0xf];
-
- if (attack == 1 && (!Settings.SoundSync))
- attack = 0;
-
- S9xSetSoundADSR(channel, attack,
- DecayRate [(adsr1 >> 4) & 7],
- SustainRate [adsr2 & 0x1f],
- (adsr2 >> 5) & 7, 8);
+ S9xSetEnvelopeRate(channel, 0, 0, gain & 0x7f, 0);
+ S9xSetEnvelopeHeight(channel, gain & 0x7f);
}
}
+ else if (gain & 0x40)
+ {
+ // Increase mode
+ if(S9xSetSoundMode(channel, (gain & 0x20) ?
+ MODE_INCREASE_BENT_LINE :
+ MODE_INCREASE_LINEAR))
+ S9xSetEnvelopeRate(channel, IncreaseRate [gain & 0x1f], 1, 127, (3 << 28) | gain);
+ }
+ else if (gain & 0x20)
+ {
+ if(S9xSetSoundMode(channel, MODE_DECREASE_EXPONENTIAL))
+ S9xSetEnvelopeRate(channel, DecreaseRateExp [gain & 0x1f] / 2, -1, 0, (4 << 28) | gain);
+ }
else
{
- // Gain mode
- if ((gain & 0x80) == 0)
- {
- if (S9xSetSoundMode(channel, MODE_GAIN))
- {
- S9xSetEnvelopeRate(channel, 0, 0, gain & 0x7f);
- S9xSetEnvelopeHeight(channel, gain & 0x7f);
- }
- }
- else
- {
- static unsigned long IncreaseRate [32] =
- {
- ~0u, 4100u, 3100u, 2600u, 2000u, 1500u, 1300u, 1000u,
- 770u, 640u, 510u, 380u, 320u, 260u, 190u, 160u,
- 130u, 96u, 80u, 64u, 48u, 40u, 32u, 24u,
- 20u, 16u, 12u, 10u, 8u, 6u, 4u, 2u
- };
- static unsigned long DecreaseRateExp [32] =
- {
- ~0u, 38000u, 28000u, 24000u, 19000u, 14000u, 12000u, 9400u,
- 7100u, 5900u, 4700u, 3500u, 2900u, 2400u, 1800u, 1500u,
- 1200u, 880u, 740u, 590u, 440u, 370u, 290u, 220u,
- 180u, 150u, 110u, 92u, 74u, 55u, 37u, 18u
- };
- if (gain & 0x40)
- {
- // Increase mode
- if (S9xSetSoundMode(channel, (gain & 0x20) ?
- MODE_INCREASE_BENT_LINE :
- MODE_INCREASE_LINEAR))
- {
- S9xSetEnvelopeRate(channel, IncreaseRate [gain & 0x1f],
- 1, 127);
- }
- }
- else
- {
- uint32_t rate = (gain & 0x20) ? DecreaseRateExp [gain & 0x1f] / 2 :
- IncreaseRate [gain & 0x1f];
- int mode = (gain & 0x20) ? MODE_DECREASE_EXPONENTIAL
- : MODE_DECREASE_LINEAR;
-
- if (S9xSetSoundMode(channel, mode))
- S9xSetEnvelopeRate(channel, rate, -1, 0);
- }
- }
+ if (S9xSetSoundMode(channel, MODE_DECREASE_LINEAR))
+ S9xSetEnvelopeRate(channel, IncreaseRate [gain & 0x1f], -1, 0, (3 << 28) | gain);
}
}
@@ -550,43 +410,16 @@ void S9xSetAPUControl(uint8_t byte)
APU.ShowROM = true;
}
}
- else
+ else if (APU.ShowROM)
{
- if (APU.ShowROM)
- {
- APU.ShowROM = false;
- // memmove converted: Different mallocs [Neb]
- // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb]
- memcpy(&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof(APUROM));
- }
+ APU.ShowROM = false;
+ // memmove converted: Different mallocs [Neb]
+ // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb]
+ memcpy(&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof(APUROM));
}
IAPU.RAM [0xf1] = byte;
}
-void S9xSetAPUTimer(uint16_t Address, uint8_t byte)
-{
- IAPU.RAM [Address] = byte;
-
- switch (Address)
- {
- case 0xfa:
- if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0)
- APU.TimerTarget [0] = 0x100;
- APU.TimerValueWritten [0] = true;
- break;
- case 0xfb:
- if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0)
- APU.TimerTarget [1] = 0x100;
- APU.TimerValueWritten [1] = true;
- break;
- case 0xfc:
- if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0)
- APU.TimerTarget [2] = 0x100;
- APU.TimerValueWritten [2] = true;
- break;
- }
-}
-
uint8_t S9xGetAPUDSP()
{
uint8_t reg = IAPU.RAM [0xf2] & 0x7f;
@@ -594,10 +427,6 @@ uint8_t S9xGetAPUDSP()
switch (reg)
{
- case APU_KON:
- break;
- case APU_KOFF:
- break;
case APU_OUTX + 0x00:
case APU_OUTX + 0x10:
case APU_OUTX + 0x20:
@@ -606,11 +435,10 @@ uint8_t S9xGetAPUDSP()
case APU_OUTX + 0x50:
case APU_OUTX + 0x60:
case APU_OUTX + 0x70:
- if (SoundData.channels [reg >> 4].state == SOUND_SILENT)
+ if(SoundData.channels [reg >> 4].state == SOUND_SILENT)
return (0);
return ((SoundData.channels [reg >> 4].sample >> 8) |
(SoundData.channels [reg >> 4].sample & 0xff));
-
case APU_ENVX + 0x00:
case APU_ENVX + 0x10:
case APU_ENVX + 0x20:
@@ -620,9 +448,6 @@ uint8_t S9xGetAPUDSP()
case APU_ENVX + 0x60:
case APU_ENVX + 0x70:
return 0;
-
- case APU_ENDX:
- break;
default:
break;
}