rlm@1: #ifdef WIN32 rlm@1: # include "../win32/stdafx.h" rlm@1: # include "../win32/VBA.h" rlm@1: #endif rlm@1: rlm@1: #include rlm@1: #include rlm@524: #include rlm@1: rlm@1: #include "../common/System.h" rlm@1: #include "../common/Util.h" rlm@1: //#include "../Blip_Buffer.h" rlm@1: #include "gbGlobals.h" rlm@1: #include "gbSound.h" rlm@1: rlm@1: #ifndef countof rlm@1: #define countof(a) (sizeof(a) / sizeof(a[0])) rlm@1: #endif rlm@1: rlm@1: extern u8 soundBuffer[6][735]; rlm@1: extern u16 soundFinalWave[1470]; rlm@1: extern u16 soundFrameSound[735 * 30 * 2]; rlm@1: extern int32 soundVolume; rlm@1: rlm@1: soundtick_t GB_USE_TICKS_AS = 24; // (1048576.0/44100.0); // FIXME: (4194304.0/70224.0)(fps) vs 60.0fps? rlm@1: rlm@1: #define SOUND_MAGIC 0x60000000 rlm@1: #define SOUND_MAGIC_2 0x30000000 rlm@1: #define NOISE_MAGIC (2097152.0 / 44100.0) rlm@1: rlm@1: extern int32 speed; rlm@1: rlm@1: extern u8 soundWavePattern[4][32]; rlm@1: rlm@1: extern u32 soundBufferLen; rlm@1: extern u32 soundBufferTotalLen; rlm@1: extern int32 soundQuality; rlm@1: extern int32 soundPaused; rlm@1: extern int32 soundPlay; rlm@1: extern soundtick_t soundTicks; rlm@1: extern soundtick_t SOUND_CLOCK_TICKS; rlm@1: extern u32 soundNextPosition; rlm@1: rlm@1: extern int32 soundLevel1; rlm@1: extern int32 soundLevel2; rlm@1: extern int32 soundBalance; rlm@1: extern int32 soundMasterOn; rlm@1: extern u32 soundIndex; rlm@1: extern u32 soundBufferIndex; rlm@1: extern int32 soundFrameSoundWritten; rlm@1: int32 soundVIN = 0; rlm@1: extern int32 soundDebug; rlm@1: rlm@1: extern int32 sound1On; rlm@1: extern int32 sound1ATL; rlm@1: extern int32 sound1Skip; rlm@1: extern int32 sound1Index; rlm@1: extern int32 sound1Continue; rlm@1: extern int32 sound1EnvelopeVolume; rlm@1: extern int32 sound1EnvelopeATL; rlm@1: extern int32 sound1EnvelopeUpDown; rlm@1: extern int32 sound1EnvelopeATLReload; rlm@1: extern int32 sound1SweepATL; rlm@1: extern int32 sound1SweepATLReload; rlm@1: extern int32 sound1SweepSteps; rlm@1: extern int32 sound1SweepUpDown; rlm@1: extern int32 sound1SweepStep; rlm@1: extern u8 * sound1Wave; rlm@1: rlm@1: extern int32 sound2On; rlm@1: extern int32 sound2ATL; rlm@1: extern int32 sound2Skip; rlm@1: extern int32 sound2Index; rlm@1: extern int32 sound2Continue; rlm@1: extern int32 sound2EnvelopeVolume; rlm@1: extern int32 sound2EnvelopeATL; rlm@1: extern int32 sound2EnvelopeUpDown; rlm@1: extern int32 sound2EnvelopeATLReload; rlm@1: extern u8 * sound2Wave; rlm@1: rlm@1: extern int32 sound3On; rlm@1: extern int32 sound3ATL; rlm@1: extern int32 sound3Skip; rlm@1: extern int32 sound3Index; rlm@1: extern int32 sound3Continue; rlm@1: extern int32 sound3OutputLevel; rlm@1: extern int32 sound3Last; rlm@1: rlm@1: extern int32 sound4On; rlm@1: extern int32 sound4Clock; rlm@1: extern int32 sound4ATL; rlm@1: extern int32 sound4Skip; rlm@1: extern int32 sound4Index; rlm@1: extern int32 sound4ShiftRight; rlm@1: extern int32 sound4ShiftSkip; rlm@1: extern int32 sound4ShiftIndex; rlm@1: extern int32 sound4NSteps; rlm@1: extern int32 sound4CountDown; rlm@1: extern int32 sound4Continue; rlm@1: extern int32 sound4EnvelopeVolume; rlm@1: extern int32 sound4EnvelopeATL; rlm@1: extern int32 sound4EnvelopeUpDown; rlm@1: extern int32 sound4EnvelopeATLReload; rlm@1: rlm@1: extern int32 soundEnableFlag; rlm@1: extern int32 soundMutedFlag; rlm@1: rlm@1: extern int32 soundFreqRatio[8]; rlm@1: extern int32 soundShiftClock[16]; rlm@1: rlm@1: extern s16 soundFilter[4000]; rlm@1: extern s16 soundLeft[5]; rlm@1: extern s16 soundRight[5]; rlm@1: extern int32 soundEchoIndex; rlm@1: extern bool8 soundEcho; rlm@1: extern bool8 soundLowPass; rlm@1: extern bool8 soundReverse; rlm@1: extern bool8 soundOffFlag; rlm@1: rlm@1: bool8 gbDigitalSound = false; rlm@1: rlm@1: void gbSoundEvent(register u16 address, register int data) rlm@1: { rlm@1: int freq = 0; rlm@1: rlm@1: gbMemory[address] = data; rlm@1: rlm@1: #ifndef FINAL_VERSION rlm@1: if (soundDebug) rlm@1: { rlm@1: // don't translate. debug only rlm@1: log("Sound event: %08lx %02x\n", address, data); rlm@1: } rlm@1: #endif rlm@1: switch (address) rlm@1: { rlm@1: case NR10: rlm@1: sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7); rlm@1: sound1SweepSteps = data & 7; rlm@1: sound1SweepUpDown = data & 0x08; rlm@1: sound1SweepStep = 0; rlm@1: break; rlm@1: case NR11: rlm@1: sound1Wave = soundWavePattern[data >> 6]; rlm@1: sound1ATL = 172 * (64 - (data & 0x3f)); rlm@1: break; rlm@1: case NR12: rlm@1: sound1EnvelopeVolume = data >> 4; rlm@1: sound1EnvelopeUpDown = data & 0x08; rlm@1: sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (data & 7); rlm@1: break; rlm@1: case NR13: rlm@1: freq = (((int)(gbMemory[NR14] & 7)) << 8) | data; rlm@1: sound1ATL = 172 * (64 - (gbMemory[NR11] & 0x3f)); rlm@1: freq = 2048 - freq; rlm@1: if (freq) rlm@1: { rlm@1: sound1Skip = SOUND_MAGIC / freq; rlm@1: } rlm@1: else rlm@1: sound1Skip = 0; rlm@1: break; rlm@1: case NR14: rlm@1: freq = (((int)(data & 7) << 8) | gbMemory[NR13]); rlm@1: freq = 2048 - freq; rlm@1: sound1ATL = 172 * (64 - (gbMemory[NR11] & 0x3f)); rlm@1: sound1Continue = data & 0x40; rlm@1: if (freq) rlm@1: { rlm@1: sound1Skip = SOUND_MAGIC / freq; rlm@1: } rlm@1: else rlm@1: sound1Skip = 0; rlm@1: if (data & 0x80) rlm@1: { rlm@1: gbMemory[NR52] |= 1; rlm@1: sound1EnvelopeVolume = gbMemory[NR12] >> 4; rlm@1: sound1EnvelopeUpDown = gbMemory[NR12] & 0x08; rlm@1: sound1ATL = 172 * (64 - (gbMemory[NR11] & 0x3f)); rlm@1: sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (gbMemory[NR12] & 7); rlm@1: sound1SweepATL = sound1SweepATLReload = 344 * ((gbMemory[NR10] >> 4) & 7); rlm@1: sound1SweepSteps = gbMemory[NR10] & 7; rlm@1: sound1SweepUpDown = gbMemory[NR10] & 0x08; rlm@1: sound1SweepStep = 0; rlm@1: rlm@1: sound1Index = 0; rlm@1: sound1On = 1; rlm@1: } rlm@1: break; rlm@1: case NR21: rlm@1: sound2Wave = soundWavePattern[data >> 6]; rlm@1: sound2ATL = 172 * (64 - (data & 0x3f)); rlm@1: break; rlm@1: case NR22: rlm@1: sound2EnvelopeVolume = data >> 4; rlm@1: sound2EnvelopeUpDown = data & 0x08; rlm@1: sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (data & 7); rlm@1: break; rlm@1: case NR23: rlm@1: freq = (((int)(gbMemory[NR24] & 7)) << 8) | data; rlm@1: sound2ATL = 172 * (64 - (gbMemory[NR21] & 0x3f)); rlm@1: freq = 2048 - freq; rlm@1: if (freq) rlm@1: { rlm@1: sound2Skip = SOUND_MAGIC / freq; rlm@1: } rlm@1: else rlm@1: sound2Skip = 0; rlm@1: break; rlm@1: case NR24: rlm@1: freq = (((int)(data & 7) << 8) | gbMemory[NR23]); rlm@1: freq = 2048 - freq; rlm@1: sound2ATL = 172 * (64 - (gbMemory[NR21] & 0x3f)); rlm@1: sound2Continue = data & 0x40; rlm@1: if (freq) rlm@1: { rlm@1: sound2Skip = SOUND_MAGIC / freq; rlm@1: } rlm@1: else rlm@1: sound2Skip = 0; rlm@1: if (data & 0x80) rlm@1: { rlm@1: gbMemory[NR52] |= 2; rlm@1: sound2EnvelopeVolume = gbMemory[NR22] >> 4; rlm@1: sound2EnvelopeUpDown = gbMemory[NR22] & 0x08; rlm@1: sound2ATL = 172 * (64 - (gbMemory[NR21] & 0x3f)); rlm@1: sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (gbMemory[NR22] & 7); rlm@1: rlm@1: sound2Index = 0; rlm@1: sound2On = 1; rlm@1: } rlm@1: break; rlm@1: case NR30: rlm@1: if (!(data & 0x80)) rlm@1: { rlm@1: gbMemory[NR52] &= 0xfb; rlm@1: sound3On = 0; rlm@1: } rlm@1: break; rlm@1: case NR31: rlm@1: sound3ATL = 172 * (256 - data); rlm@1: break; rlm@1: case NR32: rlm@1: sound3OutputLevel = (data >> 5) & 3; rlm@1: break; rlm@1: case NR33: rlm@1: freq = 2048 - (((int)(gbMemory[NR34] & 7) << 8) | data); rlm@1: if (freq) rlm@1: { rlm@1: sound3Skip = SOUND_MAGIC_2 / freq; rlm@1: } rlm@1: else rlm@1: sound3Skip = 0; rlm@1: break; rlm@1: case NR34: rlm@1: freq = 2048 - (((data & 7) << 8) | (int)gbMemory[NR33]); rlm@1: if (freq) rlm@1: { rlm@1: sound3Skip = SOUND_MAGIC_2 / freq; rlm@1: } rlm@1: else rlm@1: { rlm@1: sound3Skip = 0; rlm@1: } rlm@1: sound3Continue = data & 0x40; rlm@1: if ((data & 0x80) && (gbMemory[NR30] & 0x80)) rlm@1: { rlm@1: gbMemory[NR52] |= 4; rlm@1: sound3ATL = 172 * (256 - gbMemory[NR31]); rlm@1: sound3Index = 0; rlm@1: sound3On = 1; rlm@1: } rlm@1: break; rlm@1: case NR41: rlm@1: sound4ATL = 172 * (64 - (data & 0x3f)); rlm@1: break; rlm@1: case NR42: rlm@1: sound4EnvelopeVolume = data >> 4; rlm@1: sound4EnvelopeUpDown = data & 0x08; rlm@1: sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (data & 7); rlm@1: break; rlm@1: case NR43: rlm@1: freq = soundFreqRatio[data & 7]; rlm@1: sound4NSteps = data & 0x08; rlm@1: rlm@1: sound4Skip = freq * NOISE_MAGIC; rlm@1: rlm@1: sound4Clock = data >> 4; rlm@1: rlm@1: freq = freq / soundShiftClock[sound4Clock]; rlm@1: rlm@1: sound4ShiftSkip = freq * NOISE_MAGIC; rlm@1: rlm@1: break; rlm@1: case NR44: rlm@1: sound4Continue = data & 0x40; rlm@1: if (data & 0x80) rlm@1: { rlm@1: gbMemory[NR52] |= 8; rlm@1: sound4EnvelopeVolume = gbMemory[NR42] >> 4; rlm@1: sound4EnvelopeUpDown = gbMemory[NR42] & 0x08; rlm@1: sound4ATL = 172 * (64 - (gbMemory[NR41] & 0x3f)); rlm@1: sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (gbMemory[NR42] & 7); rlm@1: rlm@1: sound4On = 1; rlm@1: rlm@1: sound4Index = 0; rlm@1: sound4ShiftIndex = 0; rlm@1: rlm@1: freq = soundFreqRatio[gbMemory[NR43] & 7]; rlm@1: rlm@1: sound4Skip = freq * NOISE_MAGIC; rlm@1: rlm@1: sound4NSteps = gbMemory[NR43] & 0x08; rlm@1: rlm@1: freq = freq / soundShiftClock[gbMemory[NR43] >> 4]; rlm@1: rlm@1: sound4ShiftSkip = freq * NOISE_MAGIC; rlm@1: if (sound4NSteps) rlm@1: sound4ShiftRight = 0x7f; rlm@1: else rlm@1: sound4ShiftRight = 0x7fff; rlm@1: } rlm@1: break; rlm@1: case NR50: rlm@1: soundVIN = data & 0x88; rlm@1: soundLevel1 = data & 7; rlm@1: soundLevel2 = (data >> 4) & 7; rlm@1: break; rlm@1: case NR51: rlm@1: soundBalance = (data & soundEnableFlag); rlm@1: gbMemory[address] = data; rlm@1: break; rlm@1: case NR52: rlm@1: soundMasterOn = data & 0x80; rlm@1: if (!(data & 0x80)) rlm@1: { rlm@1: sound1On = 0; rlm@1: sound2On = 0; rlm@1: sound3On = 0; rlm@1: sound4On = 0; rlm@1: } rlm@1: break; rlm@1: } rlm@1: rlm@1: gbDigitalSound = true; rlm@1: rlm@1: if (sound1On && sound1EnvelopeVolume != 0) rlm@1: gbDigitalSound = false; rlm@1: if (sound2On && sound2EnvelopeVolume != 0) rlm@1: gbDigitalSound = false; rlm@1: if (sound3On && sound3OutputLevel != 0) rlm@1: gbDigitalSound = false; rlm@1: if (sound4On && sound4EnvelopeVolume != 0) rlm@1: gbDigitalSound = false; rlm@1: } rlm@1: rlm@1: void gbSoundChannel1() rlm@1: { rlm@1: int vol = sound1EnvelopeVolume; rlm@1: rlm@1: int freq = 0; rlm@1: rlm@1: int value = 0; rlm@1: rlm@1: if (sound1On && (sound1ATL || !sound1Continue)) rlm@1: { rlm@1: sound1Index += soundQuality * sound1Skip; rlm@1: sound1Index &= 0x1fffffff; rlm@1: rlm@1: value = ((s8)sound1Wave[sound1Index >> 24]) * vol; rlm@1: } rlm@1: rlm@1: soundBuffer[0][soundIndex] = value; rlm@1: rlm@1: if (sound1On) rlm@1: { rlm@1: if (sound1ATL) rlm@1: { rlm@1: sound1ATL -= soundQuality; rlm@1: rlm@1: if (sound1ATL <= 0 && sound1Continue) rlm@1: { rlm@1: gbMemory[NR52] &= 0xfe; rlm@1: sound1On = 0; rlm@1: } rlm@1: } rlm@1: rlm@1: if (sound1EnvelopeATL) rlm@1: { rlm@1: sound1EnvelopeATL -= soundQuality; rlm@1: rlm@1: if (sound1EnvelopeATL <= 0) rlm@1: { rlm@1: if (sound1EnvelopeUpDown) rlm@1: { rlm@1: if (sound1EnvelopeVolume < 15) rlm@1: sound1EnvelopeVolume++; rlm@1: } rlm@1: else rlm@1: { rlm@1: if (sound1EnvelopeVolume) rlm@1: sound1EnvelopeVolume--; rlm@1: } rlm@1: rlm@1: sound1EnvelopeATL += sound1EnvelopeATLReload; rlm@1: } rlm@1: } rlm@1: rlm@1: if (sound1SweepATL) rlm@1: { rlm@1: sound1SweepATL -= soundQuality; rlm@1: rlm@1: if (sound1SweepATL <= 0) rlm@1: { rlm@1: freq = (((int)(gbMemory[NR14] & 7) << 8) | gbMemory[NR13]); rlm@1: rlm@1: int updown = 1; rlm@1: rlm@1: if (sound1SweepUpDown) rlm@1: updown = -1; rlm@1: rlm@1: int newfreq = 0; rlm@1: if (sound1SweepSteps) rlm@1: { rlm@1: newfreq = freq + updown * freq / (1 << sound1SweepSteps); rlm@1: if (newfreq == freq) rlm@1: newfreq = 0; rlm@1: } rlm@1: else rlm@1: newfreq = freq; rlm@1: rlm@1: if (newfreq < 0) rlm@1: { rlm@1: sound1SweepATL += sound1SweepATLReload; rlm@1: } rlm@1: else if (newfreq > 2047) rlm@1: { rlm@1: sound1SweepATL = 0; rlm@1: sound1On = 0; rlm@1: gbMemory[NR52] &= 0xfe; rlm@1: } rlm@1: else rlm@1: { rlm@1: sound1SweepATL += sound1SweepATLReload; rlm@1: sound1Skip = SOUND_MAGIC / (2048 - newfreq); rlm@1: rlm@1: gbMemory[NR13] = newfreq & 0xff; rlm@1: gbMemory[NR14] = (gbMemory[NR14] & 0xf8) | ((newfreq >> 8) & 7); rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSoundChannel2() rlm@1: { rlm@1: // int freq = 0; rlm@1: int vol = sound2EnvelopeVolume; rlm@1: rlm@1: int value = 0; rlm@1: rlm@1: if (sound2On && (sound2ATL || !sound2Continue)) rlm@1: { rlm@1: sound2Index += soundQuality * sound2Skip; rlm@1: sound2Index &= 0x1fffffff; rlm@1: rlm@1: value = ((s8)sound2Wave[sound2Index >> 24]) * vol; rlm@1: } rlm@1: rlm@1: soundBuffer[1][soundIndex] = value; rlm@1: rlm@1: if (sound2On) rlm@1: { rlm@1: if (sound2ATL) rlm@1: { rlm@1: sound2ATL -= soundQuality; rlm@1: rlm@1: if (sound2ATL <= 0 && sound2Continue) rlm@1: { rlm@1: gbMemory[NR52] &= 0xfd; rlm@1: sound2On = 0; rlm@1: } rlm@1: } rlm@1: rlm@1: if (sound2EnvelopeATL) rlm@1: { rlm@1: sound2EnvelopeATL -= soundQuality; rlm@1: rlm@1: if (sound2EnvelopeATL <= 0) rlm@1: { rlm@1: if (sound2EnvelopeUpDown) rlm@1: { rlm@1: if (sound2EnvelopeVolume < 15) rlm@1: sound2EnvelopeVolume++; rlm@1: } rlm@1: else rlm@1: { rlm@1: if (sound2EnvelopeVolume) rlm@1: sound2EnvelopeVolume--; rlm@1: } rlm@1: sound2EnvelopeATL += sound2EnvelopeATLReload; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSoundChannel3() rlm@1: { rlm@1: int value = sound3Last; rlm@1: rlm@1: if (sound3On && (sound3ATL || !sound3Continue)) rlm@1: { rlm@1: sound3Index += soundQuality * sound3Skip; rlm@1: sound3Index &= 0x1fffffff; rlm@1: rlm@1: value = gbMemory[0xff30 + (sound3Index >> 25)]; rlm@1: rlm@1: if ((sound3Index & 0x01000000)) rlm@1: { rlm@1: value &= 0x0f; rlm@1: } rlm@1: else rlm@1: { rlm@1: value >>= 4; rlm@1: } rlm@1: rlm@1: value -= 8; rlm@1: value *= 2; rlm@1: rlm@1: switch (sound3OutputLevel) rlm@1: { rlm@1: case 0: rlm@1: value = 0; rlm@1: break; rlm@1: case 1: rlm@1: break; rlm@1: case 2: rlm@1: value = (value >> 1); rlm@1: break; rlm@1: case 3: rlm@1: value = (value >> 2); rlm@1: break; rlm@1: } rlm@1: //value += 1; rlm@1: sound3Last = value; rlm@1: } rlm@1: rlm@1: soundBuffer[2][soundIndex] = value; rlm@1: rlm@1: if (sound3On) rlm@1: { rlm@1: if (sound3ATL) rlm@1: { rlm@1: sound3ATL -= soundQuality; rlm@1: rlm@1: if (sound3ATL <= 0 && sound3Continue) rlm@1: { rlm@1: gbMemory[NR52] &= 0xfb; rlm@1: sound3On = 0; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSoundChannel4() rlm@1: { rlm@1: int vol = sound4EnvelopeVolume; rlm@1: rlm@1: int value = 0; rlm@1: rlm@1: if (sound4Clock <= 0x0c) rlm@1: { rlm@1: if (sound4On && (sound4ATL || !sound4Continue)) rlm@1: { rlm@1: #define NOISE_ONE_SAMP_SCALE 0x200000 rlm@1: rlm@1: sound4Index += soundQuality * sound4Skip; rlm@1: sound4ShiftIndex += soundQuality * sound4ShiftSkip; rlm@1: rlm@1: if (sound4NSteps) rlm@1: { rlm@1: while (sound4ShiftIndex >= NOISE_ONE_SAMP_SCALE) rlm@1: { rlm@1: sound4ShiftRight = (((sound4ShiftRight << 6) ^ rlm@1: (sound4ShiftRight << 5)) & 0x40) | rlm@1: (sound4ShiftRight >> 1); rlm@1: sound4ShiftIndex -= NOISE_ONE_SAMP_SCALE; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: while (sound4ShiftIndex >= NOISE_ONE_SAMP_SCALE) rlm@1: { rlm@1: sound4ShiftRight = (((sound4ShiftRight << 14) ^ rlm@1: (sound4ShiftRight << 13)) & 0x4000) | rlm@1: (sound4ShiftRight >> 1); rlm@1: rlm@1: sound4ShiftIndex -= NOISE_ONE_SAMP_SCALE; rlm@1: } rlm@1: } rlm@1: rlm@1: sound4Index %= NOISE_ONE_SAMP_SCALE; rlm@1: sound4ShiftIndex %= NOISE_ONE_SAMP_SCALE; rlm@1: rlm@1: value = ((sound4ShiftRight & 1) * 2 - 1) * vol; rlm@1: } rlm@1: else rlm@1: { rlm@1: value = 0; rlm@1: } rlm@1: } rlm@1: rlm@1: soundBuffer[3][soundIndex] = value; rlm@1: rlm@1: if (sound4On) rlm@1: { rlm@1: if (sound4ATL) rlm@1: { rlm@1: sound4ATL -= soundQuality; rlm@1: rlm@1: if (sound4ATL <= 0 && sound4Continue) rlm@1: { rlm@1: gbMemory[NR52] &= 0xfd; rlm@1: sound4On = 0; rlm@1: } rlm@1: } rlm@1: rlm@1: if (sound4EnvelopeATL) rlm@1: { rlm@1: sound4EnvelopeATL -= soundQuality; rlm@1: rlm@1: if (sound4EnvelopeATL <= 0) rlm@1: { rlm@1: if (sound4EnvelopeUpDown) rlm@1: { rlm@1: if (sound4EnvelopeVolume < 15) rlm@1: sound4EnvelopeVolume++; rlm@1: } rlm@1: else rlm@1: { rlm@1: if (sound4EnvelopeVolume) rlm@1: sound4EnvelopeVolume--; rlm@1: } rlm@1: sound4EnvelopeATL += sound4EnvelopeATLReload; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSoundMix() rlm@1: { rlm@1: int res = 0; rlm@1: rlm@1: if (gbMemory) rlm@1: soundBalance = (gbMemory[NR51] & soundEnableFlag & ~soundMutedFlag); rlm@1: rlm@1: if (soundBalance & 16) rlm@1: { rlm@1: res += ((s8)soundBuffer[0][soundIndex]); rlm@1: } rlm@1: if (soundBalance & 32) rlm@1: { rlm@1: res += ((s8)soundBuffer[1][soundIndex]); rlm@1: } rlm@1: if (soundBalance & 64) rlm@1: { rlm@1: res += ((s8)soundBuffer[2][soundIndex]); rlm@1: } rlm@1: if (soundBalance & 128) rlm@1: { rlm@1: res += ((s8)soundBuffer[3][soundIndex]); rlm@1: } rlm@1: rlm@1: if (gbDigitalSound) rlm@1: res = soundLevel1 * 256; rlm@1: else rlm@1: res *= soundLevel1 * 60; rlm@1: rlm@1: if (soundEcho) rlm@1: { rlm@1: res *= 2; rlm@1: res += soundFilter[soundEchoIndex]; rlm@1: res /= 2; rlm@1: soundFilter[soundEchoIndex++] = res; rlm@1: } rlm@1: rlm@1: if (soundLowPass) rlm@1: { rlm@1: soundLeft[4] = soundLeft[3]; rlm@1: soundLeft[3] = soundLeft[2]; rlm@1: soundLeft[2] = soundLeft[1]; rlm@1: soundLeft[1] = soundLeft[0]; rlm@1: soundLeft[0] = res; rlm@1: res = (soundLeft[4] + 2 * soundLeft[3] + 8 * soundLeft[2] + 2 * soundLeft[1] + rlm@1: soundLeft[0]) / 14; rlm@1: } rlm@1: rlm@1: bool noSpecialEffects = false; rlm@1: #if (defined(WIN32) && !defined(SDL)) rlm@1: if (theApp.soundRecording || theApp.aviRecording || theApp.nvAudioLog) rlm@1: noSpecialEffects = true; rlm@1: #endif rlm@1: rlm@1: if (!noSpecialEffects) rlm@1: { rlm@1: switch (soundVolume) rlm@1: { rlm@1: case 0: rlm@1: case 1: rlm@1: case 2: rlm@1: case 3: rlm@1: res *= (soundVolume + 1); rlm@1: break; rlm@1: case 4: rlm@1: res >>= 2; rlm@1: break; rlm@1: case 5: rlm@1: res >>= 1; rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: if (res > 32767) rlm@1: res = 32767; rlm@1: if (res < -32768) rlm@1: res = -32768; rlm@1: rlm@1: if (soundReverse && !noSpecialEffects) rlm@1: { rlm@1: soundFinalWave[++soundBufferIndex] = res; rlm@1: if ((soundFrameSoundWritten + 1) >= countof(soundFrameSound)) rlm@525: rlm@525: ; //printf("oh noes!\n"); rlm@1: else rlm@1: soundFrameSound[++soundFrameSoundWritten] = res; rlm@1: } rlm@1: else rlm@1: { rlm@1: soundFinalWave[soundBufferIndex++] = res; rlm@1: if (soundFrameSoundWritten >= countof(soundFrameSound)) rlm@525: ; //printf("oh noes!\n"); rlm@1: else rlm@1: soundFrameSound[soundFrameSoundWritten++] = res; rlm@1: } rlm@1: rlm@1: res = 0; rlm@1: rlm@1: if (soundBalance & 1) rlm@1: { rlm@1: res += ((s8)soundBuffer[0][soundIndex]); rlm@1: } rlm@1: if (soundBalance & 2) rlm@1: { rlm@1: res += ((s8)soundBuffer[1][soundIndex]); rlm@1: } rlm@1: if (soundBalance & 4) rlm@1: { rlm@1: res += ((s8)soundBuffer[2][soundIndex]); rlm@1: } rlm@1: if (soundBalance & 8) rlm@1: { rlm@1: res += ((s8)soundBuffer[3][soundIndex]); rlm@1: } rlm@1: rlm@1: if (gbDigitalSound) rlm@1: res = soundLevel2 * 256; rlm@1: else rlm@1: res *= soundLevel2 * 60; rlm@1: rlm@1: if (soundEcho) rlm@1: { rlm@1: res *= 2; rlm@1: res += soundFilter[soundEchoIndex]; rlm@1: res /= 2; rlm@1: soundFilter[soundEchoIndex++] = res; rlm@1: rlm@1: if (soundEchoIndex >= 4000) rlm@1: soundEchoIndex = 0; rlm@1: } rlm@1: rlm@1: if (soundLowPass) rlm@1: { rlm@1: soundRight[4] = soundRight[3]; rlm@1: soundRight[3] = soundRight[2]; rlm@1: soundRight[2] = soundRight[1]; rlm@1: soundRight[1] = soundRight[0]; rlm@1: soundRight[0] = res; rlm@1: res = (soundRight[4] + 2 * soundRight[3] + 8 * soundRight[2] + 2 * soundRight[1] + rlm@1: soundRight[0]) / 14; rlm@1: } rlm@1: rlm@1: if (!noSpecialEffects) rlm@1: { rlm@1: switch (soundVolume) rlm@1: { rlm@1: case 0: rlm@1: case 1: rlm@1: case 2: rlm@1: case 3: rlm@1: res *= (soundVolume + 1); rlm@1: break; rlm@1: case 4: rlm@1: res >>= 2; rlm@1: break; rlm@1: case 5: rlm@1: res >>= 1; rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: if (res > 32767) rlm@1: res = 32767; rlm@1: if (res < -32768) rlm@1: res = -32768; rlm@1: rlm@1: if (soundReverse && !noSpecialEffects) rlm@1: { rlm@1: soundFinalWave[-1 + soundBufferIndex++] = res; rlm@1: if ((soundFrameSoundWritten) >= countof(soundFrameSound)) rlm@525: ;//printf("oh noes!\n"); rlm@1: else rlm@1: soundFrameSound[-1 + soundFrameSoundWritten++] = res; rlm@1: } rlm@1: else rlm@1: { rlm@1: soundFinalWave[soundBufferIndex++] = res; rlm@1: if ((soundFrameSoundWritten + 1) >= countof(soundFrameSound)) rlm@525: ;//printf("oh noes!\n"); rlm@1: else rlm@1: soundFrameSound[soundFrameSoundWritten++] = res; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSoundTick() rlm@1: { rlm@525: if (systemSoundOn) rlm@525: { rlm@525: if (soundMasterOn) rlm@1: { rlm@525: gbSoundChannel1(); rlm@525: gbSoundChannel2(); rlm@525: gbSoundChannel3(); rlm@525: gbSoundChannel4(); rlm@525: rlm@525: gbSoundMix(); rlm@525: } rlm@525: else rlm@525: { rlm@525: soundFinalWave[soundBufferIndex++] = 0; rlm@525: soundFinalWave[soundBufferIndex++] = 0; rlm@525: if ((soundFrameSoundWritten + 1) >= countof(soundFrameSound)) rlm@525: rlm@525: ;//printf("oh noes!\n"); rlm@525: else rlm@525: { rlm@525: soundFrameSound[soundFrameSoundWritten++] = 0; rlm@525: soundFrameSound[soundFrameSoundWritten++] = 0; rlm@525: } rlm@525: } rlm@525: rlm@525: soundIndex++; rlm@525: rlm@525: if (2 * soundBufferIndex >= soundBufferLen) rlm@525: { rlm@525: if (systemSoundOn) rlm@525: { rlm@525: if (soundPaused) rlm@1: { rlm@525: extern void soundResume(); rlm@525: soundResume(); rlm@1: } rlm@1: rlm@525: systemSoundWriteToBuffer(); rlm@525: } rlm@525: soundIndex = 0; rlm@525: soundBufferIndex = 0; rlm@1: } rlm@525: } rlm@1: } rlm@1: rlm@1: void gbSoundReset() rlm@1: { rlm@1: soundPaused = 1; rlm@1: soundPlay = 0; rlm@1: SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS; rlm@1: // soundTicks = SOUND_CLOCK_TICKS; rlm@1: soundTicks = 0; rlm@1: soundNextPosition = 0; rlm@1: soundMasterOn = 1; rlm@1: soundIndex = 0; rlm@1: soundBufferIndex = 0; rlm@1: soundLevel1 = 7; rlm@1: soundLevel2 = 7; rlm@1: soundVIN = 0; rlm@1: rlm@1: sound1On = 0; rlm@1: sound1ATL = 0; rlm@1: sound1Skip = 0; rlm@1: sound1Index = 0; rlm@1: sound1Continue = 0; rlm@1: sound1EnvelopeVolume = 0; rlm@1: sound1EnvelopeATL = 0; rlm@1: sound1EnvelopeUpDown = 0; rlm@1: sound1EnvelopeATLReload = 0; rlm@1: sound1SweepATL = 0; rlm@1: sound1SweepATLReload = 0; rlm@1: sound1SweepSteps = 0; rlm@1: sound1SweepUpDown = 0; rlm@1: sound1SweepStep = 0; rlm@1: sound1Wave = soundWavePattern[2]; rlm@1: rlm@1: sound2On = 0; rlm@1: sound2ATL = 0; rlm@1: sound2Skip = 0; rlm@1: sound2Index = 0; rlm@1: sound2Continue = 0; rlm@1: sound2EnvelopeVolume = 0; rlm@1: sound2EnvelopeATL = 0; rlm@1: sound2EnvelopeUpDown = 0; rlm@1: sound2EnvelopeATLReload = 0; rlm@1: sound2Wave = soundWavePattern[2]; rlm@1: rlm@1: sound3On = 0; rlm@1: sound3ATL = 0; rlm@1: sound3Skip = 0; rlm@1: sound3Index = 0; rlm@1: sound3Continue = 0; rlm@1: sound3OutputLevel = 0; rlm@1: rlm@1: sound4On = 0; rlm@1: sound4Clock = 0; rlm@1: sound4ATL = 0; rlm@1: sound4Skip = 0; rlm@1: sound4Index = 0; rlm@1: sound4ShiftRight = 0x7f; rlm@1: sound4NSteps = 0; rlm@1: sound4CountDown = 0; rlm@1: sound4Continue = 0; rlm@1: sound4EnvelopeVolume = 0; rlm@1: sound4EnvelopeATL = 0; rlm@1: sound4EnvelopeUpDown = 0; rlm@1: sound4EnvelopeATLReload = 0; rlm@1: rlm@1: // don't translate rlm@1: if (soundDebug) rlm@1: { rlm@1: log("*** Sound Init ***\n"); rlm@1: } rlm@1: rlm@1: gbSoundEvent(0xff10, 0x80); rlm@1: gbSoundEvent(0xff11, 0xbf); rlm@1: gbSoundEvent(0xff12, 0xf3); rlm@1: gbSoundEvent(0xff14, 0xbf); rlm@1: gbSoundEvent(0xff16, 0x3f); rlm@1: gbSoundEvent(0xff17, 0x00); rlm@1: gbSoundEvent(0xff19, 0xbf); rlm@1: rlm@1: gbSoundEvent(0xff1a, 0x7f); rlm@1: gbSoundEvent(0xff1b, 0xff); rlm@1: gbSoundEvent(0xff1c, 0xbf); rlm@1: gbSoundEvent(0xff1e, 0xbf); rlm@1: rlm@1: gbSoundEvent(0xff20, 0xff); rlm@1: gbSoundEvent(0xff21, 0x00); rlm@1: gbSoundEvent(0xff22, 0x00); rlm@1: gbSoundEvent(0xff23, 0xbf); rlm@1: gbSoundEvent(0xff24, 0x77); rlm@1: gbSoundEvent(0xff25, 0xf3); rlm@1: rlm@1: gbSoundEvent(0xff26, 0xf0); rlm@1: rlm@1: // don't translate rlm@1: if (soundDebug) rlm@1: { rlm@1: log("*** Sound Init Complete ***\n"); rlm@1: } rlm@1: rlm@1: sound1On = 0; rlm@1: sound2On = 0; rlm@1: sound3On = 0; rlm@1: sound4On = 0; rlm@1: rlm@1: int addr = 0xff30; rlm@1: rlm@1: while (addr < 0xff40) rlm@1: { rlm@1: gbMemory[addr++] = 0x00; rlm@1: gbMemory[addr++] = 0xff; rlm@1: } rlm@1: rlm@1: memset(soundFinalWave, 0x00, soundBufferLen); rlm@1: rlm@1: memset(soundFilter, 0, sizeof(soundFilter)); rlm@1: soundEchoIndex = 0; rlm@1: } rlm@1: rlm@1: extern bool soundInit(); rlm@1: extern void soundShutdown(); rlm@1: rlm@1: void gbSoundSetQuality(int quality) rlm@1: { rlm@1: if (soundQuality != quality && systemSoundCanChangeQuality()) rlm@1: { rlm@1: if (!soundOffFlag) rlm@1: soundShutdown(); rlm@1: soundQuality = quality; rlm@1: soundNextPosition = 0; rlm@1: if (!soundOffFlag) rlm@1: soundInit(); rlm@1: SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * GB_USE_TICKS_AS * soundQuality; rlm@1: soundIndex = 0; rlm@1: soundBufferIndex = 0; rlm@1: } rlm@1: else rlm@1: { rlm@1: soundNextPosition = 0; rlm@1: SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * GB_USE_TICKS_AS * soundQuality; rlm@1: soundIndex = 0; rlm@1: soundBufferIndex = 0; rlm@1: } rlm@1: } rlm@1: rlm@1: static int32 soundTicks_int32; rlm@1: static int32 SOUND_CLOCK_TICKS_int32; rlm@1: variable_desc gbSoundSaveStruct[] = { rlm@1: { &soundPaused, sizeof(int32) }, rlm@1: { &soundPlay, sizeof(int32) }, rlm@1: { &soundTicks_int32, sizeof(int32) }, rlm@1: { &SOUND_CLOCK_TICKS_int32, sizeof(int32) }, rlm@1: { &soundLevel1, sizeof(int32) }, rlm@1: { &soundLevel2, sizeof(int32) }, rlm@1: { &soundBalance, sizeof(int32) }, rlm@1: { &soundMasterOn, sizeof(int32) }, rlm@1: { &soundIndex, sizeof(int32) }, rlm@1: { &soundVIN, sizeof(int32) }, rlm@1: { &sound1On, sizeof(int32) }, rlm@1: { &sound1ATL, sizeof(int32) }, rlm@1: { &sound1Skip, sizeof(int32) }, rlm@1: { &sound1Index, sizeof(int32) }, rlm@1: { &sound1Continue, sizeof(int32) }, rlm@1: { &sound1EnvelopeVolume, sizeof(int32) }, rlm@1: { &sound1EnvelopeATL, sizeof(int32) }, rlm@1: { &sound1EnvelopeATLReload, sizeof(int32) }, rlm@1: { &sound1EnvelopeUpDown, sizeof(int32) }, rlm@1: { &sound1SweepATL, sizeof(int32) }, rlm@1: { &sound1SweepATLReload, sizeof(int32) }, rlm@1: { &sound1SweepSteps, sizeof(int32) }, rlm@1: { &sound1SweepUpDown, sizeof(int32) }, rlm@1: { &sound1SweepStep, sizeof(int32) }, rlm@1: { &sound2On, sizeof(int32) }, rlm@1: { &sound2ATL, sizeof(int32) }, rlm@1: { &sound2Skip, sizeof(int32) }, rlm@1: { &sound2Index, sizeof(int32) }, rlm@1: { &sound2Continue, sizeof(int32) }, rlm@1: { &sound2EnvelopeVolume, sizeof(int32) }, rlm@1: { &sound2EnvelopeATL, sizeof(int32) }, rlm@1: { &sound2EnvelopeATLReload, sizeof(int32) }, rlm@1: { &sound2EnvelopeUpDown, sizeof(int32) }, rlm@1: { &sound3On, sizeof(int32) }, rlm@1: { &sound3ATL, sizeof(int32) }, rlm@1: { &sound3Skip, sizeof(int32) }, rlm@1: { &sound3Index, sizeof(int32) }, rlm@1: { &sound3Continue, sizeof(int32) }, rlm@1: { &sound3OutputLevel, sizeof(int32) }, rlm@1: { &sound4On, sizeof(int32) }, rlm@1: { &sound4ATL, sizeof(int32) }, rlm@1: { &sound4Skip, sizeof(int32) }, rlm@1: { &sound4Index, sizeof(int32) }, rlm@1: { &sound4Clock, sizeof(int32) }, rlm@1: { &sound4ShiftRight, sizeof(int32) }, rlm@1: { &sound4ShiftSkip, sizeof(int32) }, rlm@1: { &sound4ShiftIndex, sizeof(int32) }, rlm@1: { &sound4NSteps, sizeof(int32) }, rlm@1: { &sound4CountDown, sizeof(int32) }, rlm@1: { &sound4Continue, sizeof(int32) }, rlm@1: { &sound4EnvelopeVolume, sizeof(int32) }, rlm@1: { &sound4EnvelopeATL, sizeof(int32) }, rlm@1: { &sound4EnvelopeATLReload, sizeof(int32) }, rlm@1: { &sound4EnvelopeUpDown, sizeof(int32) }, rlm@1: { &soundEnableFlag, sizeof(int32) }, rlm@1: { NULL, 0 } rlm@1: }; rlm@1: rlm@1: //variable_desc gbSoundSaveStructV2[] = { rlm@1: // { &soundTicks, sizeof(soundtick_t) }, rlm@1: // { &SOUND_CLOCK_TICKS, sizeof(soundtick_t) }, rlm@1: // { &GB_USE_TICKS_AS, sizeof(soundtick_t) }, rlm@1: // { NULL, 0 } rlm@1: //}; rlm@1: rlm@1: void gbSoundSaveGame(gzFile gzFile) rlm@1: { rlm@1: soundTicks_int32 = (int32) soundTicks; rlm@1: SOUND_CLOCK_TICKS_int32 = (int32) SOUND_CLOCK_TICKS; rlm@1: rlm@1: utilWriteData(gzFile, gbSoundSaveStruct); rlm@1: rlm@1: utilGzWrite(gzFile, soundBuffer, 4 * 735); rlm@1: utilGzWrite(gzFile, soundFinalWave, 2 * 735); rlm@1: utilGzWrite(gzFile, &soundQuality, sizeof(int32)); rlm@1: rlm@1: //utilWriteData(gzFile, gbSoundSaveStructV2); rlm@1: } rlm@1: rlm@1: void gbSoundReadGame(int version, gzFile gzFile) rlm@1: { rlm@1: int32 oldSoundPaused = soundPaused; rlm@1: int32 oldSoundEnableFlag = soundEnableFlag; rlm@1: utilReadData(gzFile, gbSoundSaveStruct); rlm@1: soundPaused = oldSoundPaused; rlm@1: soundEnableFlag = oldSoundEnableFlag; rlm@1: rlm@1: soundBufferIndex = soundIndex * 2; rlm@1: rlm@1: utilGzRead(gzFile, soundBuffer, 4 * 735); rlm@1: utilGzRead(gzFile, soundFinalWave, 2 * 735); rlm@1: rlm@1: if (version >= 7) rlm@1: { rlm@1: int quality = 1; rlm@1: utilGzRead(gzFile, &quality, sizeof(int32)); rlm@1: gbSoundSetQuality(quality); rlm@1: } rlm@1: else rlm@1: { rlm@1: soundQuality = -1; rlm@1: gbSoundSetQuality(1); rlm@1: } rlm@1: rlm@1: sound1Wave = soundWavePattern[gbMemory[NR11] >> 6]; rlm@1: sound2Wave = soundWavePattern[gbMemory[NR21] >> 6]; rlm@1: rlm@1: //if(version >= 14) { rlm@1: // utilReadData(gzFile, gbSoundSaveStructV2); rlm@1: //} rlm@1: //else { rlm@1: soundTicks = (soundtick_t) soundTicks_int32; rlm@1: SOUND_CLOCK_TICKS = (soundtick_t) SOUND_CLOCK_TICKS_int32; rlm@1: //} rlm@1: } rlm@1: