From d8b66ac6d0524b3538ad595825651b28329f9033 Mon Sep 17 00:00:00 2001 From: João Silva Date: Tue, 24 Jan 2017 20:32:46 +0000 Subject: Sound improvements - some by me, most from snes9x2002 and snes9x 1.51. --- libretro.c | 17 +- source/apu.c | 299 ++++++-------------------- source/apu.h | 5 +- source/apumem.h | 40 ++-- source/dma.c | 7 - source/fxinst.h | 3 - source/globals.c | 1 - source/soundux.c | 645 ++++++++++++++++++++----------------------------------- source/soundux.h | 29 +-- source/spc700.c | 338 +++++++++++++++-------------- 10 files changed, 505 insertions(+), 879 deletions(-) diff --git a/libretro.c b/libretro.c index d7f20b0..9e88d2c 100644 --- a/libretro.c +++ b/libretro.c @@ -44,6 +44,7 @@ char slash = '/'; #endif static float samples_per_frame = 0.0; +static float samplerate = (((SNES_CLOCK_SPEED * 6) / (32 * ONE_APU_CYCLE))); #ifdef PERF_TEST #define RETRO_PERFORMANCE_INIT(name) \ @@ -264,13 +265,12 @@ void init_sfc_setting(void) { memset(&Settings, 0, sizeof(Settings)); Settings.JoystickEnabled = false; - Settings.SoundPlaybackRate = 32000; // -> ds2sound.h for defs - Settings.SoundBufferSize = 512; + Settings.SoundPlaybackRate = samplerate; Settings.CyclesPercentage = 100; Settings.DisableSoundEcho = false; Settings.InterpolatedSound = true; - Settings.APUEnabled = Settings.NextAPUEnabled = true; + Settings.APUEnabled = true; Settings.H_Max = SNES_CYCLES_PER_SCANLINE; Settings.SkipFrames = AUTO_FRAMERATE; @@ -285,7 +285,6 @@ void init_sfc_setting(void) Settings.Transparency = true; Settings.SupportHiRes = true; - Settings.ThreadSound = false; #ifdef USE_BLARGG_APU Settings.SoundSync = false; #endif @@ -597,13 +596,7 @@ void retro_get_system_av_info(struct retro_system_av_info* info) info->timing.fps = (SNES_CLOCK_SPEED * 6.0 / (SNES_CYCLES_PER_SCANLINE * SNES_MAX_PAL_VCOUNTER)); - info->timing.sample_rate = (((SNES_CLOCK_SPEED * 6) / (32 * ONE_APU_CYCLE))); - - // small hack to improve av sync - // since S9xSetPlaybackRate only accepts integral numbers. - - info->timing.fps = info->timing.fps * 32000 / info->timing.sample_rate; - info->timing.sample_rate = 32000; + info->timing.sample_rate = samplerate; } void retro_reset(void) @@ -894,7 +887,7 @@ bool retro_load_game(const struct retro_game_info* game) Settings.SoundPlaybackRate = av_info.timing.sample_rate; #else samples_per_frame = av_info.timing.sample_rate / av_info.timing.fps; - S9xSetPlaybackRate(32*1024); + S9xSetPlaybackRate(Settings.SoundPlaybackRate); #endif return true; } 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 #include #include -#include #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++; } -- cgit v1.2.3