aboutsummaryrefslogtreecommitdiff
path: root/source
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
parent47d3fc8ce090ec6ca06ff4e27dcf7db09588dae0 (diff)
downloadsnesemu-d8b66ac6d0524b3538ad595825651b28329f9033.tar.gz
snesemu-d8b66ac6d0524b3538ad595825651b28329f9033.tar.bz2
snesemu-d8b66ac6d0524b3538ad595825651b28329f9033.zip
Sound improvements - some by me, most from snes9x2002 and snes9x 1.51.
Diffstat (limited to 'source')
-rw-r--r--source/apu.c299
-rw-r--r--source/apu.h5
-rw-r--r--source/apumem.h40
-rw-r--r--source/dma.c7
-rw-r--r--source/fxinst.h3
-rw-r--r--source/globals.c1
-rw-r--r--source/soundux.c645
-rw-r--r--source/soundux.h29
-rw-r--r--source/spc700.c338
9 files changed, 500 insertions, 867 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;
}
diff --git a/source/apu.h b/source/apu.h
index 3f88346..6b40363 100644
--- a/source/apu.h
+++ b/source/apu.h
@@ -70,12 +70,11 @@ int S9xAPUOPrint(char* buffer, uint16_t Address);
void S9xSetAPUControl(uint8_t byte);
void S9xSetAPUDSP(uint8_t byte);
uint8_t S9xGetAPUDSP();
-void S9xSetAPUTimer(uint16_t Address, uint8_t byte);
bool S9xInitSound();
void S9xOpenCloseSoundTracingFile(bool);
void S9xPrintAPUState();
-extern uint16_t S9xAPUCycles [256]; // Scaled cycle lengths
-extern uint16_t S9xAPUCycleLengths [256]; // Raw data.
+extern uint16_t S9xAPUCycles [256]; // Scaled cycle lengths
+extern uint16_t S9xAPUCycleLengths [256]; // Raw data.
extern void (*S9xApuOpcodes [256])(void);
#define APU_VOL_LEFT 0x00
diff --git a/source/apumem.h b/source/apumem.h
index 74594d6..8a9f09a 100644
--- a/source/apumem.h
+++ b/source/apumem.h
@@ -67,32 +67,24 @@ INLINE uint8_t S9xAPUGetByte(uint32_t Address)
{
Address &= 0xffff;
- if (Address <= 0xff && Address >= 0xf0)
- {
- if (Address >= 0xf4 && Address <= 0xf7)
- {
-#ifdef SPC700_SHUTDOWN
- IAPU.WaitAddress2 = IAPU.WaitAddress1;
- IAPU.WaitAddress1 = IAPU.PC;
-#endif
- return (IAPU.RAM [Address]);
- }
- else if (Address == 0xf3)
- return (S9xGetAPUDSP());
- if (Address >= 0xfd)
- {
+ if (Address == 0xf3)
+ return S9xGetAPUDSP();
+
+ bool zero = (Address >= 0xfd && Address <= 0xff);
+ uint8_t t = IAPU.RAM [Address];
+
#ifdef SPC700_SHUTDOWN
- IAPU.WaitAddress2 = IAPU.WaitAddress1;
- IAPU.WaitAddress1 = IAPU.PC;
-#endif
- uint8_t t = IAPU.RAM [Address];
- IAPU.RAM [Address] = 0;
- return (t);
- }
- return (IAPU.RAM [Address]);
+ if (zero || (Address >= 0xf4 && Address <= 0xf7))
+ {
+ IAPU.WaitAddress2 = IAPU.WaitAddress1;
+ IAPU.WaitAddress1 = IAPU.PC;
}
- else
- return (IAPU.RAM [Address]);
+#endif
+
+ if(zero)
+ IAPU.RAM [Address] = 0;
+
+ return t;
}
INLINE void S9xAPUSetByte(uint8_t byte, uint32_t Address)
diff --git a/source/dma.c b/source/dma.c
index fc1356b..f404d4f 100644
--- a/source/dma.c
+++ b/source/dma.c
@@ -31,13 +31,6 @@ extern uint8_t* HDMABasePointers [8];
uint32_t HDMARawPointers[8]; // Cart address space pointer
#endif
-#if defined(__linux__) || defined(__WIN32__)
-static int S9xCompareSDD1IndexEntries(const void* p1, const void* p2)
-{
- return (*(uint32_t*) p1 - * (uint32_t*) p2);
-}
-#endif
-
/**********************************************************************************************/
/* S9xDoDMA() */
/* This function preforms the general dma transfer */
diff --git a/source/fxinst.h b/source/fxinst.h
index 7cb0d2e..f7450a9 100644
--- a/source/fxinst.h
+++ b/source/fxinst.h
@@ -280,9 +280,6 @@ struct FxRegs_s
/* Update pipe from ROM */
#define FETCHPIPE { PIPE = PRGBANK(R15); }
-/* ABS */
-#define ABS(x) ((x)<0?-(x):(x))
-
/* Access source register */
#define SREG (*GSU.pvSreg)
diff --git a/source/globals.c b/source/globals.c
index 83adf78..e65d1b5 100644
--- a/source/globals.c
+++ b/source/globals.c
@@ -85,7 +85,6 @@ SCheatData Cheat;
SoundStatus so;
int32_t Echo [24000];
-int32_t DummyEchoBuffer [SOUND_BUFFER_SIZE];
int32_t MixBuffer [SOUND_BUFFER_SIZE];
int32_t EchoBuffer [SOUND_BUFFER_SIZE];
int32_t FilterTaps [8];
diff --git a/source/soundux.c b/source/soundux.c
index 280c9f9..9e71bae 100644
--- a/source/soundux.c
+++ b/source/soundux.c
@@ -6,21 +6,19 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
-#include <fcntl.h>
#define CLIP16(v) \
- if ((v) < -32768) \
+if ((v) < -32768) \
(v) = -32768; \
- else \
- if ((v) > 32767) \
-(v) = 32767
+else \
+if ((v) > 32767) \
+ (v) = 32767
#define CLIP8(v) \
- if ((v) < -128) \
+if ((v) < -128) \
(v) = -128; \
- else \
- if ((v) > 127) \
-(v) = 127
+else if ((v) > 127) \
+ (v) = 127
#include "snes9x.h"
#include "soundux.h"
@@ -29,7 +27,6 @@
#include "cpuexec.h"
extern int32_t Echo [24000];
-extern int32_t DummyEchoBuffer [SOUND_BUFFER_SIZE];
extern int32_t MixBuffer [SOUND_BUFFER_SIZE];
extern int32_t EchoBuffer [SOUND_BUFFER_SIZE];
extern int32_t FilterTaps [8];
@@ -40,6 +37,42 @@ extern int32_t Loop [16];
extern long FilterValues[4][2];
extern int32_t NoiseFreq [32];
+uint32_t AttackRate [16] =
+{
+ 4100, 2600, 1500, 1000, 640, 380, 260, 160,
+ 96, 64, 40, 24, 16, 10, 6, 1
+};
+
+uint32_t DecayRate [8] =
+{
+ 1200, 740, 440, 290, 180, 110, 74, 37
+};
+
+uint32_t DecreaseRateExp [32] =
+{
+ 0xFFFFFFFF, 38000, 28000, 24000, 19000, 14000, 12000, 9400,
+ 7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500,
+ 1200, 880, 740, 590, 440, 370, 290, 220,
+ 180, 150, 110, 92, 74, 55, 37, 18
+};
+
+uint32_t IncreaseRate [32] =
+{
+ 0xFFFFFFFF, 4100, 3100, 2600, 2000, 1500, 1300, 1000,
+ 770, 640, 510, 380, 320, 260, 190, 160,
+ 130, 96, 80, 64, 48, 40, 32, 24,
+ 20, 16, 12, 10, 8, 6, 4, 2
+};
+
+#define SustainRate DecreaseRateExp
+
+// precalculated env rates for S9xSetEnvRate
+uint32_t AttackERate [16][10];
+uint32_t DecayERate [8][10];
+uint32_t SustainERate [32][10];
+uint32_t IncreaseERate [32][10];
+uint32_t DecreaseERateExp[32][10];
+uint32_t KeyOffERate [10];
static int32_t noise_gen;
@@ -51,7 +84,6 @@ static int32_t noise_gen;
#define ENVX_SHIFT 24
void DecodeBlockAsm(int8_t*, int16_t*, int32_t*, int32_t*);
-void DecodeBlockAsm2(int8_t*, int16_t*, int32_t*, int32_t*);
// F is channel's current frequency and M is the 16-bit modulation waveform
// from the previous channel multiplied by the current envelope volume level.
@@ -60,17 +92,6 @@ void DecodeBlockAsm2(int8_t*, int16_t*, int32_t*, int32_t*);
#define LAST_SAMPLE 0xffffff
#define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE)
-void S9xSetEightBitConsoleSound(bool Enabled)
-{
- if (Settings.EightBitConsoleSound != Enabled)
- {
- Settings.EightBitConsoleSound = Enabled;
- int i;
- for (i = 0; i < 8; i++)
- SoundData.channels[i].needs_decode = true;
- }
-}
-
static inline uint8_t* S9xGetSampleAddress(int sample_number)
{
uint32_t addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xffff);
@@ -92,7 +113,7 @@ void S9xAPUSetEndX(int ch)
APU.DSP [APU_ENDX] |= 1 << ch;
}
-void S9xSetEnvRate(Channel* ch, uint32_t rate, int direction, int target)
+void S9xSetEnvRate(Channel* ch, uint32_t rate, int direction, int target, unsigned int mode)
{
ch->envx_target = target;
@@ -104,38 +125,39 @@ void S9xSetEnvRate(Channel* ch, uint32_t rate, int direction, int target)
else
ch->direction = direction;
- static int64_t steps [] =
- {
- // 0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238
- 0,
- (int64_t) FIXED_POINT * 1000 * 64,
- (int64_t) FIXED_POINT * 1000 * 619,
- (int64_t) FIXED_POINT * 1000 * 619,
- (int64_t) FIXED_POINT * 1000 * 128,
- (int64_t) FIXED_POINT * 1000 * 1,
- (int64_t) FIXED_POINT * 1000 * 64,
- (int64_t) FIXED_POINT * 1000 * 55,
- (int64_t) FIXED_POINT * 1000 * 64,
- (int64_t) FIXED_POINT * 1000 * 619
- };
-
if (rate == 0 || so.playback_rate == 0)
ch->erate = 0;
else
{
- ch->erate = (uint32_t)
- (steps [ch->state] / (rate * so.playback_rate));
+ switch (mode >> 28)
+ {
+ case 0: // Attack
+ ch->erate = AttackERate[ch->env_ind_attack][ch->state];
+ break;
+ case 1: // Decay
+ ch->erate = DecayERate[ch->env_ind_decay][ch->state];
+ break;
+ case 2: // Sustain
+ ch->erate = SustainERate[ch->env_ind_sustain][ch->state];
+ break;
+ case 3: // Increase
+ ch->erate = IncreaseERate[mode & 0x1f][ch->state];
+ break;
+ case 4: // DecreaseExp
+ ch->erate = DecreaseERateExp[mode & 0x1f][ch->state];
+ break;
+ case 5: // KeyOff
+ ch->erate = KeyOffERate[ch->state];
+ break;
+ }
}
}
-
-void S9xSetEnvelopeRate(int channel, uint32_t rate, int direction,
- int target)
+void S9xSetEnvelopeRate(int channel, uint32_t rate, int direction, int target, unsigned int mode)
{
- S9xSetEnvRate(&SoundData.channels [channel], rate, direction, target);
+ S9xSetEnvRate(&SoundData.channels [channel], rate, direction, target, mode);
}
-
void S9xSetSoundVolume(int channel, int16_t volume_left, int16_t volume_right)
{
Channel* ch = &SoundData.channels[channel];
@@ -180,7 +202,7 @@ void S9xSetEchoEnable(uint8_t byte)
if (byte & (1 << i))
SoundData.channels [i].echo_buf_ptr = EchoBuffer;
else
- SoundData.channels [i].echo_buf_ptr = DummyEchoBuffer;
+ SoundData.channels [i].echo_buf_ptr = NULL;
}
}
@@ -192,7 +214,7 @@ void S9xSetEchoFeedback(int feedback)
void S9xSetEchoDelay(int delay)
{
- SoundData.echo_buffer_size = (512 * delay * so.playback_rate) / 32000;
+ SoundData.echo_buffer_size = (512 * delay * so.playback_rate) >> 15;
SoundData.echo_buffer_size <<= 1;
if (SoundData.echo_buffer_size)
SoundData.echo_ptr %= SoundData.echo_buffer_size;
@@ -209,7 +231,7 @@ void S9xSetEchoWriteEnable(uint8_t byte)
void S9xSetFrequencyModulationEnable(uint8_t byte)
{
- SoundData.pitch_mod = byte & ~1;
+ SoundData.pitch_mod = byte & 0xFE;
}
void S9xSetSoundKeyOff(int channel)
@@ -220,7 +242,7 @@ void S9xSetSoundKeyOff(int channel)
{
ch->state = SOUND_RELEASE;
ch->mode = MODE_RELEASE;
- S9xSetEnvRate(ch, 8, -1, 0);
+ S9xSetEnvRate(ch, 8, -1, 0, 5 << 28);
}
}
@@ -247,10 +269,8 @@ void S9xFixSoundAfterSnapshotLoad()
SoundData.channels [i].envxx = SoundData.channels [i].envx << ENVX_SHIFT;
SoundData.channels [i].next_sample = 0;
SoundData.channels [i].interpolate = 0;
- SoundData.channels [i].previous [0] = (int32_t)
- SoundData.channels [i].previous16 [0];
- SoundData.channels [i].previous [1] = (int32_t)
- SoundData.channels [i].previous16 [1];
+ SoundData.channels [i].previous [0] = (int32_t) SoundData.channels [i].previous16 [0];
+ SoundData.channels [i].previous [1] = (int32_t) SoundData.channels [i].previous16 [1];
}
IAPU.Scanline = 0;
}
@@ -264,10 +284,21 @@ void S9xSetFilterCoefficient(int tap, int value)
FilterTapDefinitionBitfield |= 1 << (tap & 7);
}
-void S9xSetSoundADSR(int channel, int attack_rate, int decay_rate,
- int sustain_rate, int sustain_level, int release_rate)
+void S9xSetSoundADSR(int channel, int attack_ind, int decay_ind, int sustain_ind, int sustain_level, int release_rate)
{
+ int attack_rate = AttackRate [attack_ind];
+ int decay_rate = DecayRate [decay_ind];
+ int sustain_rate = SustainRate [sustain_ind];
+
+ // Hack for ROMs that use a very short attack rate, key on a
+ // channel, then switch to decay mode. e.g. Final Fantasy II.
+ if(attack_rate == 1)
+ attack_rate = 0;
+
Channel* ch = &SoundData.channels[channel];
+ ch->env_ind_attack = attack_ind;
+ ch->env_ind_decay = decay_ind;
+ ch->env_ind_sustain = sustain_ind;
ch->attack_rate = attack_rate;
ch->decay_rate = decay_rate;
ch->sustain_rate = sustain_rate;
@@ -277,15 +308,14 @@ void S9xSetSoundADSR(int channel, int attack_rate, int decay_rate,
switch (SoundData.channels[channel].state)
{
case SOUND_ATTACK:
- S9xSetEnvRate(ch, attack_rate, 1, 127);
+ S9xSetEnvRate(ch, attack_rate, 1, 127, 0);
break;
-
case SOUND_DECAY:
S9xSetEnvRate(ch, decay_rate, -1,
- (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3);
+ (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3, 1 << 28);
break;
case SOUND_SUSTAIN:
- S9xSetEnvRate(ch, sustain_rate, -1, 0);
+ S9xSetEnvRate(ch, sustain_rate, -1, 0, 2 << 28);
break;
}
}
@@ -320,14 +350,13 @@ int S9xGetEnvelopeHeight(int channel)
return (0);
}
-void S9xSetSoundFrequency(int channel, int hertz)
+void S9xSetSoundFrequency(int channel, int hertz) // hertz [0~64K<<1]
{
if (so.playback_rate)
{
if (SoundData.channels[channel].type == SOUND_NOISE)
hertz = NoiseFreq [APU.DSP [APU_FLG] & 0x1f];
- SoundData.channels[channel].frequency = (int)
- (((int64_t) hertz * FIXED_POINT) / so.playback_rate);
+ SoundData.channels[channel].frequency = (hertz * so.freqbase) >> 11;
}
}
@@ -345,13 +374,11 @@ void S9xSetSoundType(int channel, int type_of_sound)
void DecodeBlock(Channel* ch)
{
int32_t out;
- unsigned char filter;
+ uint8_t filter;
unsigned char shift;
signed char sample1, sample2;
- unsigned char i;
- bool invalid_header;
- if (ch->block_pointer > 0x10000 - 9)
+ if (ch->block_pointer >= 0x10000 - 9)
{
ch->last_block = true;
ch->loop = false;
@@ -359,274 +386,88 @@ void DecodeBlock(Channel* ch)
return;
}
- if (Settings.EightBitConsoleSound)
- {
- signed char* compressed = (signed char*) &IAPU.RAM [ch->block_pointer];
-
- filter = *compressed;
- if ((ch->last_block = filter & 1))
- ch->loop = (filter & 2) != 0;
-
- int16_t interim[16];
- uint8_t interim_byte = 0;
-
- compressed++;
+ int8_t* compressed = (int8_t*) &IAPU.RAM [ch->block_pointer];
- // Seperate out the header parts used for decoding
+ filter = *compressed;
+ if ((ch->last_block = filter & 1))
+ ch->loop = (filter & 2) != 0;
- shift = filter >> 4;
+ int16_t* raw = ch->block = ch->decoded;
+ unsigned int i;
- // Header validity check: if range(shift) is over 12, ignore
- // all bits of the data for that block except for the sign bit of each
- invalid_header = (shift >= 0xD);
+ compressed++;
- filter = filter & 0x0c;
-
- int32_t prev0 = ch->previous [0];
- int32_t prev1 = ch->previous [1];
-
- int16_t amplitude = 0;
+ int32_t prev0 = ch->previous [0];
+ int32_t prev1 = ch->previous [1];
+ shift = filter >> 4;
+ switch ((filter >> 2) & 3)
+ {
+ case 0:
for (i = 8; i != 0; i--)
{
sample1 = *compressed++;
sample2 = sample1 << 4;
- //Sample 2 = Bottom Nibble, Sign Extended.
sample2 >>= 4;
- //Sample 1 = Top Nibble, shifted down and Sign Extended.
sample1 >>= 4;
- if (invalid_header)
- {
- sample1 >>= 3;
- sample2 >>= 3;
- }
-
- int nybblesmp;
- for (nybblesmp = 0; nybblesmp < 2; nybblesmp++)
- {
- out = (((nybblesmp) ? sample2 : sample1) << shift);
- out >>= 1;
-
- switch (filter)
- {
- case 0x00:
- // Method0 - [Smp]
- break;
-
- case 0x04:
- // Method1 - [Delta]+[Smp-1](15/16)
- out += (prev0 >> 1) + ((-prev0) >> 5);
- break;
-
- case 0x08:
- // Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16)
- out += (prev0) + ((-(prev0 + (prev0 >> 1))) >> 5) - (prev1 >> 1) + (prev1 >> 5);
- break;
-
- default:
- // Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16)
- out += (prev0) + ((-(prev0 + (prev0 << 2) + (prev0 << 3))) >> 7) -
- (prev1 >> 1) + ((prev1 + (prev1 >> 1)) >> 4);
- break;
-
- }
- CLIP16(out);
- int16_t result = (int16_t)(out << 1);
- if (abs(result) > amplitude)
- amplitude = abs(result);
- interim[interim_byte++] = out;
- prev1 = (int16_t)prev0;
- prev0 = (int16_t)(out << 1);
- }
- }
- ch->previous [0] = prev0;
- ch->previous [1] = prev1;
-
- int32_t total_deviation_from_previous = 0;
- for (i = 1; i < 16; i++)
- total_deviation_from_previous += abs(interim[i] - interim[i - 1]);
- if (total_deviation_from_previous >= (int32_t) amplitude * 4)
- {
- /* Looks like noise. Generate noise. */
- for (i = 0; i < 16; i++)
- {
- int feedback = (noise_gen << 13) ^ (noise_gen << 14);
- noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1);
- ch->decoded[i] = (noise_gen << 17) >> 17;
- }
- }
- else if (interim[0] < interim[1] && interim[1] < interim[2]
- && interim[2] < interim[3]
- && interim[4] > interim[5] && interim[5] > interim[6]
- && interim[6] > interim[7] && interim[7] > interim[8]
- && interim[8] > interim[9] && interim[9] > interim[10]
- && interim[10] > interim[11]
- && interim[12] < interim[13] && interim[13] < interim[14]
- && interim[14] < interim[15])
- {
- /* Looks like a sine or triangle wave. Make it a
- * triangle wave with an amplitude equivalent to that
- * of the highest amplitude sample of the block. */
- ch->decoded[0] = ch->decoded[8] = 0;
- ch->decoded[1] = ch->decoded[7] = amplitude / 4;
- ch->decoded[2] = ch->decoded[6] = amplitude / 2;
- ch->decoded[3] = ch->decoded[5] = amplitude * 3 / 4;
- ch->decoded[4] = amplitude;
- ch->decoded[9] = ch->decoded[15] = -(amplitude / 4);
- ch->decoded[10] = ch->decoded[14] = -(amplitude / 2);
- ch->decoded[11] = ch->decoded[13] = -(amplitude * 3 / 4);
- ch->decoded[12] = -amplitude;
- }
- else if (interim[0] > interim[1] && interim[1] > interim[2]
- && interim[2] > interim[3]
- && interim[4] < interim[5] && interim[5] < interim[6]
- && interim[6] < interim[7] && interim[7] < interim[8]
- && interim[8] < interim[9] && interim[9] < interim[10]
- && interim[10] < interim[11]
- && interim[12] > interim[13] && interim[13] > interim[14]
- && interim[14] > interim[15])
- {
- /* Inverted triangle wave. */
- ch->decoded[0] = ch->decoded[8] = 0;
- ch->decoded[1] = ch->decoded[7] = -(amplitude / 4);
- ch->decoded[2] = ch->decoded[6] = -(amplitude / 2);
- ch->decoded[3] = ch->decoded[5] = -(amplitude * 3 / 4);
- ch->decoded[4] = -amplitude;
- ch->decoded[9] = ch->decoded[15] = amplitude / 4;
- ch->decoded[10] = ch->decoded[14] = amplitude / 2;
- ch->decoded[11] = ch->decoded[13] = amplitude * 3 / 4;
- ch->decoded[12] = amplitude;
- }
- else if (interim[0] < interim[1] && interim[1] < interim[2]
- && interim[2] < interim[3] && interim[3] < interim[4]
- && interim[4] < interim[5] && interim[5] < interim[6]
- && interim[6] < interim[7]
- && interim[8] > interim[9] && interim[9] > interim[10]
- && interim[10] > interim[11] && interim[11] > interim[12]
- && interim[12] > interim[13] && interim[13] > interim[14]
- && interim[14] > interim[15])
- {
- /* Looks like a V wave. Make it a half-triangle wave
- * with an amplitude equivalent to that
- * of the highest amplitude sample of the block. */
- ch->decoded[0] = 0;
- ch->decoded[1] = ch->decoded[15] = amplitude / 8;
- ch->decoded[2] = ch->decoded[14] = amplitude / 4;
- ch->decoded[3] = ch->decoded[13] = amplitude * 3 / 8;
- ch->decoded[4] = ch->decoded[12] = amplitude / 2;
- ch->decoded[5] = ch->decoded[11] = amplitude * 5 / 8;
- ch->decoded[6] = ch->decoded[10] = amplitude * 3 / 4;
- ch->decoded[7] = ch->decoded[9] = amplitude * 7 / 8;
- ch->decoded[8] = amplitude;
+ *raw++ = ((int32_t) sample1 << shift);
+ *raw++ = ((int32_t) sample2 << shift);
}
- else if (interim[0] > interim[1] && interim[1] > interim[2]
- && interim[2] > interim[3] && interim[3] > interim[4]
- && interim[4] > interim[5] && interim[5] > interim[6]
- && interim[6] > interim[7]
- && interim[8] < interim[9] && interim[9] < interim[10]
- && interim[10] < interim[11] && interim[11] < interim[12]
- && interim[12] < interim[13] && interim[13] < interim[14]
- && interim[14] < interim[15])
+ prev1 = *(raw - 2);
+ prev0 = *(raw - 1);
+ break;
+ case 1:
+ for (i = 8; i != 0; i--)
{
- /* Inverted V wave. */
- ch->decoded[0] = 0;
- ch->decoded[1] = ch->decoded[15] = -(amplitude / 8);
- ch->decoded[2] = ch->decoded[14] = -(amplitude / 4);
- ch->decoded[3] = ch->decoded[13] = -(amplitude * 3 / 8);
- ch->decoded[4] = ch->decoded[12] = -(amplitude / 2);
- ch->decoded[5] = ch->decoded[11] = -(amplitude * 5 / 8);
- ch->decoded[6] = ch->decoded[10] = -(amplitude * 3 / 4);
- ch->decoded[7] = ch->decoded[9] = -(amplitude * 7 / 8);
- ch->decoded[8] = -amplitude;
+ sample1 = *compressed++;
+ sample2 = sample1 << 4;
+ sample2 >>= 4;
+ sample1 >>= 4;
+ prev0 = (int16_t) prev0;
+ *raw++ = prev1 = ((int32_t) sample1 << shift) + prev0 - (prev0 >> 4);
+ prev1 = (int16_t) prev1;
+ *raw++ = prev0 = ((int32_t) sample2 << shift) + prev1 - (prev1 >> 4);
}
- else
+ break;
+ case 2:
+ for (i = 8; i != 0; i--)
{
- // Make it a square wave with an amplitude equivalent to that
- // of the highest amplitude sample of the block.
- // But actually put half of the amplitude, because
- // square waves are just loud.
- for (i = 0; i < 8; i++)
- ch->decoded[i] = amplitude / 2;
- for (i = 8; i < 16; i++)
- ch->decoded[i] = -(amplitude / 2);
+ sample1 = *compressed++;
+ sample2 = sample1 << 4;
+ sample2 >>= 4;
+ sample1 >>= 4;
+ out = (sample1 << shift) - prev1 + (prev1 >> 4);
+ prev1 = (int16_t) prev0;
+ prev0 &= ~3;
+ *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - (prev0 >> 4);
+ out = (sample2 << shift) - prev1 + (prev1 >> 4);
+ prev1 = (int16_t) prev0;
+ prev0 &= ~3;
+ *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - (prev0 >> 4);
}
- }
- else
- {
- signed char* compressed = (signed char*) &IAPU.RAM [ch->block_pointer];
-
- filter = *compressed;
- if ((ch->last_block = filter & 1))
- ch->loop = (filter & 2) != 0;
-
- compressed++;
- int16_t* raw = ch->block = ch->decoded;
-
- // Seperate out the header parts used for decoding
-
- shift = filter >> 4;
-
- // Header validity check: if range(shift) is over 12, ignore
- // all bits of the data for that block except for the sign bit of each
- invalid_header = (shift >= 0xD);
-
- filter = filter & 0x0c;
-
- int32_t prev0 = ch->previous [0];
- int32_t prev1 = ch->previous [1];
-
+ break;
+ case 3:
for (i = 8; i != 0; i--)
{
sample1 = *compressed++;
sample2 = sample1 << 4;
- //Sample 2 = Bottom Nibble, Sign Extended.
sample2 >>= 4;
- //Sample 1 = Top Nibble, shifted down and Sign Extended.
sample1 >>= 4;
- if (invalid_header)
- {
- sample1 >>= 3;
- sample2 >>= 3;
- }
-
- int nybblesmp;
- for (nybblesmp = 0; nybblesmp < 2; nybblesmp++)
- {
- out = (((nybblesmp) ? sample2 : sample1) << shift);
- out >>= 1;
-
- switch (filter)
- {
- case 0x00:
- // Method0 - [Smp]
- break;
-
- case 0x04:
- // Method1 - [Delta]+[Smp-1](15/16)
- out += (prev0 >> 1) + ((-prev0) >> 5);
- break;
-
- case 0x08:
- // Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16)
- out += (prev0) + ((-(prev0 + (prev0 >> 1))) >> 5) - (prev1 >> 1) + (prev1 >> 5);
- break;
-
- default:
- // Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16)
- out += (prev0) + ((-(prev0 + (prev0 << 2) + (prev0 << 3))) >> 7) -
- (prev1 >> 1) + ((prev1 + (prev1 >> 1)) >> 4);
- break;
-
- }
- CLIP16(out);
- *raw++ = (int16_t)(out << 1);
- prev1 = (int16_t)prev0;
- prev0 = (int16_t)(out << 1);
- }
+ out = (sample1 << shift);
+ out = out - prev1 + (prev1 >> 3) + (prev1 >> 4);
+ prev1 = (int16_t) prev0;
+ prev0 &= ~3;
+ *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - (prev0 >> 4) - (prev1 >> 6);
+ out = (sample2 << shift);
+ out = out - prev1 + (prev1 >> 3) + (prev1 >> 4);
+ prev1 = (int16_t) prev0;
+ prev0 &= ~3;
+ *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - (prev0 >> 4) - (prev1 >> 6);
}
- ch->previous [0] = prev0;
- ch->previous [1] = prev1;
+ break;
}
+ ch->previous [0] = prev0;
+ ch->previous [1] = prev1;
ch->block_pointer += 9;
}
@@ -641,7 +482,7 @@ static inline void MixStereo(int sample_count)
{
Channel* ch = &SoundData.channels[J];
- if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J)))
+ if (ch->state == SOUND_SILENT)
continue;
int32_t VL, VR;
@@ -698,15 +539,13 @@ static inline void MixStereo(int sample_count)
if (ch->sustain_level != 8)
{
S9xSetEnvRate(ch, ch->decay_rate, -1,
- (MAX_ENVELOPE_HEIGHT * ch->sustain_level)
- >> 3);
+ (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1 << 28);
break;
}
ch->state = SOUND_SUSTAIN;
- S9xSetEnvRate(ch, ch->sustain_rate, -1, 0);
+ S9xSetEnvRate(ch, ch->sustain_rate, -1, 0, 2 << 28);
}
break;
-
case SOUND_DECAY:
while (ch->env_error >= FIXED_POINT)
{
@@ -722,10 +561,9 @@ static inline void MixStereo(int sample_count)
goto stereo_exit;
}
ch->state = SOUND_SUSTAIN;
- S9xSetEnvRate(ch, ch->sustain_rate, -1, 0);
+ S9xSetEnvRate(ch, ch->sustain_rate, -1, 0, 2 << 28);
}
break;
-
case SOUND_SUSTAIN:
while (ch->env_error >= FIXED_POINT)
{
@@ -739,7 +577,6 @@ static inline void MixStereo(int sample_count)
goto stereo_exit;
}
break;
-
case SOUND_RELEASE:
while (ch->env_error >= FIXED_POINT)
{
@@ -753,7 +590,6 @@ static inline void MixStereo(int sample_count)
goto stereo_exit;
}
break;
-
case SOUND_INCREASE_LINEAR:
ch->env_error &= FIXED_POINT_REMAINDER;
ch->envx += step << 1;
@@ -765,10 +601,9 @@ static inline void MixStereo(int sample_count)
ch->envxx = 127 << ENVX_SHIFT;
ch->state = SOUND_GAIN;
ch->mode = MODE_GAIN;
- S9xSetEnvRate(ch, 0, -1, 0);
+ S9xSetEnvRate(ch, 0, -1, 0, 0);
}
break;
-
case SOUND_INCREASE_BENT_LINE:
if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4)
{
@@ -792,10 +627,9 @@ static inline void MixStereo(int sample_count)
ch->envxx = 127 << ENVX_SHIFT;
ch->state = SOUND_GAIN;
ch->mode = MODE_GAIN;
- S9xSetEnvRate(ch, 0, -1, 0);
+ S9xSetEnvRate(ch, 0, -1, 0, 0);
}
break;
-
case SOUND_DECREASE_LINEAR:
ch->env_error &= FIXED_POINT_REMAINDER;
ch->envx -= step << 1;
@@ -806,7 +640,6 @@ static inline void MixStereo(int sample_count)
goto stereo_exit;
}
break;
-
case SOUND_DECREASE_EXPONENTIAL:
while (ch->env_error >= FIXED_POINT)
{
@@ -820,9 +653,8 @@ static inline void MixStereo(int sample_count)
goto stereo_exit;
}
break;
-
case SOUND_GAIN:
- S9xSetEnvRate(ch, 0, -1, 0);
+ S9xSetEnvRate(ch, 0, -1, 0, 0);
break;
}
ch-> left_vol_level = (ch->envx * ch->volume_left) / 128;
@@ -916,6 +748,10 @@ static inline void MixStereo(int sample_count)
MixBuffer [I ] += VL;
MixBuffer [I + 1] += VR;
+
+ if (!ch->echo_buf_ptr)
+ continue;
+
ch->echo_buf_ptr [I ] += VL;
ch->echo_buf_ptr [I + 1] += VR;
}
@@ -924,11 +760,17 @@ stereo_exit:
}
}
-void S9xMixSamples(uint8_t* buffer, int sample_count)
+void S9xMixSamples(uint16_t* buffer, int sample_count)
{
int J;
int I;
+ if (so.mute_sound)
+ {
+ memset(buffer, 0, sample_count * sizeof(buffer [0]));
+ return;
+ }
+
if (SoundData.echo_enable)
memset(EchoBuffer, 0, sample_count * sizeof(EchoBuffer [0]));
memset(MixBuffer, 0, sample_count * sizeof(MixBuffer [0]));
@@ -944,19 +786,14 @@ void S9xMixSamples(uint8_t* buffer, int sample_count)
for (J = 0; J < sample_count; J++)
{
int E = Echo [SoundData.echo_ptr];
+ Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer [J];
- Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 +
- EchoBuffer [J];
-
- if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size)
+ if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
SoundData.echo_ptr = 0;
- I = (MixBuffer [J] *
- SoundData.master_volume [J & 1] +
- E * SoundData.echo_volume [J & 1]) / VOL_DIV16;
-
+ I = (MixBuffer[J] * SoundData.master_volume [J & 1] + E * SoundData.echo_volume [J & 1]) / VOL_DIV16;
CLIP16(I);
- ((int16_t*) buffer)[J] = I;
+ buffer[J] = I;
}
}
else
@@ -964,39 +801,26 @@ void S9xMixSamples(uint8_t* buffer, int sample_count)
// ... with filter defined.
for (J = 0; J < sample_count; J++)
{
- int E = Echo [SoundData.echo_ptr];
-
- Loop [(Z - 0) & 15] = E;
- E = E * FilterTaps [0];
- if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] *
- FilterTaps [1];
- if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] *
- FilterTaps [2];
- if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] *
- FilterTaps [3];
- if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] *
- FilterTaps [4];
- if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] *
- FilterTaps [5];
- if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] *
- FilterTaps [6];
- if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] *
- FilterTaps [7];
+ Loop [(Z - 0) & 15] = Echo [SoundData.echo_ptr];
+ int E = Loop [(Z - 0) & 15] * FilterTaps [0];
+ if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] * FilterTaps [1];
+ if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] * FilterTaps [2];
+ if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] * FilterTaps [3];
+ if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] * FilterTaps [4];
+ if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] * FilterTaps [5];
+ if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] * FilterTaps [6];
+ if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] * FilterTaps [7];
E /= 128;
Z++;
- Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 +
- EchoBuffer [J];
+ Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J];
- if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size)
+ if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
SoundData.echo_ptr = 0;
- I = (MixBuffer [J] *
- SoundData.master_volume [J & 1] +
- E * SoundData.echo_volume [J & 1]) / VOL_DIV16;
-
+ I = (MixBuffer[J] * SoundData.master_volume [J & 1] + E * SoundData.echo_volume [J & 1]) / VOL_DIV16;
CLIP16(I);
- ((int16_t*) buffer)[J] = I;
+ buffer[J] = I;
}
}
}
@@ -1005,14 +829,11 @@ void S9xMixSamples(uint8_t* buffer, int sample_count)
// 16-bit mono or stereo sound, no echo
for (J = 0; J < sample_count; J++)
{
- I = (MixBuffer [J] *
- SoundData.master_volume [J & 1]) / VOL_DIV16;
-
+ I = (MixBuffer[J] * SoundData.master_volume [J & 1]) / VOL_DIV16;
CLIP16(I);
- ((int16_t*) buffer)[J] = I;
+ buffer[J] = I;
}
}
-
}
void S9xResetSound(bool full)
@@ -1041,6 +862,10 @@ void S9xResetSound(bool full)
SoundData.channels[i].sustain_rate = 0;
SoundData.channels[i].release_rate = 0;
SoundData.channels[i].sustain_level = 0;
+ // notaz
+ SoundData.channels[i].env_ind_attack = 0;
+ SoundData.channels[i].env_ind_decay = 0;
+ SoundData.channels[i].env_ind_sustain = 0;
SoundData.echo_ptr = 0;
SoundData.echo_feedback = 0;
SoundData.echo_buffer_size = 1;
@@ -1055,10 +880,6 @@ void S9xResetSound(bool full)
FilterTaps [7] = 0;
FilterTapDefinitionBitfield = 0;
noise_gen = 1;
- so.sound_switch = 255;
- so.samples_mixed_so_far = 0;
- so.play_position = 0;
- so.err_counter = 0;
if (full)
{
@@ -1066,9 +887,6 @@ void S9xResetSound(bool full)
SoundData.echo_write_enabled = 0;
SoundData.echo_channel_enable = 0;
SoundData.pitch_mod = 0;
- SoundData.dummy[0] = 0;
- SoundData.dummy[1] = 0;
- SoundData.dummy[2] = 0;
SoundData.master_volume[0] = 0;
SoundData.master_volume[1] = 0;
SoundData.echo_volume[0] = 0;
@@ -1077,18 +895,46 @@ void S9xResetSound(bool full)
}
SoundData.master_volume [0] = SoundData.master_volume [1] = 127;
- if (so.playback_rate)
- so.err_rate = (uint32_t)(FIXED_POINT * SNES_SCANLINE_TIME /
- (1.0 / so.playback_rate));
- else
- so.err_rate = 0;
+ so.mute_sound = true;
}
void S9xSetPlaybackRate(uint32_t playback_rate)
{
so.playback_rate = playback_rate;
- so.err_rate = (uint32_t)(SNES_SCANLINE_TIME * FIXED_POINT / (1.0 /
- (double) so.playback_rate));
+
+ if (playback_rate)
+ {
+ // notaz: calculate a value (let's call it freqbase) to simplify channel freq calculations later.
+ so.freqbase = (FIXED_POINT << 11) / (playback_rate * 33 / 32);
+ // now precalculate env rates for S9xSetEnvRate
+ static int steps [] =
+ {
+ 0, 64, 619, 619, 128, 1, 64, 55, 64, 619
+ };
+
+ int i, u;
+
+ for (u = 0 ; u < 10 ; u++)
+ {
+ int64_t fp1000su = ((int64_t) FIXED_POINT * 1000 * steps[u]);
+
+ for (i = 0 ; i < 16 ; i++)
+ AttackERate[i][u] = (uint32_t) (fp1000su / (AttackRate[i] * playback_rate));
+
+ for (i = 0 ; i < 8 ; i++)
+ DecayERate[i][u] = (uint32_t) (fp1000su / (DecayRate[i] * playback_rate));
+
+ for (i = 0 ; i < 32 ; i++)
+ {
+ SustainERate[i][u] = (uint32_t) (fp1000su / (SustainRate[i] * playback_rate));
+ IncreaseERate[i][u] = (uint32_t) (fp1000su / (IncreaseRate[i] * playback_rate));
+ DecreaseERateExp[i][u] = (uint32_t) (fp1000su / (DecreaseRateExp[i] / 2 * playback_rate));
+ }
+
+ KeyOffERate[u] = (uint32_t) (fp1000su / (8 * playback_rate));
+ }
+ }
+
S9xSetEchoDelay(APU.DSP [APU_EDL] & 0xf);
int i;
for (i = 0; i < 8; i++)
@@ -1097,13 +943,8 @@ void S9xSetPlaybackRate(uint32_t playback_rate)
bool S9xInitSound()
{
- so.sound_fd = -1;
- so.sound_switch = 255;
-
so.playback_rate = 0;
- so.buffer_size = 0;
- so.encoded = false;
-
+ S9xResetSound(true);
return (1);
}
@@ -1120,20 +961,9 @@ bool S9xSetSoundMode(int channel, int mode)
return (true);
}
break;
-
case MODE_DECREASE_LINEAR:
case MODE_DECREASE_EXPONENTIAL:
case MODE_GAIN:
- if (ch->mode != MODE_RELEASE)
- {
- ch->mode = mode;
- if (ch->state != SOUND_SILENT)
- ch->state = mode;
-
- return (true);
- }
- break;
-
case MODE_INCREASE_LINEAR:
case MODE_INCREASE_BENT_LINE:
if (ch->mode != MODE_RELEASE)
@@ -1141,11 +971,9 @@ bool S9xSetSoundMode(int channel, int mode)
ch->mode = mode;
if (ch->state != SOUND_SILENT)
ch->state = mode;
-
return (true);
}
break;
-
case MODE_ADSR:
if (ch->mode == MODE_NONE || ch->mode == MODE_ADSR)
{
@@ -1157,11 +985,6 @@ bool S9xSetSoundMode(int channel, int mode)
return (false);
}
-void S9xSetSoundControl(int sound_switch)
-{
- so.sound_switch = sound_switch;
-}
-
void S9xPlaySample(int channel)
{
Channel* ch = &SoundData.channels[channel];
@@ -1202,14 +1025,14 @@ void S9xPlaySample(int channel)
{
ch->state = SOUND_SUSTAIN;
ch->envx = (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3;
- S9xSetEnvRate(ch, ch->sustain_rate, -1, 0);
+ S9xSetEnvRate(ch, ch->sustain_rate, -1, 0, 2 << 28);
}
else
{
ch->state = SOUND_DECAY;
ch->envx = MAX_ENVELOPE_HEIGHT;
S9xSetEnvRate(ch, ch->decay_rate, -1,
- (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3);
+ (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1 << 28);
}
ch-> left_vol_level = (ch->envx * ch->volume_left) / 128;
ch->right_vol_level = (ch->envx * ch->volume_right) / 128;
@@ -1220,31 +1043,25 @@ void S9xPlaySample(int channel)
ch->envx = 0;
ch->left_vol_level = 0;
ch->right_vol_level = 0;
- S9xSetEnvRate(ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT);
+ S9xSetEnvRate(ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT, 0);
}
ch->envxx = ch->envx << ENVX_SHIFT;
break;
-
case MODE_GAIN:
ch->state = SOUND_GAIN;
break;
-
case MODE_INCREASE_LINEAR:
ch->state = SOUND_INCREASE_LINEAR;
break;
-
case MODE_INCREASE_BENT_LINE:
ch->state = SOUND_INCREASE_BENT_LINE;
break;
-
case MODE_DECREASE_LINEAR:
ch->state = SOUND_DECREASE_LINEAR;
break;
-
case MODE_DECREASE_EXPONENTIAL:
ch->state = SOUND_DECREASE_EXPONENTIAL;
break;
-
default:
break;
}
diff --git a/source/soundux.h b/source/soundux.h
index 411e334..e4cf3ad 100644
--- a/source/soundux.h
+++ b/source/soundux.h
@@ -24,23 +24,17 @@ enum { MODE_NONE = SOUND_SILENT, MODE_ADSR, MODE_RELEASE = SOUND_RELEASE,
#define SOUND_DECODE_LENGTH 16
#define NUM_CHANNELS 8
-#define SOUND_BUFFER_SIZE (1024 * 16)
+#define SOUND_BUFFER_SIZE (2 * 44100 / 50)
#define MAX_BUFFER_SIZE SOUND_BUFFER_SIZE
-#define SOUND_BUFFER_SIZE_MASK (SOUND_BUFFER_SIZE - 1)
#define SOUND_BUFS 4
typedef struct
{
- int sound_fd;
- int sound_switch;
int playback_rate;
int buffer_size;
- bool encoded;
- int32_t samples_mixed_so_far;
- int32_t play_position;
- uint32_t err_counter;
- uint32_t err_rate;
+ uint32_t freqbase; // notaz
+ bool mute_sound;
} SoundStatus;
SoundStatus so;
@@ -82,8 +76,12 @@ typedef struct
int16_t next_sample;
int32_t interpolate;
int32_t previous [2];
+ // notaz
+ uint8_t env_ind_attack;
+ uint8_t env_ind_decay;
+ uint8_t env_ind_sustain;
// Just incase they are needed in the future, for snapshot compatibility.
- uint32_t dummy [8];
+ uint8_t dummy [29];
} Channel;
typedef struct
@@ -105,18 +103,14 @@ typedef struct
SSoundData SoundData;
-void S9xSetEightBitConsoleSound(bool Enabled);
-
void S9xSetSoundVolume(int channel, int16_t volume_left, int16_t volume_right);
void S9xSetSoundFrequency(int channel, int hertz);
void S9xSetSoundHertz(int channel, int hertz);
void S9xSetSoundType(int channel, int type_of_sound);
void S9xSetMasterVolume(int16_t master_volume_left, int16_t master_volume_right);
void S9xSetEchoVolume(int16_t echo_volume_left, int16_t echo_volume_right);
-void S9xSetSoundControl(int sound_switch);
void S9xSetEnvelopeHeight(int channel, int height);
-void S9xSetSoundADSR(int channel, int attack, int decay, int sustain,
- int sustain_level, int release);
+void S9xSetSoundADSR(int channel, int attack, int decay, int sustain, int sustain_level, int release);
void S9xSetSoundKeyOff(int channel);
void S9xSetSoundDecayMode(int channel);
void S9xSetSoundAttachMode(int channel);
@@ -127,8 +121,7 @@ void S9xSetEchoDelay(int byte);
void S9xSetEchoWriteEnable(uint8_t byte);
void S9xSetFilterCoefficient(int tap, int value);
void S9xSetFrequencyModulationEnable(uint8_t byte);
-void S9xSetEnvelopeRate(int channel, uint32_t rate, int direction,
- int target);
+void S9xSetEnvelopeRate(int channel, uint32_t rate, int direction, int target, unsigned int mode);
bool S9xSetSoundMode(int channel, int mode);
void S9xResetSound(bool full);
void S9xFixSoundAfterSnapshotLoad();
@@ -137,7 +130,7 @@ void S9xPlaySample(int channel);
void S9xFixEnvelope(int channel, uint8_t gain, uint8_t adsr1, uint8_t adsr2);
void S9xStartSample(int channel);
-void S9xMixSamples(uint8_t* buffer, int sample_count);
+void S9xMixSamples(uint16_t* buffer, int sample_count);
bool S9xOpenSoundDevice(int, bool, int);
void S9xSetPlaybackRate(uint32_t rate);
#endif
diff --git a/source/spc700.c b/source/spc700.c
index c81b959..5e50cf3 100644
--- a/source/spc700.c
+++ b/source/spc700.c
@@ -23,6 +23,15 @@ void S9xAPUSetByte(uint8_t, uint32_t address);
#include "apumem.h"
#endif
+int8_t Int8 = 0;
+int16_t Int16 = 0;
+int32_t Int32 = 0;
+uint8_t W1;
+uint8_t W2;
+uint8_t Work8 = 0;
+uint16_t Work16 = 0;
+uint32_t Work32 = 0;
+
#define OP1 (*(IAPU.PC + 1))
#define OP2 (*(IAPU.PC + 2))
@@ -56,13 +65,12 @@ void S9xAPUSetByte(uint8_t, uint32_t address);
#define TCALL(n)\
{\
SPC700_PushW (IAPU.PC - IAPU.RAM + 1); \
- IAPU.PC = IAPU.RAM + (APU.ExtraRAM [((15 - n) << 1)] + \
- (APU.ExtraRAM [((15 - n) << 1) + 1] << 8)); \
+ IAPU.PC = IAPU.RAM + S9xAPUGetByte(0xffc0 + ((15 - n) << 1)) + \
+ (S9xAPUGetByte(0xffc1 + ((15 - n) << 1)) << 8); \
}
-// XXX: HalfCarry - BJ fixed?
#define SBC(a,b)\
-int16_t Int16 = (int16_t) (a) - (int16_t) (b) + (int16_t) (APUCheckCarry ()) - 1;\
+Int16 = (int16_t) (a) - (int16_t) (b) + (int16_t) (APUCheckCarry ()) - 1;\
IAPU._Carry = Int16 >= 0;\
if ((((a) ^ (b)) & 0x80) && (((a) ^ (uint8_t) Int16) & 0x80))\
APUSetOverflow ();\
@@ -74,10 +82,8 @@ if(((a) ^ (b) ^ (uint8_t) Int16) & 0x10)\
(a) = (uint8_t) Int16;\
APUSetZN8 ((uint8_t) Int16);
-// XXX: HalfCarry - BJ fixed?
-// XXX: HalfCarry used Int16 before; trying to fix it with Work16 [Neb]
#define ADC(a,b)\
-uint16_t Work16 = (a) + (b) + APUCheckCarry();\
+Work16 = (a) + (b) + APUCheckCarry();\
IAPU._Carry = Work16 >= 0x100; \
if (~((a) ^ (b)) & ((b) ^ (uint8_t) Work16) & 0x80)\
APUSetOverflow ();\
@@ -90,7 +96,7 @@ if(((a) ^ (b) ^ (uint8_t) Work16) & 0x10)\
APUSetZN8 ((uint8_t) Work16);
#define CMP(a,b)\
-int16_t Int16 = (int16_t) (a) - (int16_t) (b);\
+Int16 = (int16_t) (a) - (int16_t) (b);\
IAPU._Carry = Int16 >= 0;\
APUSetZN8 ((uint8_t) Int16);
@@ -103,12 +109,12 @@ APUSetZN8 ((uint8_t) Int16);
(b) >>= 1;\
APUSetZN8 (b);
#define ROL(b)\
- uint16_t Work16 = ((b) << 1) | APUCheckCarry (); \
+ Work16 = ((b) << 1) | APUCheckCarry (); \
IAPU._Carry = Work16 >= 0x100; \
(b) = (uint8_t) Work16; \
APUSetZN8 (b);
#define ROR(b)\
- uint16_t Work16 = (b) | ((uint16_t) APUCheckCarry () << 8); \
+ Work16 = (b) | ((uint16_t) APUCheckCarry () << 8); \
IAPU._Carry = (uint8_t) Work16 & 1; \
Work16 >>= 1; \
(b) = (uint8_t) Work16; \
@@ -124,11 +130,19 @@ APUSetZN8 ((uint8_t) Int16);
#ifdef FAST_LSB_WORD_ACCESS
#define SPC700_PushW(w)\
- *(uint16_t *) (IAPU.RAM + 0xff + IAPU.Registers.S) = w;\
+ if (IAPU.Registers.S == 0) {\
+ *(IAPU.RAM + 0x1ff) = (w);\
+ *(IAPU.RAM + 0x100) = ((w) >> 8);\
+ } else { \
+ *(uint16_t *) (IAPU.RAM + 0xff + IAPU.Registers.S) = w;\
+ }\
IAPU.Registers.S -= 2;
#define PopW(w)\
IAPU.Registers.S += 2;\
- w = *(uint16_t *) (IAPU.RAM + 0xff + IAPU.Registers.S);
+ if (IAPU.Registers.S == 0)\
+ (w) = *(IAPU.RAM + 0x1ff) | (*(IAPU.RAM + 0x100) << 8);\
+ else \
+ (w) = *(uint16_t *) (IAPU.RAM + 0xff + IAPU.Registers.S);
#else
#define SPC700_PushW(w)\
*(IAPU.RAM + 0xff + IAPU.Registers.S) = w;\
@@ -136,16 +150,19 @@ APUSetZN8 ((uint8_t) Int16);
IAPU.Registers.S -= 2;
#define PopW(w)\
IAPU.Registers.S += 2; \
- (w) = *(IAPU.RAM + 0xff + IAPU.Registers.S) + (*(IAPU.RAM + 0x100 + IAPU.Registers.S) << 8);
+ if(IAPU.Registers.S == 0) \
+ (w) = *(IAPU.RAM + 0x1ff) | (*(IAPU.RAM + 0x100) << 8); \
+ else \
+ (w) = *(IAPU.RAM + 0xff + IAPU.Registers.S) + (*(IAPU.RAM + 0x100 + IAPU.Registers.S) << 8);
#endif
#define Relative()\
- int8_t Int8 = OP1;\
- int16_t Int16 = (intptr_t) (IAPU.PC + 2 - IAPU.RAM) + Int8;
+ Int8 = OP1;\
+ Int16 = (intptr_t) (IAPU.PC + 2 - IAPU.RAM) + Int8;
#define Relative2()\
- int8_t Int8 = OP2;\
- int16_t Int16 = (intptr_t) (IAPU.PC + 3 - IAPU.RAM) + Int8;
+ Int8 = OP2;\
+ Int16 = (intptr_t) (IAPU.PC + 3 - IAPU.RAM) + Int8;
#ifdef FAST_LSB_WORD_ACCESS
#define IndexedXIndirect()\
@@ -287,7 +304,7 @@ void Apu3F() // CALL absolute
void Apu4F() // PCALL $XX
{
- uint8_t Work8 = OP1;
+ Work8 = OP1;
SPC700_PushW(IAPU.PC + 2 - IAPU.RAM);
IAPU.PC = IAPU.RAM + 0xff00 + Work8;
}
@@ -381,7 +398,7 @@ void ApuF2()
}
#define BBS(b) \
-uint8_t Work8 = OP1; \
+Work8 = OP1; \
Relative2 (); \
if (S9xAPUGetByteZ (Work8) & (1 << (b))) \
{ \
@@ -432,7 +449,7 @@ void ApuE3()
}
#define BBC(b) \
-uint8_t Work8 = OP1; \
+Work8 = OP1; \
Relative2 (); \
if (!(S9xAPUGetByteZ (Work8) & (1 << (b)))) \
{ \
@@ -527,7 +544,7 @@ void Apu08()
void Apu09()
{
// OR dp(dest),dp(src)
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
Work8 |= S9xAPUGetByteZ(OP2);
S9xAPUSetByteZ(Work8, OP2);
APUSetZN8(Work8);
@@ -572,7 +589,7 @@ void Apu17()
void Apu18()
{
// OR dp,#00
- uint8_t Work8 = OP1;
+ Work8 = OP1;
Work8 |= S9xAPUGetByteZ(OP2);
S9xAPUSetByteZ(Work8, OP2);
APUSetZN8(Work8);
@@ -582,8 +599,7 @@ void Apu18()
void Apu19()
{
// OR (X),(Y)
- uint8_t Work8 = S9xAPUGetByteZ(IAPU.Registers.X) | S9xAPUGetByteZ(
- IAPU.Registers.YA.B.Y);
+ Work8 = S9xAPUGetByteZ(IAPU.Registers.X) | S9xAPUGetByteZ(IAPU.Registers.YA.B.Y);
APUSetZN8(Work8);
S9xAPUSetByteZ(Work8, IAPU.Registers.X);
IAPU.PC++;
@@ -641,14 +657,11 @@ void Apu8A()
{
// EOR1 C, membit
MemBit();
- if (APUCheckCarry())
+ if (S9xAPUGetByte(IAPU.Address) & (1 << IAPU.Bit))
{
- if (S9xAPUGetByte(IAPU.Address) & (1 << IAPU.Bit))
+ if (APUCheckCarry())
APUClearCarry();
- }
- else
- {
- if (S9xAPUGetByte(IAPU.Address) & (1 << IAPU.Bit))
+ else
APUSetCarry();
}
IAPU.PC += 3;
@@ -687,7 +700,7 @@ void ApuEA()
void Apu0B()
{
// ASL dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
ASL(Work8);
S9xAPUSetByteZ(Work8, OP1);
IAPU.PC += 2;
@@ -697,7 +710,7 @@ void Apu0C()
{
// ASL abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
ASL(Work8);
S9xAPUSetByte(Work8, IAPU.Address);
IAPU.PC += 3;
@@ -706,7 +719,7 @@ void Apu0C()
void Apu1B()
{
// ASL dp+X
- uint8_t Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
ASL(Work8);
S9xAPUSetByteZ(Work8, OP1 + IAPU.Registers.X);
IAPU.PC += 2;
@@ -785,9 +798,9 @@ void Apu0E()
{
// TSET1 abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
S9xAPUSetByte(Work8 | IAPU.Registers.YA.B.A, IAPU.Address);
- Work8 &= IAPU.Registers.YA.B.A;
+ Work8 = IAPU.Registers.YA.B.A - Work8;
APUSetZN8(Work8);
IAPU.PC += 3;
}
@@ -796,9 +809,9 @@ void Apu4E()
{
// TCLR1 abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
S9xAPUSetByte(Work8 & ~IAPU.Registers.YA.B.A, IAPU.Address);
- Work8 &= IAPU.Registers.YA.B.A;
+ Work8 = IAPU.Registers.YA.B.A - Work8;
APUSetZN8(Work8);
IAPU.PC += 3;
}
@@ -812,23 +825,22 @@ void Apu0F()
Push(IAPU.Registers.P);
APUSetBreak();
APUClearInterrupt();
- // XXX:Where is the BRK vector ???
- IAPU.PC = IAPU.RAM + APU.ExtraRAM[0x20] + (APU.ExtraRAM[0x21] << 8);
+ IAPU.PC = IAPU.RAM + S9xAPUGetByte(0xffde) + (S9xAPUGetByte(0xffdf) << 8);
}
void ApuEF()
{
// SLEEP
- // XXX: sleep
+ APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = false;
IAPU.APUExecuting = false;
- IAPU.PC++;
}
void ApuFF()
{
// STOP
+ APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = false;
IAPU.APUExecuting = false;
- IAPU.PC++;
+ Settings.APUEnabled = false; // re-enabled on next APU reset
}
void Apu10()
@@ -973,8 +985,7 @@ void Apu40()
void Apu1A()
{
// DECW dp
- uint16_t Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8);
- Work16--;
+ Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8) - 1;
S9xAPUSetByteZ((uint8_t) Work16, OP1);
S9xAPUSetByteZ(Work16 >> 8, OP1 + 1);
APUSetZN16(Work16);
@@ -984,8 +995,8 @@ void Apu1A()
void Apu5A()
{
// CMPW YA,dp
- uint16_t Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8);
- int32_t Int32 = (long) IAPU.Registers.YA.W - (long) Work16;
+ Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8);
+ Int32 = (int32_t) IAPU.Registers.YA.W - (int32_t) Work16;
IAPU._Carry = Int32 >= 0;
APUSetZN16((uint16_t) Int32);
IAPU.PC += 2;
@@ -994,40 +1005,36 @@ void Apu5A()
void Apu3A()
{
// INCW dp
- uint16_t Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8);
- Work16++;
+ Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8) + 1;
S9xAPUSetByteZ((uint8_t) Work16, OP1);
S9xAPUSetByteZ(Work16 >> 8, OP1 + 1);
APUSetZN16(Work16);
IAPU.PC += 2;
}
-// XXX: HalfCarry - BJ Fixed? Or is it between bits 7 and 8 for ADDW/SUBW?
void Apu7A()
{
// ADDW YA,dp
- uint16_t Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8);
- uint32_t Work32 = (uint32_t) IAPU.Registers.YA.W + Work16;
+ Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8);
+ Work32 = (uint32_t) IAPU.Registers.YA.W + Work16;
IAPU._Carry = Work32 >= 0x10000;
if (~(IAPU.Registers.YA.W ^ Work16) & (Work16 ^ (uint16_t) Work32) & 0x8000)
APUSetOverflow();
else
APUClearOverflow();
APUClearHalfCarry();
- if ((IAPU.Registers.YA.W ^ Work16 ^ (uint16_t) Work32) & 0x10)
+ if ((IAPU.Registers.YA.W ^ Work16 ^ (uint16_t) Work32) & 0x1000)
APUSetHalfCarry();
IAPU.Registers.YA.W = (uint16_t) Work32;
APUSetZN16(IAPU.Registers.YA.W);
IAPU.PC += 2;
}
-// XXX: BJ: i think the old HalfCarry behavior was wrong...
-// XXX: Or is it between bits 7 and 8 for ADDW/SUBW?
void Apu9A()
{
// SUBW YA,dp
- uint16_t Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8);
- int32_t Int32 = (long) IAPU.Registers.YA.W - (long) Work16;
+ Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8);
+ Int32 = (int32_t) IAPU.Registers.YA.W - (int32_t) Work16;
APUClearHalfCarry();
IAPU._Carry = Int32 >= 0;
if (((IAPU.Registers.YA.W ^ Work16) & 0x8000) &&
@@ -1036,7 +1043,7 @@ void Apu9A()
else
APUClearOverflow();
APUSetHalfCarry();
- if ((IAPU.Registers.YA.W ^ Work16 ^ (uint16_t) Int32) & 0x10)
+ if ((IAPU.Registers.YA.W ^ Work16 ^ (uint16_t) Int32) & 0x1000)
APUClearHalfCarry();
IAPU.Registers.YA.W = (uint16_t) Int32;
APUSetZN16(IAPU.Registers.YA.W);
@@ -1063,7 +1070,7 @@ void ApuDA()
void Apu64()
{
// CMP A,dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
CMP(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1072,7 +1079,7 @@ void Apu65()
{
// CMP A,abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
CMP(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 3;
}
@@ -1080,7 +1087,7 @@ void Apu65()
void Apu66()
{
// CMP A,(X)
- uint8_t Work8 = S9xAPUGetByteZ(IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(IAPU.Registers.X);
CMP(IAPU.Registers.YA.B.A, Work8);
IAPU.PC++;
}
@@ -1089,7 +1096,7 @@ void Apu67()
{
// CMP A,(dp+X)
IndexedXIndirect();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
CMP(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1097,7 +1104,7 @@ void Apu67()
void Apu68()
{
// CMP A,#00
- uint8_t Work8 = OP1;
+ Work8 = OP1;
CMP(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1105,8 +1112,8 @@ void Apu68()
void Apu69()
{
// CMP dp(dest), dp(src)
- uint8_t W1 = S9xAPUGetByteZ(OP1);
- uint8_t Work8 = S9xAPUGetByteZ(OP2);
+ W1 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP2);
CMP(Work8, W1);
IAPU.PC += 3;
}
@@ -1114,7 +1121,7 @@ void Apu69()
void Apu74()
{
// CMP A, dp+X
- uint8_t Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
CMP(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1123,7 +1130,7 @@ void Apu75()
{
// CMP A,abs+X
AbsoluteX();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
CMP(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 3;
}
@@ -1132,7 +1139,7 @@ void Apu76()
{
// CMP A, abs+Y
AbsoluteY();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
CMP(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 3;
}
@@ -1141,7 +1148,7 @@ void Apu77()
{
// CMP A,(dp)+Y
IndirectIndexedY();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
CMP(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1149,8 +1156,8 @@ void Apu77()
void Apu78()
{
// CMP dp,#00
- uint8_t Work8 = OP1;
- uint8_t W1 = S9xAPUGetByteZ(OP2);
+ Work8 = OP1;
+ W1 = S9xAPUGetByteZ(OP2);
CMP(W1, Work8);
IAPU.PC += 3;
}
@@ -1158,8 +1165,8 @@ void Apu78()
void Apu79()
{
// CMP (X),(Y)
- uint8_t W1 = S9xAPUGetByteZ(IAPU.Registers.X);
- uint8_t Work8 = S9xAPUGetByteZ(IAPU.Registers.YA.B.Y);
+ W1 = S9xAPUGetByteZ(IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(IAPU.Registers.YA.B.Y);
CMP(W1, Work8);
IAPU.PC++;
}
@@ -1168,7 +1175,7 @@ void Apu1E()
{
// CMP X,abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
CMP(IAPU.Registers.X, Work8);
IAPU.PC += 3;
}
@@ -1176,7 +1183,7 @@ void Apu1E()
void Apu3E()
{
// CMP X,dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
CMP(IAPU.Registers.X, Work8);
IAPU.PC += 2;
}
@@ -1192,7 +1199,7 @@ void Apu5E()
{
// CMP Y,abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
CMP(IAPU.Registers.YA.B.Y, Work8);
IAPU.PC += 3;
}
@@ -1200,7 +1207,7 @@ void Apu5E()
void Apu7E()
{
// CMP Y,dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
CMP(IAPU.Registers.YA.B.Y, Work8);
IAPU.PC += 2;
}
@@ -1208,7 +1215,7 @@ void Apu7E()
void ApuAD()
{
// CMP Y,#00
- uint8_t Work8 = OP1;
+ Work8 = OP1;
CMP(IAPU.Registers.YA.B.Y, Work8);
IAPU.PC += 2;
}
@@ -1219,8 +1226,6 @@ void Apu1F()
Absolute();
IAPU.PC = IAPU.RAM + S9xAPUGetByte(IAPU.Address + IAPU.Registers.X) +
(S9xAPUGetByte(IAPU.Address + IAPU.Registers.X + 1) << 8);
- // XXX: HERE:
- // APU.Flags |= TRACE_FLAG;
}
void Apu5F()
@@ -1298,7 +1303,7 @@ void Apu28()
void Apu29()
{
// AND dp(dest),dp(src)
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
Work8 &= S9xAPUGetByteZ(OP2);
S9xAPUSetByteZ(Work8, OP2);
APUSetZN8(Work8);
@@ -1343,7 +1348,7 @@ void Apu37()
void Apu38()
{
// AND dp,#00
- uint8_t Work8 = OP1;
+ Work8 = OP1;
Work8 &= S9xAPUGetByteZ(OP2);
S9xAPUSetByteZ(Work8, OP2);
APUSetZN8(Work8);
@@ -1353,8 +1358,7 @@ void Apu38()
void Apu39()
{
// AND (X),(Y)
- uint8_t Work8 = S9xAPUGetByteZ(IAPU.Registers.X) & S9xAPUGetByteZ(
- IAPU.Registers.YA.B.Y);
+ Work8 = S9xAPUGetByteZ(IAPU.Registers.X) & S9xAPUGetByteZ(IAPU.Registers.YA.B.Y);
APUSetZN8(Work8);
S9xAPUSetByteZ(Work8, IAPU.Registers.X);
IAPU.PC++;
@@ -1363,7 +1367,7 @@ void Apu39()
void Apu2B()
{
// ROL dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
ROL(Work8);
S9xAPUSetByteZ(Work8, OP1);
IAPU.PC += 2;
@@ -1373,7 +1377,7 @@ void Apu2C()
{
// ROL abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
ROL(Work8);
S9xAPUSetByte(Work8, IAPU.Address);
IAPU.PC += 3;
@@ -1382,7 +1386,7 @@ void Apu2C()
void Apu3B()
{
// ROL dp+X
- uint8_t Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
ROL(Work8);
S9xAPUSetByteZ(Work8, OP1 + IAPU.Registers.X);
IAPU.PC += 2;
@@ -1398,7 +1402,7 @@ void Apu3C()
void Apu2E()
{
// CBNE dp,rel
- uint8_t Work8 = OP1;
+ Work8 = OP1;
Relative2();
if (S9xAPUGetByteZ(Work8) != IAPU.Registers.YA.B.A)
@@ -1414,7 +1418,7 @@ void Apu2E()
void ApuDE()
{
// CBNE dp+X,rel
- uint8_t Work8 = OP1 + IAPU.Registers.X;
+ Work8 = OP1 + IAPU.Registers.X;
Relative2();
if (S9xAPUGetByteZ(Work8) != IAPU.Registers.YA.B.A)
@@ -1482,7 +1486,7 @@ void ApuDC()
void ApuAB()
{
// INC dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1) + 1;
+ Work8 = S9xAPUGetByteZ(OP1) + 1;
S9xAPUSetByteZ(Work8, OP1);
APUSetZN8(Work8);
@@ -1497,7 +1501,7 @@ void ApuAC()
{
// INC abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address) + 1;
+ Work8 = S9xAPUGetByte(IAPU.Address) + 1;
S9xAPUSetByte(Work8, IAPU.Address);
APUSetZN8(Work8);
@@ -1511,7 +1515,7 @@ void ApuAC()
void ApuBB()
{
// INC dp+X
- uint8_t Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X) + 1;
+ Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X) + 1;
S9xAPUSetByteZ(Work8, OP1 + IAPU.Registers.X);
APUSetZN8(Work8);
@@ -1538,7 +1542,7 @@ void ApuBC()
void Apu8B()
{
// DEC dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1) - 1;
+ Work8 = S9xAPUGetByteZ(OP1) - 1;
S9xAPUSetByteZ(Work8, OP1);
APUSetZN8(Work8);
@@ -1553,7 +1557,7 @@ void Apu8C()
{
// DEC abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address) - 1;
+ Work8 = S9xAPUGetByte(IAPU.Address) - 1;
S9xAPUSetByte(Work8, IAPU.Address);
APUSetZN8(Work8);
@@ -1567,7 +1571,7 @@ void Apu8C()
void Apu9B()
{
// DEC dp+X
- uint8_t Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X) - 1;
+ Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X) - 1;
S9xAPUSetByteZ(Work8, OP1 + IAPU.Registers.X);
APUSetZN8(Work8);
@@ -1636,7 +1640,7 @@ void Apu48()
void Apu49()
{
// EOR dp(dest),dp(src)
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
Work8 ^= S9xAPUGetByteZ(OP2);
S9xAPUSetByteZ(Work8, OP2);
APUSetZN8(Work8);
@@ -1681,7 +1685,7 @@ void Apu57()
void Apu58()
{
// EOR dp,#00
- uint8_t Work8 = OP1;
+ Work8 = OP1;
Work8 ^= S9xAPUGetByteZ(OP2);
S9xAPUSetByteZ(Work8, OP2);
APUSetZN8(Work8);
@@ -1691,8 +1695,7 @@ void Apu58()
void Apu59()
{
// EOR (X),(Y)
- uint8_t Work8 = S9xAPUGetByteZ(IAPU.Registers.X) ^ S9xAPUGetByteZ(
- IAPU.Registers.YA.B.Y);
+ Work8 = S9xAPUGetByteZ(IAPU.Registers.X) ^ S9xAPUGetByteZ(IAPU.Registers.YA.B.Y);
APUSetZN8(Work8);
S9xAPUSetByteZ(Work8, IAPU.Registers.X);
IAPU.PC++;
@@ -1701,7 +1704,7 @@ void Apu59()
void Apu4B()
{
// LSR dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
LSR(Work8);
S9xAPUSetByteZ(Work8, OP1);
IAPU.PC += 2;
@@ -1711,7 +1714,7 @@ void Apu4C()
{
// LSR abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
LSR(Work8);
S9xAPUSetByte(Work8, IAPU.Address);
IAPU.PC += 3;
@@ -1720,7 +1723,7 @@ void Apu4C()
void Apu5B()
{
// LSR dp+X
- uint8_t Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
LSR(Work8);
S9xAPUSetByteZ(Work8, OP1 + IAPU.Registers.X);
IAPU.PC += 2;
@@ -1783,7 +1786,7 @@ void ApuBD()
void Apu6B()
{
// ROR dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
ROR(Work8);
S9xAPUSetByteZ(Work8, OP1);
IAPU.PC += 2;
@@ -1793,7 +1796,7 @@ void Apu6C()
{
// ROR abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
ROR(Work8);
S9xAPUSetByte(Work8, IAPU.Address);
IAPU.PC += 3;
@@ -1802,7 +1805,7 @@ void Apu6C()
void Apu7B()
{
// ROR dp+X
- uint8_t Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
ROR(Work8);
S9xAPUSetByteZ(Work8, OP1 + IAPU.Registers.X);
IAPU.PC += 2;
@@ -1818,9 +1821,9 @@ void Apu7C()
void Apu6E()
{
// DBNZ dp,rel
- uint8_t Work8 = OP1;
+ Work8 = OP1;
Relative2();
- uint8_t W1 = S9xAPUGetByteZ(Work8) - 1;
+ W1 = S9xAPUGetByteZ(Work8) - 1;
S9xAPUSetByteZ(W1, Work8);
if (W1 != 0)
{
@@ -1864,7 +1867,7 @@ void Apu7F()
void Apu84()
{
// ADC A,dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
ADC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1873,7 +1876,7 @@ void Apu85()
{
// ADC A, abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
ADC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 3;
}
@@ -1881,7 +1884,7 @@ void Apu85()
void Apu86()
{
// ADC A,(X)
- uint8_t Work8 = S9xAPUGetByteZ(IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(IAPU.Registers.X);
ADC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC++;
}
@@ -1890,7 +1893,7 @@ void Apu87()
{
// ADC A,(dp+X)
IndexedXIndirect();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
ADC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1898,7 +1901,7 @@ void Apu87()
void Apu88()
{
// ADC A,#00
- uint8_t Work8 = OP1;
+ Work8 = OP1;
ADC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1906,8 +1909,8 @@ void Apu88()
void Apu89()
{
// ADC dp(dest),dp(src)
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
- uint8_t W1 = S9xAPUGetByteZ(OP2);
+ Work8 = S9xAPUGetByteZ(OP1);
+ W1 = S9xAPUGetByteZ(OP2);
ADC(W1, Work8);
S9xAPUSetByteZ(W1, OP2);
IAPU.PC += 3;
@@ -1916,7 +1919,7 @@ void Apu89()
void Apu94()
{
// ADC A,dp+X
- uint8_t Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
ADC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1925,7 +1928,7 @@ void Apu95()
{
// ADC A, abs+X
AbsoluteX();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
ADC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 3;
}
@@ -1934,7 +1937,7 @@ void Apu96()
{
// ADC A, abs+Y
AbsoluteY();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
ADC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 3;
}
@@ -1943,7 +1946,7 @@ void Apu97()
{
// ADC A, (dp)+Y
IndirectIndexedY();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
ADC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -1951,8 +1954,8 @@ void Apu97()
void Apu98()
{
// ADC dp,#00
- uint8_t Work8 = OP1;
- uint8_t W1 = S9xAPUGetByteZ(OP2);
+ Work8 = OP1;
+ W1 = S9xAPUGetByteZ(OP2);
ADC(W1, Work8);
S9xAPUSetByteZ(W1, OP2);
IAPU.PC += 3;
@@ -1961,8 +1964,8 @@ void Apu98()
void Apu99()
{
// ADC (X),(Y)
- uint8_t W1 = S9xAPUGetByteZ(IAPU.Registers.X);
- uint8_t Work8 = S9xAPUGetByteZ(IAPU.Registers.YA.B.Y);
+ W1 = S9xAPUGetByteZ(IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(IAPU.Registers.YA.B.Y);
ADC(W1, Work8);
S9xAPUSetByteZ(W1, IAPU.Registers.X);
IAPU.PC++;
@@ -1979,7 +1982,7 @@ void Apu8D()
void Apu8F()
{
// MOV dp,#00
- uint8_t Work8 = OP1;
+ Work8 = OP1;
S9xAPUSetByteZ(Work8, OP2);
IAPU.PC += 3;
}
@@ -1987,20 +1990,36 @@ void Apu8F()
void Apu9E()
{
// DIV YA,X
- if (IAPU.Registers.X == 0)
- {
- APUSetOverflow();
- IAPU.Registers.YA.B.Y = 0xff;
- IAPU.Registers.YA.B.A = 0xff;
- }
+ if ((IAPU.Registers.X & 0x0f) <= (IAPU.Registers.YA.B.Y & 0x0f))
+ APUSetHalfCarry();
else
+ APUClearHalfCarry();
+
+ uint32_t yva = IAPU.Registers.YA.W;
+ uint32_t x = IAPU.Registers.X << 9;
+ uint32_t i;
+
+ for (i = 0 ; i < 9 ; ++i)
{
- APUClearOverflow();
- uint8_t Work8 = IAPU.Registers.YA.W / IAPU.Registers.X;
- IAPU.Registers.YA.B.Y = IAPU.Registers.YA.W % IAPU.Registers.X;
- IAPU.Registers.YA.B.A = Work8;
+ yva <<= 1;
+
+ if (yva & 0x20000)
+ yva = (yva & 0x1ffff) | 1;
+
+ if (yva >= x)
+ yva ^= 1;
+
+ if (yva & 1)
+ yva = (yva - x) & 0x1ffff;
}
- // XXX How should Overflow, Half Carry, Zero and Negative flags be set??
+
+ if (yva & 0x100)
+ APUSetOverflow();
+ else
+ APUClearOverflow();
+
+ IAPU.Registers.YA.B.Y = (yva >> 9) & 0xff;
+ IAPU.Registers.YA.B.A = yva & 0xff;
APUSetZN8(IAPU.Registers.YA.B.A);
IAPU.PC++;
}
@@ -2016,7 +2035,7 @@ void Apu9F()
void ApuA4()
{
// SBC A, dp
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
+ Work8 = S9xAPUGetByteZ(OP1);
SBC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -2025,7 +2044,7 @@ void ApuA5()
{
// SBC A, abs
Absolute();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
SBC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 3;
}
@@ -2033,7 +2052,7 @@ void ApuA5()
void ApuA6()
{
// SBC A, (X)
- uint8_t Work8 = S9xAPUGetByteZ(IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(IAPU.Registers.X);
SBC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC++;
}
@@ -2042,7 +2061,7 @@ void ApuA7()
{
// SBC A,(dp+X)
IndexedXIndirect();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
SBC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -2050,7 +2069,7 @@ void ApuA7()
void ApuA8()
{
// SBC A,#00
- uint8_t Work8 = OP1;
+ Work8 = OP1;
SBC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -2058,8 +2077,8 @@ void ApuA8()
void ApuA9()
{
// SBC dp(dest), dp(src)
- uint8_t Work8 = S9xAPUGetByteZ(OP1);
- uint8_t W1 = S9xAPUGetByteZ(OP2);
+ Work8 = S9xAPUGetByteZ(OP1);
+ W1 = S9xAPUGetByteZ(OP2);
SBC(W1, Work8);
S9xAPUSetByteZ(W1, OP2);
IAPU.PC += 3;
@@ -2068,7 +2087,7 @@ void ApuA9()
void ApuB4()
{
// SBC A, dp+X
- uint8_t Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X);
SBC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -2077,7 +2096,7 @@ void ApuB5()
{
// SBC A,abs+X
AbsoluteX();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
SBC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 3;
}
@@ -2086,7 +2105,7 @@ void ApuB6()
{
// SBC A,abs+Y
AbsoluteY();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
SBC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 3;
}
@@ -2095,7 +2114,7 @@ void ApuB7()
{
// SBC A,(dp)+Y
IndirectIndexedY();
- uint8_t Work8 = S9xAPUGetByte(IAPU.Address);
+ Work8 = S9xAPUGetByte(IAPU.Address);
SBC(IAPU.Registers.YA.B.A, Work8);
IAPU.PC += 2;
}
@@ -2103,8 +2122,8 @@ void ApuB7()
void ApuB8()
{
// SBC dp,#00
- uint8_t Work8 = OP1;
- uint8_t W1 = S9xAPUGetByteZ(OP2);
+ Work8 = OP1;
+ W1 = S9xAPUGetByteZ(OP2);
SBC(W1, Work8);
S9xAPUSetByteZ(W1, OP2);
IAPU.PC += 3;
@@ -2113,8 +2132,8 @@ void ApuB8()
void ApuB9()
{
// SBC (X),(Y)
- uint8_t W1 = S9xAPUGetByteZ(IAPU.Registers.X);
- uint8_t Work8 = S9xAPUGetByteZ(IAPU.Registers.YA.B.Y);
+ W1 = S9xAPUGetByteZ(IAPU.Registers.X);
+ Work8 = S9xAPUGetByteZ(IAPU.Registers.YA.B.Y);
SBC(W1, Work8);
S9xAPUSetByteZ(W1, IAPU.Registers.X);
IAPU.PC++;
@@ -2130,15 +2149,17 @@ void ApuAF()
void ApuBE()
{
// DAS
- if ((IAPU.Registers.YA.B.A & 0x0f) > 9 || !APUCheckHalfCarry())
- IAPU.Registers.YA.B.A -= 6;
- if (IAPU.Registers.YA.B.A > 0x9f || !IAPU._Carry)
+ if (IAPU.Registers.YA.B.A > 0x99 || !IAPU._Carry)
{
IAPU.Registers.YA.B.A -= 0x60;
APUClearCarry();
}
else
APUSetCarry();
+
+ if ((IAPU.Registers.YA.B.A & 0x0f) > 9 || !APUCheckHalfCarry())
+ IAPU.Registers.YA.B.A -= 6;
+
APUSetZN8(IAPU.Registers.YA.B.A);
IAPU.PC++;
}
@@ -2230,7 +2251,7 @@ void ApuCF()
{
// MUL YA
IAPU.Registers.YA.W = (uint16_t) IAPU.Registers.YA.B.A * IAPU.Registers.YA.B.Y;
- APUSetZN16(IAPU.Registers.YA.W);
+ APUSetZN8(IAPU.Registers.YA.B.Y);
IAPU.PC++;
}
@@ -2289,20 +2310,17 @@ void ApuDB()
void ApuDF()
{
// DAA
- if ((IAPU.Registers.YA.B.A & 0x0f) > 9 || APUCheckHalfCarry())
- {
- if (IAPU.Registers.YA.B.A > 0xf0) APUSetCarry();
- IAPU.Registers.YA.B.A += 6;
- //APUSetHalfCarry (); Intel procs do this, but this is a Sony proc...
- }
- //else { APUClearHalfCarry (); } ditto as above
- if (IAPU.Registers.YA.B.A > 0x9f || IAPU._Carry)
+ if (IAPU.Registers.YA.B.A > 0x99 || IAPU._Carry)
{
IAPU.Registers.YA.B.A += 0x60;
APUSetCarry();
}
else
APUClearCarry();
+
+ if ((IAPU.Registers.YA.B.A & 0x0f) > 9 || APUCheckHalfCarry())
+ IAPU.Registers.YA.B.A += 6;
+
APUSetZN8(IAPU.Registers.YA.B.A);
IAPU.PC++;
}