diff --git a/plugins/zerospu2/Linux/Alsa.cpp b/plugins/zerospu2/Linux/Alsa.cpp index d6f0b903ad..754b780924 100644 --- a/plugins/zerospu2/Linux/Alsa.cpp +++ b/plugins/zerospu2/Linux/Alsa.cpp @@ -34,18 +34,12 @@ int AlsaSetupSound() snd_pcm_hw_params_t *hwparams; snd_pcm_sw_params_t *swparams; snd_pcm_status_t *status; - unsigned int pspeed; - int pchannels; - snd_pcm_format_t format; - unsigned int buffer_time, period_time; + unsigned int pspeed = 48000; + int pchannels = 2; + snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; + unsigned int buffer_time = SOUNDSIZE; + unsigned int period_time= buffer_time / 4; int err; - - pchannels=2; - - pspeed = 48000; - format = SND_PCM_FORMAT_S16_LE; - buffer_time = SOUNDSIZE; - period_time = buffer_time / 4; err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if(err < 0) { diff --git a/plugins/zerospu2/zerospu2.cpp b/plugins/zerospu2/zerospu2.cpp index effafead0d..be57dd01ab 100644 --- a/plugins/zerospu2/zerospu2.cpp +++ b/plugins/zerospu2/zerospu2.cpp @@ -25,22 +25,22 @@ #include "SoundTouch/WavFile.h" // ADSR constants -#define ATTACK_MS 494L +#define ATTACK_MS 494L #define DECAYHALF_MS 286L -#define DECAY_MS 572L -#define SUSTAIN_MS 441L -#define RELEASE_MS 437L +#define DECAY_MS 572L +#define SUSTAIN_MS 441L +#define RELEASE_MS 437L #define AUDIO_BUFFER 2048 -#define NSSIZE 48 // ~ 1 ms of data -#define NSFRAMES 16 // gather at least NSFRAMES of NSSIZE before submitting +#define NSSIZE 48 // ~ 1 ms of data +#define NSFRAMES 16 // gather at least NSFRAMES of NSSIZE before submitting #define NSPACKETS 24 #ifdef _DEBUG -char *libraryName = "ZeroSPU2/PP (Debug)"; +char *libraryName = "ZeroSPU2/PP (Debug)"; #else -char *libraryName = "ZeroSPU2/PP "; +char *libraryName = "ZeroSPU2/PP "; #endif FILE *spu2Log; @@ -57,7 +57,7 @@ u16* spu2mem = NULL; u16* pSpuIrq[2] = {NULL}; u32 dwNewChannel2[2] = {0}; // keeps track of what channels that have been turned on u32 dwEndChannel2[2] = {0}; // keeps track of what channels have ended -unsigned long dwNoiseVal=1; // global noise generator +unsigned long dwNoiseVal=1; // global noise generator bool g_bPlaySound = true; // if true, will output sound, otherwise no static int iFMod[NSSIZE]; int s_buffers[NSSIZE][2]; // left and right buffers @@ -80,14 +80,14 @@ void* SPU2ThreadProc(void*); struct AUDIOBUFFER { - u8* pbuf; - u32 len; + u8* pbuf; + u32 len; - // 1 if new channels started in this packet - // Variable used to smooth out sound by concentrating on new voices - u32 timestamp; // in microseconds, only used for time stretching - u32 avgtime; - int newchannels; + // 1 if new channels started in this packet + // Variable used to smooth out sound by concentrating on new voices + u32 timestamp; // in microseconds, only used for time stretching + u32 avgtime; + int newchannels; }; static AUDIOBUFFER s_pAudioBuffers[NSPACKETS]; @@ -124,54 +124,34 @@ void (*irqCallbackDMA7)()=0; uptr g_pDMABaseAddr=0; const int f[5][2] = { - { 0, 0 }, - { 60, 0 }, - { 115, -52 }, - { 98, -55 }, - { 122, -60 } }; + { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } }; u32 RateTable[160]; - -// Atomic Operations -#if defined (_WIN32) - -#ifndef __x86_64__ -extern "C" LONG __cdecl _InterlockedExchangeAdd(LPLONG volatile Addend, LONG Value); -#endif - -#pragma intrinsic (_InterlockedExchangeAdd) -#define InterlockedExchangeAdd _InterlockedExchangeAdd - -#else - -typedef void* PVOID; - -__forceinline long InterlockedExchangeAdd(long volatile* Addend, long Value) -{ - __asm__ __volatile__(".intel_syntax\n" - "lock xadd [%0], %%eax\n" - ".att_syntax\n" : : "r"(Addend), "a"(Value) : "memory" ); -} - -#endif - // channels and voices VOICE_PROCESSED voices[SPU_NUMBER_VOICES+1]; // +1 for modulation -u32 CALLBACK PS2EgetLibType() { +u32 CALLBACK PS2EgetLibType() +{ return PS2E_LT_SPU2; } -char* CALLBACK PS2EgetLibName() { +char* CALLBACK PS2EgetLibName() +{ return libraryName; } -u32 CALLBACK PS2EgetLibVersion2(u32 type) { - return (SPU2_MINOR<<24)|(SPU2_VERSION<<16)|(SPU2_REVISION<<8)|SPU2_BUILD; +u32 CALLBACK PS2EgetLibVersion2(u32 type) +{ + return (SPU2_MINOR<<24) | (SPU2_VERSION<<16) | (SPU2_REVISION<<8) | SPU2_BUILD; } -void __Log(char *fmt, ...) { +void __Log(char *fmt, ...) +{ va_list list; if (!conf.Log || spu2Log == NULL) return; @@ -185,157 +165,163 @@ s32 CALLBACK SPU2init() { spu2Log = fopen("logs/spu2.txt", "w"); if (spu2Log) setvbuf(spu2Log, NULL, _IONBF, 0); + SPU2_LOG("Spu2 null version %d,%d\n",SPU2_REVISION,SPU2_BUILD); SPU2_LOG("SPU2init\n"); - + #ifdef _WIN32 - QueryPerformanceFrequency(&g_counterfreq); + QueryPerformanceFrequency(&g_counterfreq); #else - char strcurdir[256]; - getcwd(strcurdir, 256); - s_strIniPath = strcurdir; - s_strIniPath += "/inis/zerospu2.ini"; + char strcurdir[256]; + getcwd(strcurdir, 256); + s_strIniPath = strcurdir; + s_strIniPath += "/inis/zerospu2.ini"; #endif - spu2regs = (s8*)malloc(0x10000); - if (spu2regs == NULL) { + spu2regs = (s8*)malloc(0x10000); + spu2mem = (u16*)malloc(0x200000); // 2Mb + memset(spu2regs, 0, 0x10000); + memset(spu2mem, 0, 0x200000); + if ((spu2mem == NULL) || (spu2regs == NULL)) + { SysMessage("Error allocating Memory\n"); return -1; } - memset(spu2regs, 0, 0x10000); + + memset(dwEndChannel2, 0, sizeof(dwEndChannel2)); + memset(dwNewChannel2, 0, sizeof(dwNewChannel2)); + memset(iFMod, 0, sizeof(iFMod)); + memset(s_buffers, 0, sizeof(s_buffers)); - spu2mem = (u16*)malloc(0x200000); // 2Mb - if (spu2mem == NULL) { - SysMessage("Error allocating Memory\n"); return -1; + InitADSR(); + + memset(voices, 0, sizeof(voices)); + // last 24 channels have higher mem offset + for (int i = 0; i < 24; ++i) + voices[i+24].memoffset = 0x400; + + // init each channel + for (u32 i = 0; i < ARRAYSIZE(voices); ++i) { + voices[i].chanid = i; + voices[i].pLoop = voices[i].pStart = voices[i].pCurr = (u8*)spu2mem; + + voices[i].pvoice = (_SPU_VOICE*)((u8*)spu2regs+voices[i].memoffset)+(i%24); + voices[i].ADSRX.SustainLevel = 1024; // -> init sustain } - memset(spu2mem, 0, 0x200000); - memset(dwEndChannel2, 0, sizeof(dwEndChannel2)); - memset(dwNewChannel2, 0, sizeof(dwNewChannel2)); - memset(iFMod, 0, sizeof(iFMod)); - memset(s_buffers, 0, sizeof(s_buffers)); - - InitADSR(); - - memset(voices, 0, sizeof(voices)); - // last 24 channels have higher mem offset - for(int i = 0; i < 24; ++i) - voices[i+24].memoffset = 0x400; - - // init each channel - for(u32 i = 0; i < ARRAYSIZE(voices); ++i) { - - voices[i].chanid = i; - voices[i].pLoop = voices[i].pStart = voices[i].pCurr = (u8*)spu2mem; - - voices[i].pvoice = (_SPU_VOICE*)((u8*)spu2regs+voices[i].memoffset)+(i%24); - voices[i].ADSRX.SustainLevel = 1024; // -> init sustain - } return 0; } -s32 CALLBACK SPU2open(void *pDsp) { +s32 CALLBACK SPU2open(void *pDsp) +{ #ifdef _WIN32 - hWMain = pDsp == NULL ? NULL : *(HWND*)pDsp; - if(!IsWindow(hWMain)) - hWMain=GetActiveWindow(); + hWMain = pDsp == NULL ? NULL : *(HWND*)pDsp; + if (!IsWindow(hWMain)) + hWMain=GetActiveWindow(); #endif - LoadConfig(); + LoadConfig(); - SPUCycles = SPUWorkerCycles = 0; - interrupt = 0; - SPUStartCycle[0] = SPUStartCycle[1] = 0; - SPUTargetCycle[0] = SPUTargetCycle[1] = 0; - s_nDropPacket = 0; + SPUCycles = SPUWorkerCycles = 0; + interrupt = 0; + SPUStartCycle[0] = SPUStartCycle[1] = 0; + SPUTargetCycle[0] = SPUTargetCycle[1] = 0; + s_nDropPacket = 0; - if( conf.options & OPTION_TIMESTRETCH ) { - pSoundTouch = new soundtouch::SoundTouch(); - pSoundTouch->setSampleRate(48000); - pSoundTouch->setChannels(2); - pSoundTouch->setTempoChange(0); + if ( conf.options & OPTION_TIMESTRETCH ) + { + pSoundTouch = new soundtouch::SoundTouch(); + pSoundTouch->setSampleRate(48000); + pSoundTouch->setChannels(2); + pSoundTouch->setTempoChange(0); - pSoundTouch->setSetting(SETTING_USE_QUICKSEEK, 0); - pSoundTouch->setSetting(SETTING_USE_AA_FILTER, 1); - } + pSoundTouch->setSetting(SETTING_USE_QUICKSEEK, 0); + pSoundTouch->setSetting(SETTING_USE_AA_FILTER, 1); + } - //conf.Log = 1; + //conf.Log = 1; - g_bPlaySound = !(conf.options&OPTION_MUTE); + g_bPlaySound = !(conf.options&OPTION_MUTE); - if( g_bPlaySound && SetupSound() != 0 ) { - SysMessage("ZeroSPU2: Failed to initialize sound"); - g_bPlaySound = false; - } + if ( g_bPlaySound && SetupSound() != 0 ) + { + SysMessage("ZeroSPU2: Failed to initialize sound"); + g_bPlaySound = false; + } - if( g_bPlaySound ) { - // initialize the audio buffers - for(u32 i = 0; i < ARRAYSIZE(s_pAudioBuffers); ++i) { - s_pAudioBuffers[i].pbuf = (u8*)_aligned_malloc(4*NSSIZE*NSFRAMES, 16); // 4 bytes for each sample - s_pAudioBuffers[i].len = 0; - } + if ( g_bPlaySound ) { + // initialize the audio buffers + for (u32 i = 0; i < ARRAYSIZE(s_pAudioBuffers); ++i) + { + s_pAudioBuffers[i].pbuf = (u8*)_aligned_malloc(4*NSSIZE*NSFRAMES, 16); // 4 bytes for each sample + s_pAudioBuffers[i].len = 0; + } - s_nCurBuffer = 0; - s_nQueuedBuffers = 0; - s_pCurOutput = (s16*)s_pAudioBuffers[0].pbuf; - assert( s_pCurOutput != NULL); - - for(int i = 0; i < ARRAYSIZE(s_nDurations); ++i) { - s_nDurations[i] = NSFRAMES*1000; - } - s_nTotalDuration = ARRAYSIZE(s_nDurations)*NSFRAMES*1000; - s_nCurDuration = 0; - - // launch the thread - s_bThreadExit = false; + s_nCurBuffer = 0; + s_nQueuedBuffers = 0; + s_pCurOutput = (s16*)s_pAudioBuffers[0].pbuf; + assert( s_pCurOutput != NULL); + + for (int i = 0; i < ARRAYSIZE(s_nDurations); ++i) + { + s_nDurations[i] = NSFRAMES*1000; + } + s_nTotalDuration = ARRAYSIZE(s_nDurations)*NSFRAMES*1000; + s_nCurDuration = 0; + + // launch the thread + s_bThreadExit = false; #ifdef _WIN32 - s_threadSPU2 = CreateThread(NULL, 0, SPU2ThreadProc, NULL, 0, NULL); - if( s_threadSPU2 == NULL ) { - return -1; - } + s_threadSPU2 = CreateThread(NULL, 0, SPU2ThreadProc, NULL, 0, NULL); + if ( s_threadSPU2 == NULL ) + { + return -1; + } #else - if( pthread_create(&s_threadSPU2, NULL, SPU2ThreadProc, NULL) != 0 ) { - SysMessage("ZeroSPU2: Failed to create spu2thread\n"); - return -1; - } + if ( pthread_create(&s_threadSPU2, NULL, SPU2ThreadProc, NULL) != 0 ) + { + SysMessage("ZeroSPU2: Failed to create spu2thread\n"); + return -1; + } #endif - } + } - g_nSpuInit = 1; - return 0; + g_nSpuInit = 1; + return 0; } void CALLBACK SPU2close() { - g_nSpuInit = 0; + g_nSpuInit = 0; - if( g_bPlaySound && !s_bThreadExit ) { - s_bThreadExit = true; - printf("ZeroSPU2: Waiting for thread... "); + if ( g_bPlaySound && !s_bThreadExit ) { + s_bThreadExit = true; + printf("ZeroSPU2: Waiting for thread... "); #ifdef _WIN32 - WaitForSingleObject(s_threadSPU2, INFINITE); - CloseHandle(s_threadSPU2); s_threadSPU2 = NULL; + WaitForSingleObject(s_threadSPU2, INFINITE); + CloseHandle(s_threadSPU2); s_threadSPU2 = NULL; #else - pthread_join(s_threadSPU2, NULL); + pthread_join(s_threadSPU2, NULL); #endif - printf("done\n"); - } + printf("done\n"); + } - RemoveSound(); + RemoveSound(); - delete g_pWavRecord; g_pWavRecord = NULL; - delete pSoundTouch; pSoundTouch = NULL; - - for(u32 i = 0; i < ARRAYSIZE(s_pAudioBuffers); ++i) { - _aligned_free(s_pAudioBuffers[i].pbuf); - } - memset(s_pAudioBuffers, 0, sizeof(s_pAudioBuffers)); + delete g_pWavRecord; g_pWavRecord = NULL; + delete pSoundTouch; pSoundTouch = NULL; + + for (u32 i = 0; i < ARRAYSIZE(s_pAudioBuffers); ++i) + { + _aligned_free(s_pAudioBuffers[i].pbuf); + } + memset(s_pAudioBuffers, 0, sizeof(s_pAudioBuffers)); } void CALLBACK SPU2shutdown() { - free(spu2regs); spu2regs = NULL; - free(spu2mem); spu2mem = NULL; + free(spu2regs); spu2regs = NULL; + free(spu2mem); spu2mem = NULL; - if (spu2Log) fclose(spu2Log); + if (spu2Log) fclose(spu2Log); } // simulate SPU2 for 1ms @@ -345,521 +331,536 @@ void SPU2Worker(); void CALLBACK SPU2async(u32 cycle) { - SPUCycles += cycle; - if(interrupt & (1<<2)){ - if(SPUCycles - SPUStartCycle[1] >= SPUTargetCycle[1]){ + SPUCycles += cycle; + + if (interrupt & (1<<2)) + { + if (SPUCycles - SPUStartCycle[1] >= SPUTargetCycle[1]) + { interrupt &= ~(1<<2); irqCallbackDMA7(); } } - if(interrupt & (1<<1)){ - if(SPUCycles - SPUStartCycle[0] >= SPUTargetCycle[0]){ + if (interrupt & (1<<1)) + { + if (SPUCycles - SPUStartCycle[0] >= SPUTargetCycle[0]) + { interrupt &= ~(1<<1); irqCallbackDMA4(); } } - if( g_nSpuInit ) { - while( SPUCycles-SPUWorkerCycles > 0 && CYCLES_PER_MS < SPUCycles-SPUWorkerCycles ) { - SPU2Worker(); - SPUWorkerCycles += CYCLES_PER_MS; - } - } - else SPUWorkerCycles = SPUCycles; + if ( g_nSpuInit ) + { + while( SPUCycles-SPUWorkerCycles > 0 && CYCLES_PER_MS < SPUCycles-SPUWorkerCycles ) + { + SPU2Worker(); + SPUWorkerCycles += CYCLES_PER_MS; + } + } + else + SPUWorkerCycles = SPUCycles; } -void InitADSR() // INIT ADSR +void InitADSR() // INIT ADSR { - unsigned long r,rs,rd; - int i; - memset(RateTable,0,sizeof(unsigned long)*160); // build the rate table according to Neill's rules (see at bottom of file) + unsigned long r,rs,rd; + int i; + memset(RateTable,0,sizeof(unsigned long)*160); // build the rate table according to Neill's rules (see at bottom of file) - r=3;rs=1;rd=0; + r=3;rs=1;rd=0; - for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0 - { - if(r<0x3FFFFFFF) - { - r+=rs; - rd++; - if(rd==5) {rd=1;rs*=2;} - } - if(r>0x3FFFFFFF) r=0x3FFFFFFF; - - RateTable[i]=r; - } + for (i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0 + { + if (r<0x3FFFFFFF) + { + r+=rs; + rd++; + + if (rd==5) + { + rd=1; + rs*=2; + } + } + + if (r>0x3FFFFFFF) r=0x3FFFFFFF; + RateTable[i]=r; + } } -int MixADSR(VOICE_PROCESSED* pvoice) // MIX ADSR -{ - if(pvoice->bStop) // should be stopped: - { - if(pvoice->bIgnoreLoop==0){ - pvoice->ADSRX.EnvelopeVol=0; - pvoice->bOn=false; - pvoice->pStart= (u8*)(spu2mem+pvoice->iStartAddr); - pvoice->pLoop= (u8*)(spu2mem+pvoice->iStartAddr); - pvoice->pCurr= (u8*)(spu2mem+pvoice->iStartAddr); - pvoice->bStop=true; - pvoice->bIgnoreLoop=false; - return 0; - } - if(pvoice->ADSRX.ReleaseModeExp)// do release - { - switch((pvoice->ADSRX.EnvelopeVol>>28)&0x7) - { - case 0: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break; - case 1: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break; - case 2: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break; - case 3: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break; - case 4: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break; - case 5: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break; - case 6: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break; - case 7: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break; - } - } - else - { - pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x0C + 32]; - } +int MixADSR(VOICE_PROCESSED* pvoice) // MIX ADSR +{ + u32 rateadd[8] = { 0, 4, 6, 8, 9, 10, 11, 12 }; + + if (pvoice->bStop) // should be stopped: + { + if (pvoice->bIgnoreLoop == 0) + { + pvoice->ADSRX.EnvelopeVol=0; + pvoice->bOn=false; + pvoice->pStart= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->pLoop= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->pCurr= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->bStop=true; + pvoice->bIgnoreLoop=false; + return 0; + } + + if (pvoice->ADSRX.ReleaseModeExp) // do release + { + s32 temp = ((pvoice->ADSRX.EnvelopeVol>>28)&0x7); + pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 + rateadd[temp] + 32]; + } + else + { + pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x0C + 32]; + } - if(pvoice->ADSRX.EnvelopeVol<0) - { - pvoice->ADSRX.EnvelopeVol=0; - pvoice->bOn=false; - pvoice->pStart= (u8*)(spu2mem+pvoice->iStartAddr); - pvoice->pLoop= (u8*)(spu2mem+pvoice->iStartAddr); - pvoice->pCurr= (u8*)(spu2mem+pvoice->iStartAddr); - pvoice->bStop=true; - pvoice->bIgnoreLoop=false; - //pvoice->bReverb=0; - //pvoice->bNoise=0; - } + if (pvoice->ADSRX.EnvelopeVol<0) + { + pvoice->ADSRX.EnvelopeVol=0; + pvoice->bOn=false; + pvoice->pStart= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->pLoop= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->pCurr= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->bStop = true; + pvoice->bIgnoreLoop = false; + //pvoice->bReverb=0; + //pvoice->bNoise=0; + } - pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; - pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; - return pvoice->ADSRX.lVolume; - } - else // not stopped yet? - { - if(pvoice->ADSRX.State==0) // -> attack - { - if(pvoice->ADSRX.AttackModeExp) - { - if(pvoice->ADSRX.EnvelopeVol<0x60000000) - pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.AttackRate^0x7F)-0x10 + 32]; - else - pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.AttackRate^0x7F)-0x18 + 32]; - } - else - { - pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.AttackRate^0x7F)-0x10 + 32]; - } + pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; + + return pvoice->ADSRX.lVolume; + } + else // not stopped yet? + { + if (pvoice->ADSRX.State==0) // -> attack + { + if (pvoice->ADSRX.AttackModeExp) + { + if (pvoice->ADSRX.EnvelopeVol<0x60000000) + pvoice->ADSRX.EnvelopeVol += RateTable[(pvoice->ADSRX.AttackRate^0x7F) - 0x10 + 32]; + else + pvoice->ADSRX.EnvelopeVol += RateTable[(pvoice->ADSRX.AttackRate^0x7F) - 0x18 + 32]; + } + else + { + pvoice->ADSRX.EnvelopeVol += RateTable[(pvoice->ADSRX.AttackRate^0x7F) - 0x10 + 32]; + } - if(pvoice->ADSRX.EnvelopeVol<0) - { - pvoice->ADSRX.EnvelopeVol=0x7FFFFFFF; - pvoice->ADSRX.State=1; - } + if (pvoice->ADSRX.EnvelopeVol<0) + { + pvoice->ADSRX.EnvelopeVol=0x7FFFFFFF; + pvoice->ADSRX.State=1; + } - pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; - return pvoice->ADSRX.lVolume; - } - //--------------------------------------------------// - if(pvoice->ADSRX.State==1) // -> decay - { - switch((pvoice->ADSRX.EnvelopeVol>>28)&0x7) - { - // Note: Simplify - case 0: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break; - case 1: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break; - case 2: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break; - case 3: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break; - case 4: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break; - case 5: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break; - case 6: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break; - case 7: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break; - } + pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; + return pvoice->ADSRX.lVolume; + } + //--------------------------------------------------// + if (pvoice->ADSRX.State==1) // -> decay + { + s32 temp = ((pvoice->ADSRX.EnvelopeVol>>28)&0x7); + + pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 + rateadd[temp] + 32]; - if(pvoice->ADSRX.EnvelopeVol<0) - pvoice->ADSRX.EnvelopeVol=0; - if(((pvoice->ADSRX.EnvelopeVol>>27)&0xF) <= pvoice->ADSRX.SustainLevel) - pvoice->ADSRX.State=2; + if (pvoice->ADSRX.EnvelopeVol<0) + pvoice->ADSRX.EnvelopeVol=0; + if (((pvoice->ADSRX.EnvelopeVol>>27)&0xF) <= pvoice->ADSRX.SustainLevel) + pvoice->ADSRX.State=2; - pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; - return pvoice->ADSRX.lVolume; - } - //--------------------------------------------------// - if(pvoice->ADSRX.State==2) // -> sustain - { - if(pvoice->ADSRX.SustainIncrease) - { - if(pvoice->ADSRX.SustainModeExp) - { - if(pvoice->ADSRX.EnvelopeVol<0x60000000) - pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.SustainRate^0x7F)-0x10 + 32]; - else - pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.SustainRate^0x7F)-0x18 + 32]; - } - else - { - pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.SustainRate^0x7F)-0x10 + 32]; - } + pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; + return pvoice->ADSRX.lVolume; + } + //--------------------------------------------------// + if (pvoice->ADSRX.State==2) // -> sustain + { + if (pvoice->ADSRX.SustainIncrease) + { + if (pvoice->ADSRX.SustainModeExp) + { + if (pvoice->ADSRX.EnvelopeVol<0x60000000) + pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.SustainRate^0x7F)-0x10 + 32]; + else + pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.SustainRate^0x7F)-0x18 + 32]; + } + else + { + pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.SustainRate^0x7F)-0x10 + 32]; + } - if(pvoice->ADSRX.EnvelopeVol<0) - { - pvoice->ADSRX.EnvelopeVol=0x7FFFFFFF; - } - } - else - { - if(pvoice->ADSRX.SustainModeExp) - { - switch((pvoice->ADSRX.EnvelopeVol>>28)&0x7) - { - // Note: Simplify - case 0: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break; - case 1: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break; - case 2: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break; - case 3: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break; - case 4: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break; - case 5: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break; - case 6: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break; - case 7: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break; - } - } - else - { - pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x0F + 32]; - } + if (pvoice->ADSRX.EnvelopeVol<0) + { + pvoice->ADSRX.EnvelopeVol=0x7FFFFFFF; + } + } + else + { + if (pvoice->ADSRX.SustainModeExp) + { + s32 temp = ((pvoice->ADSRX.EnvelopeVol>>28)&0x7); + + pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 + rateadd[temp] + 32]; + } + else + { + pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x0F + 32]; + } - if(pvoice->ADSRX.EnvelopeVol<0) - { - pvoice->ADSRX.EnvelopeVol=0; - } - } - pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; - return pvoice->ADSRX.lVolume; - } - } - return 0; + if (pvoice->ADSRX.EnvelopeVol<0) + { + pvoice->ADSRX.EnvelopeVol=0; + } + } + pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; + return pvoice->ADSRX.lVolume; + } + } + return 0; } // simulate SPU2 for 1ms void SPU2Worker() { - int s_1,s_2,fa; - u8* start; - unsigned int nSample; - int ch,predict_nr,shift_factor,flags,d,s; + int s_1,s_2,fa; + u8* start; + unsigned int nSample; + int ch,predict_nr,shift_factor,flags,d,s; - // assume s_buffers are zeroed out - if( dwNewChannel2[0] || dwNewChannel2[1] ) - s_pAudioBuffers[s_nCurBuffer].newchannels++; - - VOICE_PROCESSED* pChannel=voices; - for(ch=0;chbNew) { - pChannel->StartSound(); // start new sound - dwEndChannel2[ch/24]&=~(1<<(ch%24)); // clear end channel bit - dwNewChannel2[ch/24]&=~(1<<(ch%24)); // clear channel bit - } + // assume s_buffers are zeroed out + if ( dwNewChannel2[0] || dwNewChannel2[1] ) + s_pAudioBuffers[s_nCurBuffer].newchannels++; + + VOICE_PROCESSED* pChannel=voices; + for (ch=0;chbNew) + { + pChannel->StartSound(); // start new sound + dwEndChannel2[ch/24]&=~(1<<(ch%24)); // clear end channel bit + dwNewChannel2[ch/24]&=~(1<<(ch%24)); // clear channel bit + } - if(!pChannel->bOn) - continue; + if (!pChannel->bOn) continue; - if(pChannel->iActFreq!=pChannel->iUsedFreq) // new psx frequency? - pChannel->VoiceChangeFrequency(); + if (pChannel->iActFreq!=pChannel->iUsedFreq) // new psx frequency? + pChannel->VoiceChangeFrequency(); - // loop until 1 ms of data is reached - int ns = 0; - while(nsbFMod==1 && iFMod[ns]) // fmod freq channel - pChannel->FModChangeFrequency(ns); + // loop until 1 ms of data is reached + int ns = 0; + + while(nsbFMod==1 && iFMod[ns]) // fmod freq channel + pChannel->FModChangeFrequency(ns); - while(pChannel->spos >= 0x10000 ) - { - if(pChannel->iSBPos==28) // 28 reached? - { - start=pChannel->pCurr; // set up the current pos + while(pChannel->spos >= 0x10000 ) + { + if (pChannel->iSBPos == 28) // 28 reached? + { + start=pChannel->pCurr; // set up the current pos - // special "stop" sign - if( start == (u8*)-1 ) //!pChannel->bOn - { - pChannel->bOn=false; // -> turn everything off - pChannel->ADSRX.lVolume=0; - pChannel->ADSRX.EnvelopeVol=0; - goto ENDX; // -> and done for this channel - } + // special "stop" sign - fixme - an *unsigned* -1? + if (start == (u8*)-1) //!pChannel->bOn + { + pChannel->bOn=false; // -> turn everything off + pChannel->ADSRX.lVolume=0; + pChannel->ADSRX.EnvelopeVol=0; + goto ENDX; // -> and done for this channel + } - pChannel->iSBPos=0; + pChannel->iSBPos=0; - // decode the 16byte packet - s_1=pChannel->s_1; - s_2=pChannel->s_2; + // decode the 16byte packet + s_1=pChannel->s_1; + s_2=pChannel->s_2; - predict_nr=(int)start[0]; - shift_factor=predict_nr&0xf; - predict_nr >>= 4; - flags=(int)start[1]; - start += 2; + predict_nr=(int)start[0]; + shift_factor=predict_nr&0xf; + predict_nr >>= 4; + flags=(int)start[1]; + start += 2; - for(nSample=0;nSample<28; ++start) - { - d=(int)*start; - s=((d&0xf)<<12); - if(s&0x8000) s|=0xffff0000; + for (nSample=0;nSample<28; ++start) + { + d = (int)*start; + s = ((d&0xf)<<12); + if (s&0x8000) s|=0xffff0000; - fa=(s >> shift_factor); - fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); - s_2=s_1;s_1=fa; - s=((d & 0xf0) << 8); + fa = (s >> shift_factor); + fa += ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2 = s_1; + s_1 = fa; + s = ((d & 0xf0) << 8); - pChannel->SB[nSample++]=fa; + pChannel->SB[nSample++]=fa; - if(s&0x8000) s|=0xffff0000; - fa=(s>>shift_factor); - fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); - s_2=s_1;s_1=fa; + if (s&0x8000) s|=0xffff0000; + fa = (s>>shift_factor); + fa += ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2 = s_1; + s_1 = fa; - pChannel->SB[nSample++]=fa; - } - - // irq occurs no matter what core access the address - for(int core = 0; core < 2; ++core) { - if(((SPU_CONTROL_*)(spu2regs+0x400*core+REG_C0_CTRL))->irq) // some callback and irq active? - { - // if irq address reached or irq on looping addr, when stop/loop flag is set - u8* pirq = (u8*)pSpuIrq[core]; - if( (pirq > start-16 && pirq <= start) - || ((flags&1) && (pirq > pChannel->pLoop-16 && pirq <= pChannel->pLoop))) - { - IRQINFO |= 4<SB[nSample++]=fa; + } + + // irq occurs no matter what core access the address + for (int core = 0; core < 2; ++core) + { + if (((SPU_CONTROL_*)(spu2regs+0x400*core+REG_C0_CTRL))->irq) // some callback and irq active? + { + // if irq address reached or irq on looping addr, when stop/loop flag is set + u8* pirq = (u8*)pSpuIrq[core]; + if ((pirq > start-16 && pirq <= start) || ((flags&1) && (pirq > pChannel->pLoop-16 && pirq <= pChannel->pLoop))) + { + IRQINFO |= 4<bIgnoreLoop)) - pChannel->pLoop=start-16; // loop adress + // flag handler + if ((flags&4) && (!pChannel->bIgnoreLoop)) + pChannel->pLoop=start-16; // loop adress - if(flags&1) // 1: stop/loop - { - // We play this block out first... - dwEndChannel2[ch/24]|=(1<<(ch%24)); - - if(flags!=3 || pChannel->pLoop==NULL) - { // and checking if pLoop is set avoids crashes, yeah - start = (u8*)-1; - pChannel->bStop = true; - pChannel->bIgnoreLoop = false; - } - else - { - start = pChannel->pLoop; - } - } + if (flags&1) // 1: stop/loop + { + // We play this block out first... + dwEndChannel2[ch/24]|=(1<<(ch%24)); + + if (flags!=3 || pChannel->pLoop==NULL) + { // and checking if pLoop is set avoids crashes, yeah + start = (u8*)-1; + pChannel->bStop = true; + pChannel->bIgnoreLoop = false; + } + else + { + start = pChannel->pLoop; + } + } - pChannel->pCurr=start; // store values for next cycle - pChannel->s_1=s_1; - pChannel->s_2=s_2; - } + pChannel->pCurr=start; // store values for next cycle + pChannel->s_1=s_1; + pChannel->s_2=s_2; + } - fa=pChannel->SB[pChannel->iSBPos++]; // get sample data - pChannel->StoreInterpolationVal(fa); - pChannel->spos -= 0x10000; - } + fa=pChannel->SB[pChannel->iSBPos++]; // get sample data + pChannel->StoreInterpolationVal(fa); + pChannel->spos -= 0x10000; + } - if(pChannel->bNoise) - fa=pChannel->iGetNoiseVal(); // get noise val - else - fa=pChannel->iGetInterpolationVal(); // get sample val + if (pChannel->bNoise) + fa=pChannel->iGetNoiseVal(); // get noise val + else + fa=pChannel->iGetInterpolationVal(); // get sample val - int sval = (MixADSR(pChannel)*fa)/1023; // mix adsr + int sval = (MixADSR(pChannel)*fa)/1023; // mix adsr - if(pChannel->bFMod==2) // fmod freq channel - { - iFMod[ns]=sval; // -> store 1T sample data, use that to do fmod on next channel - } - else { - if(pChannel->bVolumeL) - s_buffers[ns][0]+=(sval*pChannel->leftvol)>>14; - - if(pChannel->bVolumeR) - s_buffers[ns][1]+=(sval*pChannel->rightvol)>>14; - } + if (pChannel->bFMod==2) // fmod freq channel + { + iFMod[ns]=sval; // -> store 1T sample data, use that to do fmod on next channel + } + else + { + if (pChannel->bVolumeL) + s_buffers[ns][0]+=(sval*pChannel->leftvol)>>14; + + if (pChannel->bVolumeR) + s_buffers[ns][1]+=(sval*pChannel->rightvol)>>14; + } - // go to the next packet - ns++; - pChannel->spos += pChannel->sinc; - } + // go to the next packet + ns++; + pChannel->spos += pChannel->sinc; + } ENDX: - ; - } + ; + } - // mix all channels - if( (spu2Ru16(REG_C0_MMIX) & 0xF0) && (spu2Ru16(REG_C0_ADMAS) & 0x1) /*&& !(spu2Ru16(REG_C0_CTRL) & 0x30)*/) { - for(int ns=0;ns>16; - if((spu2Ru16(REG_C0_MMIX) & 0x40)) s_buffers[ns][1] += (((short*)spu2mem)[0x2200+Adma4.Index]*(int)spu2Ru16(REG_C0_BVOLR))>>16; + // mix all channels + if ((spu2Ru16(REG_C0_MMIX) & 0xF0) && (spu2Ru16(REG_C0_ADMAS) & 0x1) /*&& !(spu2Ru16(REG_C0_CTRL) & 0x30)*/) + { + for (int ns=0;ns>16; + if ((spu2Ru16(REG_C0_MMIX) & 0x40)) + s_buffers[ns][1] += (((short*)spu2mem)[0x2200+Adma4.Index]*(int)spu2Ru16(REG_C0_BVOLR))>>16; - Adma4.Index +=1; - // just add after every sample, it is better than adding 1024 all at once (games like Genji don't like it) - MemAddr[0] += 4; + Adma4.Index +=1; + // just add after every sample, it is better than adding 1024 all at once (games like Genji don't like it) + MemAddr[0] += 4; - if(Adma4.Index == 128 || Adma4.Index == 384) - { - if(ADMAS4Write()) - { - if(interrupt & 0x2){ + if (Adma4.Index == 128 || Adma4.Index == 384) + { + if (ADMAS4Write()) + { + if (interrupt & 0x2) + { interrupt &= ~0x2; printf("Stopping double interrupt DMA4\n"); } - irqCallbackDMA4(); + irqCallbackDMA4(); - } - } - - if(Adma4.Index == 512) { - if( Adma4.Enabled == 2 ) { - Adma4.Enabled = 0; - } - Adma4.Index = 0; - } - } + } + } + + if (Adma4.Index == 512) + { + if ( Adma4.Enabled == 2 ) + { + Adma4.Enabled = 0; + } + Adma4.Index = 0; + } + } + } - } + if ((spu2Ru16(REG_C1_MMIX) & 0xF0) && (spu2Ru16(REG_C1_ADMAS) & 0x2)) + { - if( (spu2Ru16(REG_C1_MMIX) & 0xF0) && (spu2Ru16(REG_C1_ADMAS) & 0x2)) { - - for(int ns=0;ns>16; - if((spu2Ru16(REG_C1_MMIX) & 0x40)) - s_buffers[ns][1] += (((short*)spu2mem)[0x2600+Adma7.Index]*(int)spu2Ru16(REG_C1_BVOLR))>>16; - - Adma7.Index +=1; - MemAddr[1] += 4; - - if(Adma7.Index == 128 || Adma7.Index == 384) - { - if(ADMAS7Write()) - { - if(interrupt & 0x4){ + for (int ns=0;ns>16; + if ((spu2Ru16(REG_C1_MMIX) & 0x40)) + s_buffers[ns][1] += (((short*)spu2mem)[0x2600+Adma7.Index]*(int)spu2Ru16(REG_C1_BVOLR))>>16; + + Adma7.Index +=1; + MemAddr[1] += 4; + + if (Adma7.Index == 128 || Adma7.Index == 384) + { + if (ADMAS7Write()) + { + if (interrupt & 0x4) + { interrupt &= ~0x4; printf("Stopping double interrupt DMA7\n"); } - irqCallbackDMA7(); + irqCallbackDMA7(); - } - Adma7.Enabled = 2; - } + } + Adma7.Enabled = 2; + } - if(Adma7.Index == 512) { - if( Adma7.Enabled == 2 ) - Adma7.Enabled = 0; - Adma7.Index = 0; - } - } - } + if (Adma7.Index == 512) + { + if ( Adma7.Enabled == 2 ) Adma7.Enabled = 0; + Adma7.Index = 0; + } + } + } - if( g_bPlaySound ) { + if ( g_bPlaySound ) + { + assert( s_pCurOutput != NULL); - assert( s_pCurOutput != NULL); + for (int ns=0;ns 32767 ) + s_pCurOutput[0] = 32767; + else + s_pCurOutput[0] = (s16)s_buffers[ns][0]; + + if ( s_buffers[ns][1] < -32767 ) + s_pCurOutput[1] = -32767; + else if ( s_buffers[ns][1] > 32767 ) + s_pCurOutput[1] = 32767; + else + s_pCurOutput[1] = (s16)s_buffers[ns][1]; + + s_pCurOutput += 2; + s_buffers[ns][0] = 0; + s_buffers[ns][1] = 0; + } + // check if end reached - for(int ns=0;ns 32767 ) s_pCurOutput[0] = 32767; - else s_pCurOutput[0] = (s16)s_buffers[ns][0]; - - if( s_buffers[ns][1] < -32767 ) s_pCurOutput[1] = -32767; - else if( s_buffers[ns][1] > 32767 ) s_pCurOutput[1] = 32767; - else s_pCurOutput[1] = (s16)s_buffers[ns][1]; - s_pCurOutput += 2; + if ((uptr)s_pCurOutput - (uptr)s_pAudioBuffers[s_nCurBuffer].pbuf >= 4 * NSSIZE * NSFRAMES) + { - - s_buffers[ns][0] = 0; - s_buffers[ns][1] = 0; - } - // check if end reached + if ( conf.options & OPTION_RECORDING ) + { + static int lastrectime=0; + if (timeGetTime() - lastrectime > 5000) + { + printf("ZeroSPU2: recording\n"); + lastrectime = timeGetTime(); + } + LogRawSound(s_pAudioBuffers[s_nCurBuffer].pbuf, 4, s_pAudioBuffers[s_nCurBuffer].pbuf+2, 4, NSSIZE*NSFRAMES); + } - if( (uptr)s_pCurOutput - (uptr)s_pAudioBuffers[s_nCurBuffer].pbuf >= 4 * NSSIZE * NSFRAMES ) { - - if( conf.options & OPTION_RECORDING ) { - static int lastrectime=0; - if( timeGetTime()-lastrectime > 5000 ) { - printf("ZeroSPU2: recording\n"); - lastrectime = timeGetTime(); - } - LogRawSound(s_pAudioBuffers[s_nCurBuffer].pbuf, 4, s_pAudioBuffers[s_nCurBuffer].pbuf+2, 4, NSSIZE*NSFRAMES); - } - - if( s_nQueuedBuffers >= ARRAYSIZE(s_pAudioBuffers)-1 ) { - //ZeroSPU2: dropping packets! game too fast - s_nDropPacket += NSFRAMES; - s_GlobalTimeStamp = GetMicroTime(); - } - else { - // submit to final mixer + if ( s_nQueuedBuffers >= ARRAYSIZE(s_pAudioBuffers)-1 ) + { + //ZeroSPU2: dropping packets! game too fast + s_nDropPacket += NSFRAMES; + s_GlobalTimeStamp = GetMicroTime(); + } + else { + // submit to final mixer #ifdef _DEBUG - if( g_logsound ) { - LogRawSound(s_pAudioBuffers[s_nCurBuffer].pbuf, 4, s_pAudioBuffers[s_nCurBuffer].pbuf+2, 4, NSSIZE*NSFRAMES); - } + if ( g_logsound ) + LogRawSound(s_pAudioBuffers[s_nCurBuffer].pbuf, 4, s_pAudioBuffers[s_nCurBuffer].pbuf+2, 4, NSSIZE*NSFRAMES); #endif - if( g_startcount == 0xffffffff ) { - g_startcount = timeGetTime(); - g_packetcount = 0; - } + if ( g_startcount == 0xffffffff ) + { + g_startcount = timeGetTime(); + g_packetcount = 0; + } - if( conf.options & OPTION_TIMESTRETCH ) { - u64 newtime = GetMicroTime(); - if( s_GlobalTimeStamp == 0 ) - s_GlobalTimeStamp = newtime-NSFRAMES*1000; - u32 newtotal = s_nTotalDuration-s_nDurations[s_nCurDuration]; - u32 duration = (u32)(newtime-s_GlobalTimeStamp); - s_nDurations[s_nCurDuration] = duration; - s_nTotalDuration = newtotal + duration; - s_nCurDuration = (s_nCurDuration+1)%ARRAYSIZE(s_nDurations); - s_GlobalTimeStamp = newtime; - s_pAudioBuffers[s_nCurBuffer].timestamp = timeGetTime(); - s_pAudioBuffers[s_nCurBuffer].avgtime = s_nTotalDuration/ARRAYSIZE(s_nDurations); - } + if ( conf.options & OPTION_TIMESTRETCH ) + { + u64 newtime = GetMicroTime(); + if ( s_GlobalTimeStamp == 0 ) + s_GlobalTimeStamp = newtime-NSFRAMES*1000; + u32 newtotal = s_nTotalDuration-s_nDurations[s_nCurDuration]; + u32 duration = (u32)(newtime-s_GlobalTimeStamp); + s_nDurations[s_nCurDuration] = duration; + s_nTotalDuration = newtotal + duration; + s_nCurDuration = (s_nCurDuration+1)%ARRAYSIZE(s_nDurations); + s_GlobalTimeStamp = newtime; + s_pAudioBuffers[s_nCurBuffer].timestamp = timeGetTime(); + s_pAudioBuffers[s_nCurBuffer].avgtime = s_nTotalDuration/ARRAYSIZE(s_nDurations); + } - s_pAudioBuffers[s_nCurBuffer].len = 4*NSSIZE*NSFRAMES; - InterlockedExchangeAdd((long*)&s_nQueuedBuffers, 1); + s_pAudioBuffers[s_nCurBuffer].len = 4*NSSIZE*NSFRAMES; + InterlockedExchangeAdd((long*)&s_nQueuedBuffers, 1); - s_nCurBuffer = (s_nCurBuffer+1)%ARRAYSIZE(s_pAudioBuffers); - s_pAudioBuffers[s_nCurBuffer].newchannels = 0; // reset - } + s_nCurBuffer = (s_nCurBuffer+1)%ARRAYSIZE(s_pAudioBuffers); + s_pAudioBuffers[s_nCurBuffer].newchannels = 0; // reset + } - // restart - s_pCurOutput = (s16*)s_pAudioBuffers[s_nCurBuffer].pbuf; - } - } + // restart + s_pCurOutput = (s16*)s_pAudioBuffers[s_nCurBuffer].pbuf; + } + } } // resamples pStereoSamples void ResampleLinear(s16* pStereoSamples, int oldsamples, s16* pNewSamples, int newsamples) { - for(int i = 0; i < newsamples; ++i) { - int io = i * oldsamples; - int old = io / newsamples; - int rem = io - old * newsamples; + for (int i = 0; i < newsamples; ++i) + { + int io = i * oldsamples; + int old = io / newsamples; + int rem = io - old * newsamples; - old *= 2; - int newsampL = pStereoSamples[old] * (newsamples - rem) + pStereoSamples[old+2] * rem; - int newsampR = pStereoSamples[old+1] * (newsamples - rem) + pStereoSamples[old+3] * rem; - pNewSamples[2*i] = newsampL / newsamples; - pNewSamples[2*i+1] = newsampR / newsamples; - } + old *= 2; + int newsampL = pStereoSamples[old] * (newsamples - rem) + pStereoSamples[old+2] * rem; + int newsampR = pStereoSamples[old+1] * (newsamples - rem) + pStereoSamples[old+3] * rem; + pNewSamples[2*i] = newsampL / newsamples; + pNewSamples[2*i+1] = newsampR / newsamples; + } } static PCSX2_ALIGNED16(s16 s_ThreadBuffer[NSSIZE*NSFRAMES*2*5]); @@ -871,150 +872,159 @@ DWORD WINAPI SPU2ThreadProc(LPVOID) void* SPU2ThreadProc(void* lpParam) #endif { - int nReadBuf = 0; + int nReadBuf = 0; - while(!s_bThreadExit) { + while (!s_bThreadExit) + { - if( !(conf.options&OPTION_REALTIME) ) { - while(s_nQueuedBuffers< 3 && !s_bThreadExit) { - //Sleeping - Sleep(1); - if( s_bThreadExit ) - return NULL; - } + if (!(conf.options&OPTION_REALTIME)) + { + while(s_nQueuedBuffers< 3 && !s_bThreadExit) + { + //Sleeping + Sleep(1); + if ( s_bThreadExit ) + return NULL; + } - while( SoundGetBytesBuffered() > 72000 ) { - //Bytes buffered - Sleep(1); + while( SoundGetBytesBuffered() > 72000 ) + { + //Bytes buffered + Sleep(1); - if( s_bThreadExit ) return NULL; - } - } - else { - while(s_nQueuedBuffers< 1 && !s_bThreadExit) { - //Sleeping - Sleep(1); - } - } + if ( s_bThreadExit ) return NULL; + } + } + else + { + while(s_nQueuedBuffers< 1 && !s_bThreadExit) + { + //Sleeping + Sleep(1); + } + } - int ps2delay = timeGetTime() - s_pAudioBuffers[nReadBuf].timestamp; - int NewSamples = s_pAudioBuffers[nReadBuf].avgtime; + int ps2delay = timeGetTime() - s_pAudioBuffers[nReadBuf].timestamp; + int NewSamples = s_pAudioBuffers[nReadBuf].avgtime; - if( (conf.options & OPTION_TIMESTRETCH) ) { + if ( (conf.options & OPTION_TIMESTRETCH) ) + { - int bytesbuf = SoundGetBytesBuffered(); - if( bytesbuf < 8000 ) - NewSamples += 1000; - // check the current timestamp, if too far apart, speed up audio - else if( bytesbuf > 40000 ) { - //printf("making faster %d\n", timeGetTime() - s_pAudioBuffers[nReadBuf].timestamp); - NewSamples -= (bytesbuf-40000)/10;//*(ps2delay-NewSamples*8/1000); - } + int bytesbuf = SoundGetBytesBuffered(); + if ( bytesbuf < 8000 ) + NewSamples += 1000; + // check the current timestamp, if too far apart, speed up audio + else if ( bytesbuf > 40000 ) + { + //printf("making faster %d\n", timeGetTime() - s_pAudioBuffers[nReadBuf].timestamp); + NewSamples -= (bytesbuf-40000)/10;//*(ps2delay-NewSamples*8/1000); + } - if( s_nDropPacket > 0 ) { - s_nDropPacket--; - NewSamples -= 1000; - } + if ( s_nDropPacket > 0 ) + { + s_nDropPacket--; + NewSamples -= 1000; + } - NewSamples *= NSSIZE; - NewSamples /= 1000; + NewSamples *= NSSIZE; + NewSamples /= 1000; - NewSamples = min(NewSamples, NSFRAMES*NSSIZE*3); + NewSamples = min(NewSamples, NSFRAMES*NSSIZE*3); - int oldsamples = s_pAudioBuffers[nReadBuf].len/4; + int oldsamples = s_pAudioBuffers[nReadBuf].len/4; - if( (nReadBuf&3)==0 ) { // wow, this if statement makes the whole difference - pSoundTouch->setTempoChange(100.0f*(float)oldsamples/(float)NewSamples - 100.0f); - } + if ((nReadBuf&3)==0) // wow, this if statement makes the whole difference + pSoundTouch->setTempoChange(100.0f*(float)oldsamples/(float)NewSamples - 100.0f); - pSoundTouch->putSamples((s16*)s_pAudioBuffers[nReadBuf].pbuf, oldsamples); + pSoundTouch->putSamples((s16*)s_pAudioBuffers[nReadBuf].pbuf, oldsamples); - // extract 2*NSFRAMES ms at a time - int nOutSamples; - do - { - nOutSamples = pSoundTouch->receiveSamples(s_ThreadBuffer, NSSIZE*NSFRAMES*5); - if( nOutSamples > 0 ) SoundFeedVoiceData((u8*)s_ThreadBuffer, nOutSamples*4); - } while (nOutSamples != 0); + // extract 2*NSFRAMES ms at a time + int nOutSamples; + + do + { + nOutSamples = pSoundTouch->receiveSamples(s_ThreadBuffer, NSSIZE*NSFRAMES*5); + if ( nOutSamples > 0 ) SoundFeedVoiceData((u8*)s_ThreadBuffer, nOutSamples*4); + + } while (nOutSamples != 0); - } - else { - SoundFeedVoiceData(s_pAudioBuffers[nReadBuf].pbuf, s_pAudioBuffers[nReadBuf].len); - } + } + else + SoundFeedVoiceData(s_pAudioBuffers[nReadBuf].pbuf, s_pAudioBuffers[nReadBuf].len); - // don't go to the next buffer unless there is more data buffered - nReadBuf = (nReadBuf+1)%ARRAYSIZE(s_pAudioBuffers); - InterlockedExchangeAdd((long*)&s_nQueuedBuffers, -1); + // don't go to the next buffer unless there is more data buffered + nReadBuf = (nReadBuf+1)%ARRAYSIZE(s_pAudioBuffers); + InterlockedExchangeAdd((long*)&s_nQueuedBuffers, -1); - if( s_bThreadExit ) - break; - } + if ( s_bThreadExit ) break; + } - return NULL; + return NULL; } void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size) { - u32 spuaddr = C0_SPUADDR; - int i; + u32 spuaddr = C0_SPUADDR; + int i; - SPU2_LOG("SPU2 readDMA4Mem size %x, addr: %x\n", size, pMem); + SPU2_LOG("SPU2 readDMA4Mem size %x, addr: %x\n", size, pMem); - for(i=0;i0x0fffff) // wrap at 2Mb - spuaddr=0; // wrap - } + spuaddr++; // inc spu addr + if (spuaddr>0x0fffff) spuaddr=0; // wrap at 2Mb + } - spuaddr+=19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd) - C0_SPUADDR_SET(spuaddr); + spuaddr+=19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd) + C0_SPUADDR_SET(spuaddr); - // got from J.F. and Kanodin... is it needed? - spu2Ru16(REG_C0_SPUSTAT) &=~0x80; // DMA complete - SPUStartCycle[0] = SPUCycles; - SPUTargetCycle[0] = size; - interrupt |= (1<<1); + // got from J.F. and Kanodin... is it needed? + spu2Ru16(REG_C0_SPUSTAT) &=~0x80; // DMA complete + SPUStartCycle[0] = SPUCycles; + SPUTargetCycle[0] = size; + interrupt |= (1<<1); } void CALLBACK SPU2readDMA7Mem(u16* pMem, int size) { - u32 spuaddr = C1_SPUADDR; - int i; + u32 spuaddr = C1_SPUADDR; + int i; - SPU2_LOG("SPU2 readDMA7Mem size %x, addr: %x\n", size, pMem); + SPU2_LOG("SPU2 readDMA7Mem size %x, addr: %x\n", size, pMem); - for(i=0;i0x0fffff) // wrap at 2Mb - spuaddr=0; // wrap - } + for (i=0;i0x0fffff) // wrap at 2Mb + spuaddr=0; // wrap + } - spuaddr+=19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd) - C1_SPUADDR_SET(spuaddr); + spuaddr+=19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd) + C1_SPUADDR_SET(spuaddr); - // got from J.F. and Kanodin... is it needed? - spu2Ru16(REG_C1_SPUSTAT)&=~0x80; // DMA complete - SPUStartCycle[1] = SPUCycles; - SPUTargetCycle[1] = size; - interrupt |= (1<<2); + // got from J.F. and Kanodin... is it needed? + spu2Ru16(REG_C1_SPUSTAT)&=~0x80; // DMA complete + SPUStartCycle[1] = SPUCycles; + SPUTargetCycle[1] = size; + interrupt |= (1<<2); } // WRITE @@ -1027,184 +1037,209 @@ void CALLBACK SPU2readDMA7Mem(u16* pMem, int size) // the end of the transfer. int ADMAS4Write() { - u32 spuaddr; - if(interrupt & 0x2){ + u32 spuaddr; + if (interrupt & 0x2) + { printf("4 returning for interrupt\n"); - return 0; + return 0; } - if(Adma4.AmountLeft <= 0){ + if (Adma4.AmountLeft <= 0) + { printf("4 amount left is 0\n"); - return 1; + return 1; } - assert( Adma4.AmountLeft >= 512 ); - spuaddr = C0_SPUADDR; - // SPU2 Deinterleaves the Left and Right Channels - memcpy((short*)(spu2mem + spuaddr + 0x2000),(short*)Adma4.MemAddr,512); - Adma4.MemAddr += 256; - memcpy((short*)(spu2mem + spuaddr + 0x2200),(short*)Adma4.MemAddr,512); - Adma4.MemAddr += 256; - if( (spu2Ru16(REG_C0_CTRL)&0x40) && ((spuaddr + 0x2400) <= C0_IRQA && (spuaddr + 0x2400 + 256) >= C0_IRQA)){ - IRQINFO |= 4; - printf("ADMA 4 Mem access:interrupt\n"); - irqCallbackSPU2(); - } - if( (spu2Ru16(REG_C0_CTRL)&0x40) && ((spuaddr + 0x2600) <= C0_IRQA && (spuaddr + 0x2600 + 256) >= C0_IRQA)){ - IRQINFO |= 4; - printf("ADMA 4 Mem access:interrupt\n"); - irqCallbackSPU2(); - } - - spuaddr = (spuaddr + 256) & 511; - C0_SPUADDR_SET(spuaddr); + assert( Adma4.AmountLeft >= 512 ); + spuaddr = C0_SPUADDR; - Adma4.AmountLeft-=512; - - + // SPU2 Deinterleaves the Left and Right Channels + memcpy((short*)(spu2mem + spuaddr + 0x2000),(short*)Adma4.MemAddr,512); + Adma4.MemAddr += 256; + memcpy((short*)(spu2mem + spuaddr + 0x2200),(short*)Adma4.MemAddr,512); + Adma4.MemAddr += 256; - if(Adma4.AmountLeft > 0) return 0; - else return 1; + if ((spu2Ru16(REG_C0_CTRL)&0x40) && ((spuaddr + 0x2400) <= C0_IRQA && (spuaddr + 0x2400 + 256) >= C0_IRQA)) + { + IRQINFO |= 4; + printf("ADMA 4 Mem access:interrupt\n"); + irqCallbackSPU2(); + } + + if ((spu2Ru16(REG_C0_CTRL)&0x40) && ((spuaddr + 0x2600) <= C0_IRQA && (spuaddr + 0x2600 + 256) >= C0_IRQA)) + { + IRQINFO |= 4; + printf("ADMA 4 Mem access:interrupt\n"); + irqCallbackSPU2(); + } + + spuaddr = (spuaddr + 256) & 511; + C0_SPUADDR_SET(spuaddr); + + Adma4.AmountLeft-=512; + + if (Adma4.AmountLeft > 0) + return 0; + else + return 1; } int ADMAS7Write() { - u32 spuaddr; - if(interrupt & 0x4){ - printf("7 returning for interrupt\n"); - return 0; - } - if(Adma7.AmountLeft <= 0){ - printf("7 amount left is 0\n"); - return 1; - } - - assert( Adma7.AmountLeft >= 512 ); - spuaddr = C1_SPUADDR; - // SPU2 Deinterleaves the Left and Right Channels - memcpy((short*)(spu2mem + spuaddr + 0x2400),(short*)Adma7.MemAddr,512); - Adma7.MemAddr += 256; - memcpy((short*)(spu2mem + spuaddr + 0x2600),(short*)Adma7.MemAddr,512); - Adma7.MemAddr += 256; - if( (spu2Ru16(REG_C1_CTRL)&0x40) && ((spuaddr + 0x2400) <= C1_IRQA && (spuaddr + 0x2400 + 256) >= C1_IRQA)){ - IRQINFO |= 8; - printf("ADMA 7 Mem access:interrupt\n"); - irqCallbackSPU2(); - } - if( (spu2Ru16(REG_C1_CTRL)&0x40) && ((spuaddr + 0x2600) <= C1_IRQA && (spuaddr + 0x2600 + 256) >= C1_IRQA)){ - IRQINFO |= 8; - printf("ADMA 7 Mem access:interrupt\n"); - irqCallbackSPU2(); - } - spuaddr = (spuaddr + 256) & 511; - C1_SPUADDR_SET(spuaddr); + u32 spuaddr; - Adma7.AmountLeft-=512; - - assert( Adma7.AmountLeft >= 0 ); + if (interrupt & 0x4) + { + printf("7 returning for interrupt\n"); + return 0; + } + if (Adma7.AmountLeft <= 0) + { + printf("7 amount left is 0\n"); + return 1; + } - if(Adma7.AmountLeft > 0) return 0; - else return 1; + assert( Adma7.AmountLeft >= 512 ); + spuaddr = C1_SPUADDR; + + // SPU2 Deinterleaves the Left and Right Channels + memcpy((short*)(spu2mem + spuaddr + 0x2400),(short*)Adma7.MemAddr,512); + Adma7.MemAddr += 256; + + memcpy((short*)(spu2mem + spuaddr + 0x2600),(short*)Adma7.MemAddr,512); + Adma7.MemAddr += 256; + + if ((spu2Ru16(REG_C1_CTRL)&0x40) && ((spuaddr + 0x2400) <= C1_IRQA && (spuaddr + 0x2400 + 256) >= C1_IRQA)) + { + IRQINFO |= 8; + printf("ADMA 7 Mem access:interrupt\n"); + irqCallbackSPU2(); + } + + if ((spu2Ru16(REG_C1_CTRL)&0x40) && ((spuaddr + 0x2600) <= C1_IRQA && (spuaddr + 0x2600 + 256) >= C1_IRQA)) + { + IRQINFO |= 8; + printf("ADMA 7 Mem access:interrupt\n"); + irqCallbackSPU2(); + } + + spuaddr = (spuaddr + 256) & 511; + C1_SPUADDR_SET(spuaddr); + + Adma7.AmountLeft-=512; + + assert( Adma7.AmountLeft >= 0 ); + + if (Adma7.AmountLeft > 0) + return 0; + else + return 1; } void CALLBACK SPU2writeDMA4Mem(u16* pMem, int size) { - u32 spuaddr; + u32 spuaddr; - SPU2_LOG("SPU2 writeDMA4Mem size %x, addr: %x(spu2:%x), ctrl: %x, adma: %x\n", size, pMem, C0_SPUADDR, spu2Ru16(REG_C0_CTRL), spu2Ru16(REG_C0_ADMAS)); + SPU2_LOG("SPU2 writeDMA4Mem size %x, addr: %x(spu2:%x), ctrl: %x, adma: %x\n", size, pMem, C0_SPUADDR, spu2Ru16(REG_C0_CTRL), spu2Ru16(REG_C0_ADMAS)); - if((spu2Ru16(REG_C0_ADMAS) & 0x1) && (spu2Ru16(REG_C0_CTRL) & 0x30) == 0 && size) - { - // if still active, don't destroy adma4 - if( !Adma4.Enabled ) - Adma4.Index = 0; + if ((spu2Ru16(REG_C0_ADMAS) & 0x1) && (spu2Ru16(REG_C0_CTRL) & 0x30) == 0 && size) + { + // if still active, don't destroy adma4 + if ( !Adma4.Enabled ) + Adma4.Index = 0; - Adma4.MemAddr = pMem; - Adma4.AmountLeft = size; + Adma4.MemAddr = pMem; + Adma4.AmountLeft = size; SPUTargetCycle[0] = size; spu2Ru16(REG_C0_SPUSTAT)&=~0x80; - if( !Adma4.Enabled || Adma4.Index > 384 ) { - C0_SPUADDR_SET(0); - if(ADMAS4Write()){ + if (!Adma4.Enabled || Adma4.Index > 384) + { + C0_SPUADDR_SET(0); + if (ADMAS4Write()) + { SPUStartCycle[0] = SPUCycles; interrupt |= (1<<1); } - } - Adma4.Enabled = 1; - return; - } + } + Adma4.Enabled = 1; + return; + } - spuaddr = C0_SPUADDR; - memcpy((unsigned char*)(spu2mem + spuaddr),(unsigned char*)pMem,size<<1); - spuaddr += size; - C0_SPUADDR_SET(spuaddr); - - if( (spu2Ru16(REG_C0_CTRL)&0x40) && (spuaddr < C0_IRQA && C0_IRQA <= spuaddr+0x20)){ - IRQINFO |= 4; - SPU2_LOG("SPU2writeDMA4Mem:interrupt\n"); - irqCallbackSPU2(); - } - if(spuaddr>0xFFFFE) - spuaddr = 0x2800; - C0_SPUADDR_SET(spuaddr); + spuaddr = C0_SPUADDR; + memcpy((unsigned char*)(spu2mem + spuaddr),(unsigned char*)pMem,size<<1); + spuaddr += size; + C0_SPUADDR_SET(spuaddr); + + if ((spu2Ru16(REG_C0_CTRL)&0x40) && (spuaddr < C0_IRQA && C0_IRQA <= spuaddr+0x20)) + { + IRQINFO |= 4; + SPU2_LOG("SPU2writeDMA4Mem:interrupt\n"); + irqCallbackSPU2(); + } + + if (spuaddr>0xFFFFE) + spuaddr = 0x2800; + C0_SPUADDR_SET(spuaddr); - MemAddr[0] += size<<1; - spu2Ru16(REG_C0_SPUSTAT)&=~0x80; - SPUStartCycle[0] = SPUCycles; - SPUTargetCycle[0] = size; - interrupt |= (1<<1); + MemAddr[0] += size<<1; + spu2Ru16(REG_C0_SPUSTAT)&=~0x80; + SPUStartCycle[0] = SPUCycles; + SPUTargetCycle[0] = size; + interrupt |= (1<<1); } void CALLBACK SPU2writeDMA7Mem(u16* pMem, int size) { - u32 spuaddr; + u32 spuaddr; - SPU2_LOG("SPU2 writeDMA7Mem size %x, addr: %x(spu2:%x), ctrl: %x, adma: %x\n", size, pMem, C1_SPUADDR, spu2Ru16(REG_C1_CTRL), spu2Ru16(REG_C1_ADMAS)); + SPU2_LOG("SPU2 writeDMA7Mem size %x, addr: %x(spu2:%x), ctrl: %x, adma: %x\n", size, pMem, C1_SPUADDR, spu2Ru16(REG_C1_CTRL), spu2Ru16(REG_C1_ADMAS)); - if((spu2Ru16(REG_C1_ADMAS) & 0x2) && (spu2Ru16(REG_C1_CTRL) & 0x30) == 0 && size) - { - if( !Adma7.Enabled ) - Adma7.Index = 0; + if ((spu2Ru16(REG_C1_ADMAS) & 0x2) && (spu2Ru16(REG_C1_CTRL) & 0x30) == 0 && size) + { + if (!Adma7.Enabled ) Adma7.Index = 0; - Adma7.MemAddr = pMem; - Adma7.AmountLeft = size; - SPUTargetCycle[1] = size; - spu2Ru16(REG_C1_SPUSTAT)&=~0x80; - if( !Adma7.Enabled || Adma7.Index > 384 ) { - C1_SPUADDR_SET(0); - if(ADMAS7Write()){ + Adma7.MemAddr = pMem; + Adma7.AmountLeft = size; + SPUTargetCycle[1] = size; + spu2Ru16(REG_C1_SPUSTAT)&=~0x80; + if (!Adma7.Enabled || Adma7.Index > 384) + { + C1_SPUADDR_SET(0); + if (ADMAS7Write()) + { SPUStartCycle[1] = SPUCycles; interrupt |= (1<<2); } - } - Adma7.Enabled = 1; + } + Adma7.Enabled = 1; - return; - } + return; + } #ifdef _DEBUG - if( conf.Log && conf.options & OPTION_RECORDING ) - LogPacketSound(pMem, 0x8000); + if (conf.Log && conf.options & OPTION_RECORDING) + LogPacketSound(pMem, 0x8000); #endif - spuaddr = C1_SPUADDR; - memcpy((unsigned char*)(spu2mem + spuaddr),(unsigned char*)pMem,size<<1); - spuaddr += size; - C1_SPUADDR_SET(spuaddr); - - if( (spu2Ru16(REG_C1_CTRL)&0x40) && (spuaddr < C1_IRQA && C1_IRQA <= spuaddr+0x20)){ - IRQINFO |= 8; - SPU2_LOG("SPU2writeDMA7Mem:interrupt\n"); - irqCallbackSPU2(); - } - if(spuaddr>0xFFFFE) - spuaddr = 0x2800; - C1_SPUADDR_SET(spuaddr); + spuaddr = C1_SPUADDR; + memcpy((unsigned char*)(spu2mem + spuaddr),(unsigned char*)pMem,size<<1); + spuaddr += size; + C1_SPUADDR_SET(spuaddr); + + if ((spu2Ru16(REG_C1_CTRL)&0x40) && (spuaddr < C1_IRQA && C1_IRQA <= spuaddr+0x20)) + { + IRQINFO |= 8; + SPU2_LOG("SPU2writeDMA7Mem:interrupt\n"); + irqCallbackSPU2(); + } + + if (spuaddr>0xFFFFE) spuaddr = 0x2800; + C1_SPUADDR_SET(spuaddr); - MemAddr[1] += size<<1; - spu2Ru16(REG_C1_SPUSTAT)&=~0x80; - SPUStartCycle[1] = SPUCycles; - SPUTargetCycle[1] = size; - interrupt |= (1<<2); + MemAddr[1] += size<<1; + spu2Ru16(REG_C1_SPUSTAT)&=~0x80; + SPUStartCycle[1] = SPUCycles; + SPUTargetCycle[1] = size; + interrupt |= (1<<2); } void CALLBACK SPU2interruptDMA4() @@ -1222,352 +1257,369 @@ void CALLBACK SPU2interruptDMA7() } // turn channels on -void SoundOn(int start,int end,unsigned short val) // SOUND ON PSX COMAND +void SoundOn(int start,int end,unsigned short val) // SOUND ON PSX COMAND { - for(int ch=start;ch>=1) // loop channels - { - if((val&1) && voices[ch].pStart) // mmm... start has to be set before key on !?! - { - voices[ch].bNew=true; - voices[ch].bIgnoreLoop = false; - dwNewChannel2[ch/24]|=(1<<(ch%24)); // clear end channel bit - } - } + for (int ch=start;ch>=1) // loop channels + { + if ((val&1) && voices[ch].pStart) // mmm... start has to be set before key on !?! + { + voices[ch].bNew=true; + voices[ch].bIgnoreLoop = false; + dwNewChannel2[ch/24]|=(1<<(ch%24)); // clear end channel bit + } + } } // turn channels off -void SoundOff(int start,int end,unsigned short val) // SOUND OFF PSX COMMAND +void SoundOff(int start,int end,unsigned short val) // SOUND OFF PSX COMMAND { - for(int ch=start;ch>=1) { // loop channels - if(val&1) // && s_chan[i].bOn) mmm... - voices[ch].bStop=true; - } + for (int ch=start;ch>=1) // loop channels + { + if (val&1) voices[ch].bStop=true; // && s_chan[i].bOn) mmm... + } } -void FModOn(int start,int end,unsigned short val) // FMOD ON PSX COMMAND +void FModOn(int start,int end,unsigned short val) // FMOD ON PSX COMMAND { - int ch; + int ch; - for(ch=start;ch>=1) { // loop channels - if(val&1) { // -> fmod on/off - if(ch>0) { - voices[ch].bFMod=1; // --> sound channel - voices[ch-1].bFMod=2; // --> freq channel - } - } - else - voices[ch].bFMod=0; // --> turn off fmod - } + for (ch=start;ch>=1) // loop channels + { + if (val&1) + { // -> fmod on/off + if (ch>0) + { + voices[ch].bFMod=1; // --> sound channel + voices[ch-1].bFMod=2; // --> freq channel + } + } + else + voices[ch].bFMod=0; // --> turn off fmod + } } void VolumeOn(int start,int end,unsigned short val,int iRight) // VOLUME ON PSX COMMAND { - int ch; - - for(ch=start;ch>=1) { // loop channels - if(val&1) { // -> reverb on/off - - if(iRight) - voices[ch].bVolumeR=1; - else - voices[ch].bVolumeL=1; - } - else { - if(iRight) - voices[ch].bVolumeR=0; - else - voices[ch].bVolumeL=0; - } - } + int ch; + + for (ch=start;ch>=1) // loop channels + { + if (val&1) + { // -> reverb on/off + if (iRight) + voices[ch].bVolumeR=1; + else + voices[ch].bVolumeL=1; + } + else + { + if (iRight) + voices[ch].bVolumeR=0; + else + voices[ch].bVolumeL=0; + } + } } void CALLBACK SPU2write(u32 mem, u16 value) { - u32 spuaddr; + u32 spuaddr; SPU2_LOG("SPU2 write mem %x value %x\n", mem, value); - assert( C0_SPUADDR < 0x100000); - assert( C1_SPUADDR < 0x100000); + assert( C0_SPUADDR < 0x100000); + assert( C1_SPUADDR < 0x100000); - spu2Ru16(mem) = value; - u32 r = mem&0xffff; + spu2Ru16(mem) = value; + u32 r = mem&0xffff; - // channel info - if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580)) // some channel info? - { - int ch=0; - if(r>=0x400) ch=((r-0x400)>>4)+24; - else ch=(r>>4); + // channel info + if ((r>=0x0000 && r<0x0180) || (r>=0x0400 && r<0x0580)) // some channel info? + { + int ch=0; + if (r>=0x400) ch=((r-0x400)>>4)+24; + else ch=(r>>4); - VOICE_PROCESSED* pvoice = &voices[ch]; + VOICE_PROCESSED* pvoice = &voices[ch]; - switch(r&0x0f) - { - case 0: - case 2: - pvoice->SetVolume(mem&0x2); - break; - case 4: - { - int NP; - if(value>0x3fff) NP=0x3fff; // get pitch val - else NP=value; + switch(r&0x0f) + { + case 0: + case 2: + pvoice->SetVolume(mem&0x2); + break; + case 4: + { + int NP; + if (value>0x3fff) NP=0x3fff; // get pitch val + else NP=value; - pvoice->pvoice->pitch = NP; + pvoice->pvoice->pitch = NP; - NP=(48000L*NP)/4096L; // calc frequency - if(NP<1) NP=1; // some security - pvoice->iActFreq=NP; // store frequency - break; - } - case 6: - { - pvoice->ADSRX.AttackModeExp=(value&0x8000)?1:0; - pvoice->ADSRX.AttackRate = ((value>>8) & 0x007f); - pvoice->ADSRX.DecayRate = (((value>>4) & 0x000f)); - pvoice->ADSRX.SustainLevel = (value & 0x000f); - break; - } - case 8: - pvoice->ADSRX.SustainModeExp = (value&0x8000)?1:0; - pvoice->ADSRX.SustainIncrease= (value&0x4000)?0:1; - pvoice->ADSRX.SustainRate = ((value>>6) & 0x007f); - pvoice->ADSRX.ReleaseModeExp = (value&0x0020)?1:0; - pvoice->ADSRX.ReleaseRate = ((value & 0x001f)); - break; - } + NP=(48000L*NP)/4096L; // calc frequency + if (NP<1) NP=1; // some security + pvoice->iActFreq=NP; // store frequency + break; + } + case 6: + { + pvoice->ADSRX.AttackModeExp=(value&0x8000)?1:0; + pvoice->ADSRX.AttackRate = ((value>>8) & 0x007f); + pvoice->ADSRX.DecayRate = (((value>>4) & 0x000f)); + pvoice->ADSRX.SustainLevel = (value & 0x000f); + break; + } + case 8: + pvoice->ADSRX.SustainModeExp = (value&0x8000)?1:0; + pvoice->ADSRX.SustainIncrease= (value&0x4000)?0:1; + pvoice->ADSRX.SustainRate = ((value>>6) & 0x007f); + pvoice->ADSRX.ReleaseModeExp = (value&0x0020)?1:0; + pvoice->ADSRX.ReleaseRate = ((value & 0x001f)); + break; + } - return; - } - - // more channel info - if((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0)) - { - int ch=0; - unsigned long rx=r; - if(rx>=0x400) - { - ch=24; - rx-=0x400; - } - - ch+=((rx-0x1c0)/12); - rx-=(ch%24)*12; - VOICE_PROCESSED* pvoice = &voices[ch]; - - switch(rx) - { - case 0x1C0: - pvoice->iStartAddr=(((unsigned long)value&0x3f)<<16)|(pvoice->iStartAddr&0xFFFF); - pvoice->pStart=(u8*)(spu2mem+pvoice->iStartAddr); - break; - case 0x1C2: - pvoice->iStartAddr=(pvoice->iStartAddr & 0x3f0000) | (value & 0xFFFF); - pvoice->pStart=(u8*)(spu2mem+pvoice->iStartAddr); - break; - case 0x1C4: - pvoice->iLoopAddr =(((unsigned long)value&0x3f)<<16)|(pvoice->iLoopAddr&0xFFFF); - pvoice->pLoop=(u8*)(spu2mem+pvoice->iLoopAddr); - pvoice->bIgnoreLoop=pvoice->iLoopAddr>0; - break; - case 0x1C6: - pvoice->iLoopAddr=(pvoice->iLoopAddr& 0x3f0000) | (value & 0xFFFF); - pvoice->pLoop=(u8*)(spu2mem+pvoice->iLoopAddr); - pvoice->bIgnoreLoop=pvoice->iLoopAddr>0; - break; - case 0x1C8: - // unused... check if it gets written as well - pvoice->iNextAddr=(((unsigned long)value&0x3f)<<16)|(pvoice->iNextAddr&0xFFFF); - break; - case 0x1CA: - // unused... check if it gets written as well - pvoice->iNextAddr=(pvoice->iNextAddr & 0x3f0000) | (value & 0xFFFF); - break; - } - - return; - } - - // process non-channel data - switch(mem&0xffff) { - case REG_C0_SPUDATA: - spuaddr = C0_SPUADDR; - spu2mem[spuaddr] = value; - spuaddr++; - if( (spu2Ru16(REG_C0_CTRL)&0x40) && C0_IRQA == spuaddr){ - IRQINFO |= 4; - SPU2_LOG("SPU2write:C0_CPUDATA interrupt\n"); - irqCallbackSPU2(); - } - if(spuaddr>0xFFFFE) - spuaddr = 0x2800; - C0_SPUADDR_SET(spuaddr); - spu2Ru16(REG_C0_SPUSTAT)&=~0x80; - spu2Ru16(REG_C0_CTRL)&=~0x30; - break; - case REG_C1_SPUDATA: - spuaddr = C1_SPUADDR; - spu2mem[spuaddr] = value; - spuaddr++; - if( (spu2Ru16(REG_C1_CTRL)&0x40) && C1_IRQA == spuaddr){ - IRQINFO |= 8; - SPU2_LOG("SPU2write:C1_CPUDATA interrupt\n"); - irqCallbackSPU2(); - } - if(spuaddr>0xFFFFE) - spuaddr = 0x2800; - C1_SPUADDR_SET(spuaddr); - spu2Ru16(REG_C1_SPUSTAT)&=~0x80; - spu2Ru16(REG_C1_CTRL)&=~0x30; - break; - case REG_C0_IRQA_HI: - case REG_C0_IRQA_LO: - pSpuIrq[0]=spu2mem+C0_IRQA; - break; - case REG_C1_IRQA_HI: - case REG_C1_IRQA_LO: - pSpuIrq[1]=spu2mem+C1_IRQA; - break; - - case REG_C0_SPUADDR_HI: - case REG_C1_SPUADDR_HI: - spu2Ru16(mem) = value&0xf; - break; - - case REG_C0_CTRL: - spu2Ru16(mem) = value; - // clear interrupt - if( !(value & 0x40) ) - IRQINFO &= ~0x4; - break; - case REG_C1_CTRL: - spu2Ru16(mem) = value; - // clear interrupt - if( !(value & 0x40) ) - IRQINFO &= ~0x8; - break; + return; + } - // Could probably simplify - case REG_C0_SPUON1: SoundOn(0,16,value); break; - case REG_C0_SPUON2: SoundOn(16,24,value); break; - case REG_C1_SPUON1: SoundOn(24,40,value); break; - case REG_C1_SPUON2: SoundOn(40,48,value); break; - case REG_C0_SPUOFF1: SoundOff(0,16,value); break; - case REG_C0_SPUOFF2: SoundOff(16,24,value); break; - case REG_C1_SPUOFF1: SoundOff(24,40,value); break; - case REG_C1_SPUOFF2: SoundOff(40,48,value); break; + // more channel info + if ((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0)) + { + int ch=0; + unsigned long rx=r; + if (rx>=0x400) + { + ch=24; + rx-=0x400; + } - // According to manual all bits are cleared by writing an arbitary value - case REG_C0_END1: dwEndChannel2[0] &= 0x00ff0000; break; - case REG_C0_END2: dwEndChannel2[0] &= 0x0000ffff; break; - case REG_C1_END1: dwEndChannel2[1] &= 0x00ff0000; break; - case REG_C1_END2: dwEndChannel2[1] &= 0x0000ffff; break; - case REG_C0_FMOD1: FModOn(0,16,value); break; - case REG_C0_FMOD2: FModOn(16,24,value); break; - case REG_C1_FMOD1: FModOn(24,40,value); break; - case REG_C1_FMOD2: FModOn(40,48,value); break; - case REG_C0_VMIXL1: VolumeOn(0,16,value,0); break; - case REG_C0_VMIXL2: VolumeOn(16,24,value,0); break; - case REG_C1_VMIXL1: VolumeOn(24,40,value,0); break; - case REG_C1_VMIXL2: VolumeOn(40,48,value,0); break; - case REG_C0_VMIXR1: VolumeOn(0,16,value,1); break; - case REG_C0_VMIXR2: VolumeOn(16,24,value,1); break; - case REG_C1_VMIXR1: VolumeOn(24,40,value,1); break; - case REG_C1_VMIXR2: VolumeOn(40,48,value,1); break; - } + ch += ((rx-0x1c0)/12); + rx -= (ch%24)*12; + VOICE_PROCESSED* pvoice = &voices[ch]; - assert( C0_SPUADDR < 0x100000); - assert( C1_SPUADDR < 0x100000); + switch(rx) + { + case 0x1C0: + pvoice->iStartAddr=(((unsigned long)value&0x3f)<<16)|(pvoice->iStartAddr&0xFFFF); + pvoice->pStart=(u8*)(spu2mem+pvoice->iStartAddr); + break; + case 0x1C2: + pvoice->iStartAddr=(pvoice->iStartAddr & 0x3f0000) | (value & 0xFFFF); + pvoice->pStart=(u8*)(spu2mem+pvoice->iStartAddr); + break; + case 0x1C4: + pvoice->iLoopAddr =(((unsigned long)value&0x3f)<<16)|(pvoice->iLoopAddr&0xFFFF); + pvoice->pLoop=(u8*)(spu2mem+pvoice->iLoopAddr); + pvoice->bIgnoreLoop=pvoice->iLoopAddr>0; + break; + case 0x1C6: + pvoice->iLoopAddr=(pvoice->iLoopAddr& 0x3f0000) | (value & 0xFFFF); + pvoice->pLoop=(u8*)(spu2mem+pvoice->iLoopAddr); + pvoice->bIgnoreLoop=pvoice->iLoopAddr>0; + break; + case 0x1C8: + // unused... check if it gets written as well + pvoice->iNextAddr=(((unsigned long)value&0x3f)<<16)|(pvoice->iNextAddr&0xFFFF); + break; + case 0x1CA: + // unused... check if it gets written as well + pvoice->iNextAddr=(pvoice->iNextAddr & 0x3f0000) | (value & 0xFFFF); + break; + } + + return; + } + + // process non-channel data + switch(mem&0xffff) + { + case REG_C0_SPUDATA: + spuaddr = C0_SPUADDR; + spu2mem[spuaddr] = value; + spuaddr++; + + if ((spu2Ru16(REG_C0_CTRL)&0x40) && (C0_IRQA == spuaddr)) + { + IRQINFO |= 4; + SPU2_LOG("SPU2write:C0_CPUDATA interrupt\n"); + irqCallbackSPU2(); + } + + if (spuaddr>0xFFFFE) spuaddr = 0x2800; + + C0_SPUADDR_SET(spuaddr); + spu2Ru16(REG_C0_SPUSTAT)&=~0x80; + spu2Ru16(REG_C0_CTRL)&=~0x30; + break; + + case REG_C1_SPUDATA: + spuaddr = C1_SPUADDR; + spu2mem[spuaddr] = value; + spuaddr++; + + if ((spu2Ru16(REG_C1_CTRL)&0x40) && (C1_IRQA == spuaddr)) + { + IRQINFO |= 8; + SPU2_LOG("SPU2write:C1_CPUDATA interrupt\n"); + irqCallbackSPU2(); + } + + if (spuaddr>0xFFFFE) spuaddr = 0x2800; + + C1_SPUADDR_SET(spuaddr); + spu2Ru16(REG_C1_SPUSTAT)&=~0x80; + spu2Ru16(REG_C1_CTRL)&=~0x30; + break; + + case REG_C0_IRQA_HI: + case REG_C0_IRQA_LO: + pSpuIrq[0]=spu2mem+C0_IRQA; + break; + + case REG_C1_IRQA_HI: + case REG_C1_IRQA_LO: + pSpuIrq[1]=spu2mem+C1_IRQA; + break; + + case REG_C0_SPUADDR_HI: + case REG_C1_SPUADDR_HI: + spu2Ru16(mem) = value&0xf; + break; + + case REG_C0_CTRL: + spu2Ru16(mem) = value; + // clear interrupt + if (!(value & 0x40)) IRQINFO &= ~0x4; + break; + + case REG_C1_CTRL: + spu2Ru16(mem) = value; + // clear interrupt + if (!(value & 0x40)) IRQINFO &= ~0x8; + break; + + // Could probably simplify + case REG_C0_SPUON1: SoundOn(0,16,value); break; + case REG_C0_SPUON2: SoundOn(16,24,value); break; + case REG_C1_SPUON1: SoundOn(24,40,value); break; + case REG_C1_SPUON2: SoundOn(40,48,value); break; + case REG_C0_SPUOFF1: SoundOff(0,16,value); break; + case REG_C0_SPUOFF2: SoundOff(16,24,value); break; + case REG_C1_SPUOFF1: SoundOff(24,40,value); break; + case REG_C1_SPUOFF2: SoundOff(40,48,value); break; + + // According to manual all bits are cleared by writing an arbitary value + case REG_C0_END1: dwEndChannel2[0] &= 0x00ff0000; break; + case REG_C0_END2: dwEndChannel2[0] &= 0x0000ffff; break; + case REG_C1_END1: dwEndChannel2[1] &= 0x00ff0000; break; + case REG_C1_END2: dwEndChannel2[1] &= 0x0000ffff; break; + case REG_C0_FMOD1: FModOn(0,16,value); break; + case REG_C0_FMOD2: FModOn(16,24,value); break; + case REG_C1_FMOD1: FModOn(24,40,value); break; + case REG_C1_FMOD2: FModOn(40,48,value); break; + case REG_C0_VMIXL1: VolumeOn(0,16,value,0); break; + case REG_C0_VMIXL2: VolumeOn(16,24,value,0); break; + case REG_C1_VMIXL1: VolumeOn(24,40,value,0); break; + case REG_C1_VMIXL2: VolumeOn(40,48,value,0); break; + case REG_C0_VMIXR1: VolumeOn(0,16,value,1); break; + case REG_C0_VMIXR2: VolumeOn(16,24,value,1); break; + case REG_C1_VMIXR1: VolumeOn(24,40,value,1); break; + case REG_C1_VMIXR2: VolumeOn(40,48,value,1); break; + } + + assert( C0_SPUADDR < 0x100000); + assert( C1_SPUADDR < 0x100000); } u16 CALLBACK SPU2read(u32 mem) { - u32 spuaddr; + u32 spuaddr; u16 ret; - u32 r = mem&0xffff; + u32 r = mem&0xffff; - if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580)) // some channel info? - { - int ch=0; - if(r>=0x400) ch=((r-0x400)>>4)+24; - else ch=(r>>4); + if ((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580)) // some channel info? + { + int ch=0; + + if (r>=0x400) + ch=((r-0x400)>>4)+24; + else + ch=(r>>4); - VOICE_PROCESSED* pvoice = &voices[ch]; - - switch(r&0x0f) { - case 10: - return (unsigned short)(pvoice->ADSRX.EnvelopeVol>>16); - } - } + VOICE_PROCESSED* pvoice = &voices[ch]; + + if ((r&0x0f) == 10) return (unsigned short)(pvoice->ADSRX.EnvelopeVol>>16); + } - if((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0)) // some channel info? - { - int ch=0; - unsigned long rx=r; - if(rx>=0x400) - { - ch=24; - rx-=0x400; - } + if ((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0)) // some channel info? + { + int ch=0; + unsigned long rx=r; + + if (rx>=0x400) + { + ch=24; + rx-=0x400; + } - ch+=((rx-0x1c0)/12); - rx-=(ch%24)*12; - VOICE_PROCESSED* pvoice = &voices[ch]; + ch+=((rx-0x1c0)/12); + rx-=(ch%24)*12; + VOICE_PROCESSED* pvoice = &voices[ch]; - // Note - can we generalize this? - switch(rx) { - case 0x1C0: - ret = ((((uptr)pvoice->pStart-(uptr)spu2mem)>>17)&0x3F); - break; - case 0x1C2: - ret = ((((uptr)pvoice->pStart-(uptr)spu2mem)>>1)&0xFFFF); - break; - case 0x1C4: - ret = ((((uptr)pvoice->pLoop-(uptr)spu2mem)>>17)&0x3F); - break; - case 0x1C6: - ret = ((((uptr)pvoice->pLoop-(uptr)spu2mem)>>1)&0xFFFF); - break; - case 0x1C8: - ret = ((((uptr)pvoice->pCurr-(uptr)spu2mem)>>17)&0x3F); - break; - case 0x1CA: - ret = ((((uptr)pvoice->pCurr-(uptr)spu2mem)>>1)&0xFFFF); - break; - } + // Note - can we generalize this? + switch(rx) + { + case 0x1C0: + ret = ((((uptr)pvoice->pStart-(uptr)spu2mem)>>17)&0x3F); + break; + case 0x1C2: + ret = ((((uptr)pvoice->pStart-(uptr)spu2mem)>>1)&0xFFFF); + break; + case 0x1C4: + ret = ((((uptr)pvoice->pLoop-(uptr)spu2mem)>>17)&0x3F); + break; + case 0x1C6: + ret = ((((uptr)pvoice->pLoop-(uptr)spu2mem)>>1)&0xFFFF); + break; + case 0x1C8: + ret = ((((uptr)pvoice->pCurr-(uptr)spu2mem)>>17)&0x3F); + break; + case 0x1CA: + ret = ((((uptr)pvoice->pCurr-(uptr)spu2mem)>>1)&0xFFFF); + break; + } - SPU2_LOG("SPU2 channel read mem %x: %x\n", mem, ret); - return ret; - } + SPU2_LOG("SPU2 channel read mem %x: %x\n", mem, ret); + return ret; + } - switch(mem&0xffff) { - case REG_C0_SPUDATA: - spuaddr = C0_SPUADDR; - ret =spu2mem[spuaddr]; - spuaddr++; - if(spuaddr>0xfffff) - spuaddr=0; - C0_SPUADDR_SET(spuaddr); - break; - case REG_C1_SPUDATA: - spuaddr = C1_SPUADDR; - ret = spu2mem[spuaddr]; - spuaddr++; - if(spuaddr>0xfffff) - spuaddr=0; - C1_SPUADDR_SET(spuaddr); - break; + switch(mem&0xffff) + { + case REG_C0_SPUDATA: + spuaddr = C0_SPUADDR; + ret =spu2mem[spuaddr]; + spuaddr++; + if (spuaddr>0xfffff) + spuaddr=0; + C0_SPUADDR_SET(spuaddr); + break; + case REG_C1_SPUDATA: + spuaddr = C1_SPUADDR; + ret = spu2mem[spuaddr]; + spuaddr++; + if (spuaddr>0xfffff) + spuaddr=0; + C1_SPUADDR_SET(spuaddr); + break; - case REG_C0_END1: ret = (dwEndChannel2[0]&0xffff); break; - case REG_C0_END2: ret = (dwEndChannel2[0]>>16); break; - case REG_C1_END1: ret = (dwEndChannel2[1]&0xffff); break; - case REG_C1_END2: ret = (dwEndChannel2[1]>>16); break; + case REG_C0_END1: ret = (dwEndChannel2[0]&0xffff); break; + case REG_C0_END2: ret = (dwEndChannel2[0]>>16); break; + case REG_C1_END1: ret = (dwEndChannel2[1]&0xffff); break; + case REG_C1_END2: ret = (dwEndChannel2[1]>>16); break; - case REG_IRQINFO: - ret = IRQINFO; - break; + case REG_IRQINFO: + ret = IRQINFO; + break; - default: + default: ret = spu2Ru16(mem); } @@ -1583,134 +1635,140 @@ void CALLBACK SPU2WriteMemAddr(int core, u32 value) u32 CALLBACK SPU2ReadMemAddr(int core) { - return MemAddr[core]-g_pDMABaseAddr; + return MemAddr[core]-g_pDMABaseAddr; } void CALLBACK SPU2setDMABaseAddr(uptr baseaddr) { - g_pDMABaseAddr = baseaddr; + g_pDMABaseAddr = baseaddr; } void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()) { - irqCallbackSPU2 = SPU2callback; - irqCallbackDMA4 = DMA4callback; - irqCallbackDMA7 = DMA7callback; + irqCallbackSPU2 = SPU2callback; + irqCallbackDMA4 = DMA4callback; + irqCallbackDMA7 = DMA7callback; } // VOICE_PROCESSED definitions SPU_CONTROL_* VOICE_PROCESSED::GetCtrl() { - return ((SPU_CONTROL_*)(spu2regs+memoffset+REG_C0_CTRL)); + return ((SPU_CONTROL_*)(spu2regs+memoffset+REG_C0_CTRL)); } void VOICE_PROCESSED::SetVolume(int iProcessRight) { - u16 vol = iProcessRight ? pvoice->right.word : pvoice->left.word; + u16 vol = iProcessRight ? pvoice->right.word : pvoice->left.word; - if(vol&0x8000) // sweep not working - { - short sInc=1; // -> sweep up? - if(vol&0x2000) sInc=-1; // -> or down? - if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this - vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 - vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! - vol*=128; - } - else // no sweep: - { - if(vol&0x4000) // -> mmm... phase inverted? have to investigate this - vol=0x3fff-(vol&0x3fff); - } + if (vol&0x8000) // sweep not working + { + short sInc=1; // -> sweep up? + + if (vol&0x2000) sInc=-1; // -> or down? + if (vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + } + else // no sweep: + { + if (vol&0x4000) // -> mmm... phase inverted? have to investigate this + vol=0x3fff-(vol&0x3fff); + } - if( iProcessRight ) - rightvol = vol&0x3fff; - else - leftvol = vol&0x3fff; + if ( iProcessRight ) + rightvol = vol&0x3fff; + else + leftvol = vol&0x3fff; - bVolChanged = true; + bVolChanged = true; } void VOICE_PROCESSED::StartSound() { - ADSRX.lVolume=1; // and init some adsr vars - ADSRX.State=0; - ADSRX.EnvelopeVol=0; - - if(bReverb && GetCtrl()->reverb ) - { - // setup the reverb effects - } + ADSRX.lVolume=1; // and init some adsr vars + ADSRX.State=0; + ADSRX.EnvelopeVol=0; + + if (bReverb && GetCtrl()->reverb) + { + // setup the reverb effects + } - pCurr=pStart; // set sample start - - s_1=0; // init mixing vars - s_2=0; - iSBPos=28; + pCurr=pStart; // set sample start + + s_1=0; // init mixing vars + s_2=0; + iSBPos=28; - bNew=false; // init channel flags - bStop=false; - bOn=true; - SB[29]=0; // init our interpolation helpers - SB[30]=0; + bNew=false; // init channel flags + bStop=false; + bOn=true; + SB[29]=0; // init our interpolation helpers + SB[30]=0; - spos=0x10000L; - SB[31]=0; + spos=0x10000L; + SB[31]=0; } void VOICE_PROCESSED::VoiceChangeFrequency() { - iUsedFreq=iActFreq; // -> take it and calc steps - sinc=(u32)pvoice->pitch<<4; - if(!sinc) - sinc=1; - - // -> freq change in simle imterpolation mode: set flag - SB[32]=1; + iUsedFreq=iActFreq; // -> take it and calc steps + sinc=(u32)pvoice->pitch<<4; + + if (!sinc) sinc=1; + + // -> freq change in simle imterpolation mode: set flag + SB[32]=1; } void VOICE_PROCESSED::InterpolateUp() { - if(SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass - { - const int id1=SB[30]-SB[29]; // curr delta to next val - const int id2=SB[31]-SB[30]; // and next delta to next-next val :) + if (SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass + { + const int id1=SB[30]-SB[29]; // curr delta to next val + const int id2=SB[31]-SB[30]; // and next delta to next-next val :) - SB[32]=0; + SB[32]=0; - if(id1>0) // curr delta positive - { - if(id2id1) - {SB[28]=id1;SB[32]=2;} - else - if(id2>(id1<<1)) - SB[28]=(id1*sinc)/0x10000L; - else - SB[28]=(id1*sinc)/0x20000L; - } - } - else if(SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass - { - SB[32]=0; + if (id1>0) // curr delta positive + { + if (id2id1) + { + SB[28]=id1; + SB[32]=2; + } + else if (id2>(id1<<1)) + SB[28]=(id1*sinc)/0x10000L; + else + SB[28]=(id1*sinc)/0x20000L; + } + } + else if (SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass + { + SB[32]=0; - SB[28]=(SB[28]*sinc)/0x20000L; - if(sinc<=0x8000) - SB[29]=SB[30]-(SB[28]*((0x10000/sinc)-1)); - else - SB[29]+=SB[28]; - } - else // no flags? add bigger val (if possible), calc smaller step, set flag1 - SB[29]+=SB[28]; + SB[28]=(SB[28]*sinc)/0x20000L; + if (sinc<=0x8000) + SB[29]=SB[30]-(SB[28]*((0x10000/sinc)-1)); + else + SB[29]+=SB[28]; + } + else // no flags? add bigger val (if possible), calc smaller step, set flag1 + SB[29]+=SB[28]; } // @@ -1719,35 +1777,35 @@ void VOICE_PROCESSED::InterpolateUp() void VOICE_PROCESSED::InterpolateDown() { - if(sinc>=0x20000L) // we would skip at least one val? - { - SB[29]+=(SB[30]-SB[29])/2; // add easy weight - if(sinc>=0x30000L) // we would skip even more vals? - SB[29]+=(SB[31]-SB[30])/2; // add additional next weight - } + if (sinc>=0x20000L) // we would skip at least one val? + { + SB[29]+=(SB[30]-SB[29])/2; // add easy weight + if (sinc>=0x30000L) // we would skip even more vals? + SB[29]+=(SB[31]-SB[30])/2; // add additional next weight + } } void VOICE_PROCESSED::FModChangeFrequency(int ns) { - int NP=pvoice->pitch; + int NP=pvoice->pitch; - NP=((32768L+iFMod[ns])*NP)/32768L; + NP=((32768L+iFMod[ns])*NP)/32768L; - if(NP>0x3fff) NP=0x3fff; - if(NP<0x1) NP=0x1; + if (NP>0x3fff) NP=0x3fff; + if (NP<0x1) NP=0x1; - NP=(48000L*NP)/(4096L); // calc frequency + NP=(48000L*NP)/(4096L); // calc frequency - iActFreq=NP; - iUsedFreq=NP; - sinc=(((NP/10)<<16)/4800); - if(!sinc) - sinc=1; + iActFreq=NP; + iUsedFreq=NP; + sinc=(((NP/10)<<16)/4800); + if (!sinc) + sinc=1; - // freq change in simple interpolation mode - SB[32]=1; + // freq change in simple interpolation mode + SB[32]=1; - iFMod[ns]=0; + iFMod[ns]=0; } // fixme - noise handler... just produces some noise data @@ -1755,65 +1813,67 @@ void VOICE_PROCESSED::FModChangeFrequency(int ns) // and sometimes the noise will be used as fmod modulation... pfff int VOICE_PROCESSED::iGetNoiseVal() { - int fa; + int fa; - if((dwNoiseVal<<=1)&0x80000000L) - { - dwNoiseVal^=0x0040001L; - fa=((dwNoiseVal>>2)&0x7fff); - fa=-fa; - } - else - fa=(dwNoiseVal>>2)&0x7fff; + if ((dwNoiseVal<<=1)&0x80000000L) + { + dwNoiseVal^=0x0040001L; + fa = ((dwNoiseVal>>2)&0x7fff); + fa = -fa; + } + else + fa=(dwNoiseVal>>2)&0x7fff; - // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val - fa=iOldNoise+((fa-iOldNoise)/((0x001f-(GetCtrl()->noiseFreq))+1)); - if(fa>32767L) - fa=32767L; - if(fa<-32767L) - fa=-32767L; + // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val + fa=iOldNoise + ((fa - iOldNoise) / ((0x001f - (GetCtrl()->noiseFreq)) + 1)); + + if (fa > 32767L) + fa = 32767L; + if (fa < -32767L) + fa = -32767L; - iOldNoise=fa; - SB[29] = fa; // -> store noise val in "current sample" slot - return fa; -} + iOldNoise=fa; + SB[29] = fa; // -> store noise val in "current sample" slot + return fa; +} void VOICE_PROCESSED::StoreInterpolationVal(int fa) { - if(bFMod==2) // fmod freq channel - SB[29]=fa; - else - { - if(!GetCtrl()->spuUnmute) - fa=0; // muted? - else // else adjust - { - if(fa>32767L) - fa=32767L; - if(fa<-32767L) - fa=-32767L; - } + if (bFMod==2) // fmod freq channel + SB[29]=fa; + else + { + if (!GetCtrl()->spuUnmute) + fa=0; // muted? + else // else adjust + { + if (fa >32767L) + fa = 32767L; + if (fa < -32767L) + fa = -32767L; + } - SB[28] = 0; - SB[29] = SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' - SB[30] = SB[31]; - SB[31] = fa; - SB[32] = 1; // -> flag: calc new interolation - } + SB[28] = 0; + SB[29] = SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' + SB[30] = SB[31]; + SB[31] = fa; + SB[32] = 1; // -> flag: calc new interolation + } } int VOICE_PROCESSED::iGetInterpolationVal() { - int fa; - if(bFMod==2) - return SB[29]; + int fa; + + if (bFMod==2) return SB[29]; - if(sinc<0x10000L) // -> upsampling? - InterpolateUp(); // --> interpolate up - else InterpolateDown(); // --> else down - fa=SB[29]; - - return fa; + if (sinc<0x10000L) // -> upsampling? + InterpolateUp(); // --> interpolate up + else + InterpolateDown(); // --> else down + + fa=SB[29]; + return fa; } void VOICE_PROCESSED::Stop() @@ -1829,200 +1889,217 @@ s32 CALLBACK SPU2test() // size is in bytes void LogPacketSound(void* packet, int memsize) { - u16 buf[28]; + u16 buf[28]; - u8* pstart = (u8*)packet; - int s_1 = 0; - int s_2=0; - for(int i = 0; i < memsize; i += 16) { - int predict_nr=(int)pstart[0]; - int shift_factor=predict_nr&0xf; - predict_nr >>= 4; - int flags=(int)pstart[1]; - pstart += 2; + u8* pstart = (u8*)packet; + int s_1 = 0; + int s_2=0; + + for (int i = 0; i < memsize; i += 16) + { + int predict_nr=(int)pstart[0]; + int shift_factor=predict_nr&0xf; + predict_nr >>= 4; + int flags=(int)pstart[1]; + pstart += 2; - for(int nSample=0;nSample<28; ++pstart) - { - int d=(int)*pstart; - int s=((d&0xf)<<12); - if(s&0x8000) s|=0xffff0000; + for (int nSample=0;nSample<28; ++pstart) + { + int d=(int)*pstart; + int s=((d&0xf)<<12); + if (s&0x8000) s|=0xffff0000; + int fa; + + fa = (s >> shift_factor); + fa += ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2 = s_1; + s_1 = fa; + s=((d & 0xf0) << 8); - int fa=(s >> shift_factor); - fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); - s_2=s_1;s_1=fa; - s=((d & 0xf0) << 8); + buf[nSample++]=fa; - buf[nSample++]=fa; + if (s&0x8000) s|=0xffff0000; + fa = (s>>shift_factor); + fa += ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2 = s_1; + s_1 = fa; - if(s&0x8000) s|=0xffff0000; - fa=(s>>shift_factor); - fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); - s_2=s_1;s_1=fa; + buf[nSample++]=fa; + } - buf[nSample++]=fa; - } - - LogRawSound(buf, 2, buf, 2, 28); - } + LogRawSound(buf, 2, buf, 2, 28); + } } #define RECORD_FILENAME "zerospu2.wav" void LogRawSound(void* pleft, int leftstride, void* pright, int rightstride, int numsamples) { - if( g_pWavRecord == NULL ) { - g_pWavRecord = new WavOutFile(RECORD_FILENAME, 48000, 16, 2); - } + if (g_pWavRecord == NULL ) + g_pWavRecord = new WavOutFile(RECORD_FILENAME, 48000, 16, 2); - u8* left = (u8*)pleft; - u8* right = (u8*)pright; - static vector tempbuf; + u8* left = (u8*)pleft; + u8* right = (u8*)pright; + static vector tempbuf; - tempbuf.resize(2*numsamples); + tempbuf.resize(2*numsamples); - for(int i = 0; i < numsamples; ++i) { - tempbuf[2*i+0] = *(s16*)left; - tempbuf[2*i+1] = *(s16*)right; - left += leftstride; - right += rightstride; - } + for (int i = 0; i < numsamples; ++i) + { + tempbuf[2*i+0] = *(s16*)left; + tempbuf[2*i+1] = *(s16*)right; + left += leftstride; + right += rightstride; + } - g_pWavRecord->write(&tempbuf[0], numsamples*2); + g_pWavRecord->write(&tempbuf[0], numsamples*2); } int CALLBACK SPU2setupRecording(int start, void* pData) { - if( start ) { - conf.options |= OPTION_RECORDING; - printf("ZeroSPU2: started recording at %s\n", RECORD_FILENAME); - } - else { - conf.options &= ~OPTION_RECORDING; - printf("ZeroSPU2: stopped recording\n"); - } - - return 1; + if ( start ) + { + conf.options |= OPTION_RECORDING; + printf("ZeroSPU2: started recording at %s\n", RECORD_FILENAME); + } + else + { + conf.options &= ~OPTION_RECORDING; + printf("ZeroSPU2: stopped recording\n"); + } + + return 1; } struct SPU2freezeData { - u32 version; + u32 version; u8 spu2regs[0x10000]; - u8 spu2mem[0x200000]; - u16 interrupt; - int nSpuIrq[2]; - u32 dwNewChannel2[2], dwEndChannel2[2]; - u32 dwNoiseVal; - int iFMod[NSSIZE]; - u32 MemAddr[2]; - ADMA adma[2]; - u32 Adma4MemAddr, Adma7MemAddr; + u8 spu2mem[0x200000]; + u16 interrupt; + int nSpuIrq[2]; + u32 dwNewChannel2[2], dwEndChannel2[2]; + u32 dwNoiseVal; + int iFMod[NSSIZE]; + u32 MemAddr[2]; + ADMA adma[2]; + u32 Adma4MemAddr, Adma7MemAddr; - int SPUCycles, SPUWorkerCycles; - int SPUStartCycle[2]; - int SPUTargetCycle[2]; + int SPUCycles, SPUWorkerCycles; + int SPUStartCycle[2]; + int SPUTargetCycle[2]; - int voicesize; - VOICE_PROCESSED voices[SPU_NUMBER_VOICES+1]; + int voicesize; + VOICE_PROCESSED voices[SPU_NUMBER_VOICES+1]; }; s32 CALLBACK SPU2freeze(int mode, freezeData *data) { SPU2freezeData *spud; - int i; - assert( g_pDMABaseAddr != 0 ); + int i; + assert( g_pDMABaseAddr != 0 ); - if (mode == FREEZE_LOAD) { + if (mode == FREEZE_LOAD) + { spud = (SPU2freezeData*)data->data; - if( spud->version != 0x70000001 ) { - printf("zerospu2: data wrong format\n"); - return 0; - } + if (spud->version != 0x70000001) + { + printf("zerospu2: data wrong format\n"); + return 0; + } memcpy(spu2regs, spud->spu2regs, 0x10000); - memcpy(spu2mem, spud->spu2mem, 0x200000); - pSpuIrq[0] = spu2mem + spud->nSpuIrq[0]; - pSpuIrq[1] = spu2mem + spud->nSpuIrq[1]; - memcpy(dwNewChannel2, spud->dwNewChannel2, 4*2); - memcpy(dwEndChannel2, spud->dwEndChannel2, 4*2); - dwNoiseVal = spud->dwNoiseVal; - memcpy(iFMod, spud->iFMod, sizeof(iFMod)); - interrupt = spud->interrupt; - memcpy(MemAddr, spud->MemAddr, sizeof(MemAddr)); - Adma4 = spud->adma[0]; - Adma4.MemAddr = (u16*)(g_pDMABaseAddr+spud->Adma4MemAddr); - Adma7 = spud->adma[1]; - Adma7.MemAddr = (u16*)(g_pDMABaseAddr+spud->Adma7MemAddr); + memcpy(spu2mem, spud->spu2mem, 0x200000); + pSpuIrq[0] = spu2mem + spud->nSpuIrq[0]; + pSpuIrq[1] = spu2mem + spud->nSpuIrq[1]; + memcpy(dwNewChannel2, spud->dwNewChannel2, 4*2); + memcpy(dwEndChannel2, spud->dwEndChannel2, 4*2); + dwNoiseVal = spud->dwNoiseVal; + memcpy(iFMod, spud->iFMod, sizeof(iFMod)); + interrupt = spud->interrupt; + memcpy(MemAddr, spud->MemAddr, sizeof(MemAddr)); + Adma4 = spud->adma[0]; + Adma4.MemAddr = (u16*)(g_pDMABaseAddr+spud->Adma4MemAddr); + Adma7 = spud->adma[1]; + Adma7.MemAddr = (u16*)(g_pDMABaseAddr+spud->Adma7MemAddr); - SPUCycles = spud->SPUCycles; - SPUWorkerCycles = spud->SPUWorkerCycles; - memcpy(SPUStartCycle, spud->SPUStartCycle, sizeof(SPUStartCycle)); - memcpy(SPUTargetCycle, spud->SPUTargetCycle, sizeof(SPUTargetCycle)); + SPUCycles = spud->SPUCycles; + SPUWorkerCycles = spud->SPUWorkerCycles; + memcpy(SPUStartCycle, spud->SPUStartCycle, sizeof(SPUStartCycle)); + memcpy(SPUTargetCycle, spud->SPUTargetCycle, sizeof(SPUTargetCycle)); - for(i = 0; i < ARRAYSIZE(voices); ++i) { - memcpy(&voices[i], &spud->voices[i], min((int)SPU_VOICE_STATE_SIZE, spud->voicesize)); - voices[i].pStart = (u8*)((uptr)spud->voices[i].pStart+(uptr)spu2mem); - voices[i].pLoop = (u8*)((uptr)spud->voices[i].pLoop+(uptr)spu2mem); - voices[i].pCurr = (u8*)((uptr)spud->voices[i].pCurr+(uptr)spu2mem); - } + for (i = 0; i < ARRAYSIZE(voices); ++i) + { + memcpy(&voices[i], &spud->voices[i], min((int)SPU_VOICE_STATE_SIZE, spud->voicesize)); + voices[i].pStart = (u8*)((uptr)spud->voices[i].pStart+(uptr)spu2mem); + voices[i].pLoop = (u8*)((uptr)spud->voices[i].pLoop+(uptr)spu2mem); + voices[i].pCurr = (u8*)((uptr)spud->voices[i].pCurr+(uptr)spu2mem); + } - s_GlobalTimeStamp = 0; - g_startcount=0xffffffff; - for(int i = 0; i < ARRAYSIZE(s_nDurations); ++i) { - s_nDurations[i] = NSFRAMES*1000; - } - s_nTotalDuration = ARRAYSIZE(s_nDurations)*NSFRAMES*1000; - s_nCurDuration = 0; - s_nQueuedBuffers = 0; - s_nDropPacket = 0; + s_GlobalTimeStamp = 0; + g_startcount = 0xffffffff; + + for (int i = 0; i < ARRAYSIZE(s_nDurations); ++i) + { + s_nDurations[i] = NSFRAMES*1000; + } + + s_nTotalDuration = ARRAYSIZE(s_nDurations)*NSFRAMES*1000; + s_nCurDuration = 0; + s_nQueuedBuffers = 0; + s_nDropPacket = 0; } - else if (mode == FREEZE_SAVE) { + else if (mode == FREEZE_SAVE) + { spud = (SPU2freezeData*)data->data; - spud->version = 0x70000001; + spud->version = 0x70000001; memcpy(spud->spu2regs, spu2regs, 0x10000); - memcpy(spud->spu2mem, spu2mem, 0x200000); - spud->nSpuIrq[0] = (int)(pSpuIrq[0] - spu2mem); - spud->nSpuIrq[1] = (int)(pSpuIrq[1] - spu2mem); - memcpy(spud->dwNewChannel2, dwNewChannel2, 4*2); - memcpy(spud->dwEndChannel2, dwEndChannel2, 4*2); - spud->dwNoiseVal = dwNoiseVal; - memcpy(spud->iFMod, iFMod, sizeof(iFMod)); - spud->interrupt = interrupt; - memcpy(spud->MemAddr, MemAddr, sizeof(MemAddr)); + memcpy(spud->spu2mem, spu2mem, 0x200000); + spud->nSpuIrq[0] = (int)(pSpuIrq[0] - spu2mem); + spud->nSpuIrq[1] = (int)(pSpuIrq[1] - spu2mem); + memcpy(spud->dwNewChannel2, dwNewChannel2, 4*2); + memcpy(spud->dwEndChannel2, dwEndChannel2, 4*2); + spud->dwNoiseVal = dwNoiseVal; + memcpy(spud->iFMod, iFMod, sizeof(iFMod)); + spud->interrupt = interrupt; + memcpy(spud->MemAddr, MemAddr, sizeof(MemAddr)); - spud->adma[0] = Adma4; - spud->Adma4MemAddr = (u32)((uptr)Adma4.MemAddr - g_pDMABaseAddr); - spud->adma[1] = Adma7; - spud->Adma7MemAddr = (u32)((uptr)Adma7.MemAddr - g_pDMABaseAddr); + spud->adma[0] = Adma4; + spud->Adma4MemAddr = (u32)((uptr)Adma4.MemAddr - g_pDMABaseAddr); + spud->adma[1] = Adma7; + spud->Adma7MemAddr = (u32)((uptr)Adma7.MemAddr - g_pDMABaseAddr); - spud->SPUCycles = SPUCycles; - spud->SPUWorkerCycles = SPUWorkerCycles; + spud->SPUCycles = SPUCycles; + spud->SPUWorkerCycles = SPUWorkerCycles; - memcpy(spud->SPUStartCycle, SPUStartCycle, sizeof(SPUStartCycle)); - memcpy(spud->SPUTargetCycle, SPUTargetCycle, sizeof(SPUTargetCycle)); + memcpy(spud->SPUStartCycle, SPUStartCycle, sizeof(SPUStartCycle)); + memcpy(spud->SPUTargetCycle, SPUTargetCycle, sizeof(SPUTargetCycle)); - for(i = 0; i < ARRAYSIZE(s_nDurations); ++i) { - s_nDurations[i] = NSFRAMES*1000; - } - s_nTotalDuration = ARRAYSIZE(s_nDurations)*NSFRAMES*1000; - s_nCurDuration = 0; + for (i = 0; i < ARRAYSIZE(s_nDurations); ++i) + { + s_nDurations[i] = NSFRAMES*1000; + } + s_nTotalDuration = ARRAYSIZE(s_nDurations)*NSFRAMES*1000; + s_nCurDuration = 0; - spud->voicesize = SPU_VOICE_STATE_SIZE; - for(i = 0; i < ARRAYSIZE(voices); ++i) { - memcpy(&spud->voices[i], &voices[i], SPU_VOICE_STATE_SIZE); - spud->voices[i].pStart = (u8*)((uptr)voices[i].pStart-(uptr)spu2mem); - spud->voices[i].pLoop = (u8*)((uptr)voices[i].pLoop-(uptr)spu2mem); - spud->voices[i].pCurr = (u8*)((uptr)voices[i].pCurr-(uptr)spu2mem); - } + spud->voicesize = SPU_VOICE_STATE_SIZE; + for (i = 0; i < ARRAYSIZE(voices); ++i) + { + memcpy(&spud->voices[i], &voices[i], SPU_VOICE_STATE_SIZE); + spud->voices[i].pStart = (u8*)((uptr)voices[i].pStart-(uptr)spu2mem); + spud->voices[i].pLoop = (u8*)((uptr)voices[i].pLoop-(uptr)spu2mem); + spud->voices[i].pCurr = (u8*)((uptr)voices[i].pCurr-(uptr)spu2mem); + } - g_startcount=0xffffffff; - s_GlobalTimeStamp = 0; - s_nDropPacket = 0; + g_startcount=0xffffffff; + s_GlobalTimeStamp = 0; + s_nDropPacket = 0; } - else if (mode == FREEZE_SIZE) { + else if (mode == FREEZE_SIZE) + { data->size = sizeof(SPU2freezeData); } - + return 0; } diff --git a/plugins/zerospu2/zerospu2.h b/plugins/zerospu2/zerospu2.h index 777d7a9dbc..58a1ace145 100644 --- a/plugins/zerospu2/zerospu2.h +++ b/plugins/zerospu2/zerospu2.h @@ -33,21 +33,21 @@ extern "C" { #ifdef __LINUX__ #include #include -#include // ftime(), struct timeb +#include // ftime(), struct timeb #define Sleep(ms) usleep(1000*ms) inline unsigned long timeGetTime() { #ifdef _WIN32 - _timeb t; - _ftime(&t); + _timeb t; + _ftime(&t); #else - timeb t; - ftime(&t); + timeb t; + ftime(&t); #endif - return (unsigned long)(t.time*1000+t.millitm); + return (unsigned long)(t.time*1000+t.millitm); } #include @@ -56,21 +56,21 @@ inline unsigned long timeGetTime() #include #include -#include // ftime(), struct timeb +#include // ftime(), struct timeb #endif inline u64 GetMicroTime() { #ifdef _WIN32 - extern LARGE_INTEGER g_counterfreq; - LARGE_INTEGER count; - QueryPerformanceCounter(&count); - return count.QuadPart * 1000000 / g_counterfreq.QuadPart; + extern LARGE_INTEGER g_counterfreq; + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + return count.QuadPart * 1000000 / g_counterfreq.QuadPart; #else - timeval t; - gettimeofday(&t, NULL); - return t.tv_sec*1000000+t.tv_usec; + timeval t; + gettimeofday(&t, NULL); + return t.tv_sec*1000000+t.tv_usec; #endif } @@ -88,7 +88,7 @@ extern FILE *spu2Log; #define SPU2_VERSION PS2E_SPU2_VERSION #define SPU2_REVISION 0 -#define SPU2_BUILD 4 // increase that with each version +#define SPU2_BUILD 4 // increase that with each version #define SPU2_MINOR 6 #define OPTION_TIMESTRETCH 1 // stretches samples without changing pitch to reduce cracking @@ -97,8 +97,8 @@ extern FILE *spu2Log; #define OPTION_RECORDING 8 typedef struct { - int Log; - int options; + int Log; + int options; } Config; extern Config conf; @@ -125,7 +125,7 @@ void SoundFeedVoiceData(unsigned char* pSound,long lBytes); // declare linux equivalents extern __forceinline void* pcsx2_aligned_malloc(size_t size, size_t align) { - assert( align < 0x10000 ); + assert( align < 0x10000 ); char* p = (char*)malloc(size+align); int off = 2+align - ((int)(uptr)(p+2) % align); @@ -137,10 +137,10 @@ extern __forceinline void* pcsx2_aligned_malloc(size_t size, size_t align) extern __forceinline void pcsx2_aligned_free(void* pmem) { - if( pmem != NULL ) { - char* p = (char*)pmem; - free(p - (int)*(u16*)(p-2)); - } + if( pmem != NULL ) { + char* p = (char*)pmem; + free(p - (int)*(u16*)(p-2)); + } } #define _aligned_malloc pcsx2_aligned_malloc @@ -148,54 +148,77 @@ extern __forceinline void pcsx2_aligned_free(void* pmem) #endif +// Atomic Operations +#if defined (_WIN32) + +#ifndef __x86_64__ +extern "C" LONG __cdecl _InterlockedExchangeAdd(LPLONG volatile Addend, LONG Value); +#endif + +#pragma intrinsic (_InterlockedExchangeAdd) +#define InterlockedExchangeAdd _InterlockedExchangeAdd + +#else + +typedef void* PVOID; + +__forceinline long InterlockedExchangeAdd(long volatile* Addend, long Value) +{ + __asm__ __volatile__(".intel_syntax\n" + "lock xadd [%0], %%eax\n" + ".att_syntax\n" : : "r"(Addend), "a"(Value) : "memory" ); +} + +#endif + //////////////////// // SPU2 Registers // //////////////////// -#define REG_VP_VOLL 0x0000 -#define REG_VP_VOLR 0x0002 -#define REG_VP_PITCH 0x0004 -#define REG_VP_ADSR1 0x0006 -#define REG_VP_ADSR2 0x0008 -#define REG_VP_ENVX 0x000A -#define REG_VP_VOLXL 0x000C -#define REG_VP_VOLXR 0x000E -#define REG_C0_FMOD1 0x0180 -#define REG_C0_FMOD2 0x0182 -#define REG_C0_VMIXL1 0x0188 -#define REG_C0_VMIXL2 0x018A -#define REG_C0_VMIXR1 0x0190 -#define REG_C0_VMIXR2 0x0192 -#define REG_C0_MMIX 0x0198 -#define REG_C0_CTRL 0x019A +#define REG_VP_VOLL 0x0000 +#define REG_VP_VOLR 0x0002 +#define REG_VP_PITCH 0x0004 +#define REG_VP_ADSR1 0x0006 +#define REG_VP_ADSR2 0x0008 +#define REG_VP_ENVX 0x000A +#define REG_VP_VOLXL 0x000C +#define REG_VP_VOLXR 0x000E +#define REG_C0_FMOD1 0x0180 +#define REG_C0_FMOD2 0x0182 +#define REG_C0_VMIXL1 0x0188 +#define REG_C0_VMIXL2 0x018A +#define REG_C0_VMIXR1 0x0190 +#define REG_C0_VMIXR2 0x0192 +#define REG_C0_MMIX 0x0198 +#define REG_C0_CTRL 0x019A #define REG_C0_IRQA_HI 0x019C #define REG_C0_IRQA_LO 0x019E -#define REG_C0_SPUON1 0x1A0 -#define REG_C0_SPUON2 0x1A2 +#define REG_C0_SPUON1 0x1A0 +#define REG_C0_SPUON2 0x1A2 #define REG_C0_SPUOFF1 0x1A4 #define REG_C0_SPUOFF2 0x1A6 #define REG_C0_SPUADDR_HI 0x01A8 #define REG_C0_SPUADDR_LO 0x01AA #define REG_C0_SPUDATA 0x01AC #define REG_C0_DMACTRL 0x01AE -#define REG_C0_ADMAS 0x01B0 -#define REG_C0_END1 0x0340 -#define REG_C0_END2 0x0342 +#define REG_C0_ADMAS 0x01B0 +#define REG_C0_END1 0x0340 +#define REG_C0_END2 0x0342 #define REG_C0_SPUSTAT 0x0344 -#define REG_C0_BVOLL 0x076C -#define REG_C0_BVOLR 0x076E +#define REG_C0_BVOLL 0x076C +#define REG_C0_BVOLR 0x076E -//#define SPU2_TRANS_BY_DMA (0x0<<3) -//#define SPU2_TRANS_BY_IO (0x1<<3) +//#define SPU2_TRANS_BY_DMA (0x0<<3) +//#define SPU2_TRANS_BY_IO (0x1<<3) // //#define SPU2_BLOCK_ONESHOT (0<<4) //#define SPU2_BLOCK_LOOP (1<<4) //#define SPU2_BLOCK_HANDLER (1<<7) -//#define SPU2_BLOCK_C0_VOICE1 ( 0x0<<8 ) -//#define SPU2_BLOCK_C0_VOICE3 ( 0x1<<8 ) -//#define SPU2_BLOCK_C1_SINL ( 0x2<<8 ) -//#define SPU2_BLOCK_C1_SINR ( 0x3<<8 ) -//#define SPU2_BLOCK_C1_VOICE1 ( 0x4<<8 ) -//#define SPU2_BLOCK_C1_VOICE3 ( 0x5<<8 ) +//#define SPU2_BLOCK_C0_VOICE1 ( 0x0<<8 ) +//#define SPU2_BLOCK_C0_VOICE3 ( 0x1<<8 ) +//#define SPU2_BLOCK_C1_SINL ( 0x2<<8 ) +//#define SPU2_BLOCK_C1_SINR ( 0x3<<8 ) +//#define SPU2_BLOCK_C1_VOICE1 ( 0x4<<8 ) +//#define SPU2_BLOCK_C1_VOICE3 ( 0x5<<8 ) //#define SPU2_BLOCK_C0_MEMOUTL ( 0x6<<8 ) //#define SPU2_BLOCK_C0_MEMOUTR ( 0x7<<8 ) //#define SPU2_BLOCK_C0_MEMOUTEL ( 0x8<<8 ) @@ -237,57 +260,57 @@ extern __forceinline void pcsx2_aligned_free(void* pmem) //#define SPU2_REV_SIZE_DELAY 0x18040 //#define SPU2_REV_SIZE_PIPE 0x3c00 // -//#define SPU2_SOUNDOUT_TOPADDR 0x0 -//#define SPU2_SOUNDIN_TOPADDR 0x4000 -//#define SPU2_USERAREA_TOPADDR 0x5010 +//#define SPU2_SOUNDOUT_TOPADDR 0x0 +//#define SPU2_SOUNDIN_TOPADDR 0x4000 +//#define SPU2_USERAREA_TOPADDR 0x5010 // //#define SPU2_INIT_COLD 0 //#define SPU2_INIT_HOT 1 -#define REG_C1_FMOD1 0x0580 -#define REG_C1_FMOD2 0x0582 -#define REG_S_NON 0x0184 -#define REG_C1_VMIXL1 0x0588 -#define REG_C1_VMIXL2 0x058A -#define REG_S_VMIXEL 0x018C -#define REG_C1_VMIXR1 0x0590 -#define REG_C1_VMIXR2 0x0592 -#define REG_S_VMIXER 0x0194 -#define REG_C1_MMIX 0x0598 +#define REG_C1_FMOD1 0x0580 +#define REG_C1_FMOD2 0x0582 +#define REG_S_NON 0x0184 +#define REG_C1_VMIXL1 0x0588 +#define REG_C1_VMIXL2 0x058A +#define REG_S_VMIXEL 0x018C +#define REG_C1_VMIXR1 0x0590 +#define REG_C1_VMIXR2 0x0592 +#define REG_S_VMIXER 0x0194 +#define REG_C1_MMIX 0x0598 #define REG_C1_IRQA_HI 0x059C #define REG_C1_IRQA_LO 0x059E -#define REG_C1_SPUON1 0x5A0 -#define REG_C1_SPUON2 0x5A2 +#define REG_C1_SPUON1 0x5A0 +#define REG_C1_SPUON2 0x5A2 #define REG_C1_SPUOFF1 0x5A4 #define REG_C1_SPUOFF2 0x5A6 #define REG_C1_SPUADDR_HI 0x05A8 #define REG_C1_SPUADDR_LO 0x05AA #define REG_C1_SPUDATA 0x05AC #define REG_C1_DMACTRL 0x05AE -#define REG_VA_SSA 0x01C0 -#define REG_VA_LSAX 0x01C4 -#define REG_VA_NAX 0x01C8 -#define REG_A_ESA 0x02E0 -#define REG_A_EEA 0x033C -#define REG_C1_END1 0x0740 -#define REG_C1_END2 0x0742 -#define REG_C1_CTRL 0x059A -#define REG_C1_ADMAS 0x05B0 +#define REG_VA_SSA 0x01C0 +#define REG_VA_LSAX 0x01C4 +#define REG_VA_NAX 0x01C8 +#define REG_A_ESA 0x02E0 +#define REG_A_EEA 0x033C +#define REG_C1_END1 0x0740 +#define REG_C1_END2 0x0742 +#define REG_C1_CTRL 0x059A +#define REG_C1_ADMAS 0x05B0 #define REG_C1_SPUSTAT 0x0744 -#define REG_P_MVOLL 0x0760 -#define REG_P_MVOLR 0x0762 -#define REG_P_EVOLL 0x0764 -#define REG_P_EVOLR 0x0766 -#define REG_P_AVOLL 0x0768 -#define REG_P_AVOLR 0x076A -#define REG_C1_BVOLL 0x0794 -#define REG_C1_BVOLR 0x0796 -#define REG_P_MVOLXL 0x0770 -#define REG_P_MVOLXR 0x0772 -#define SPDIF_OUT 0x07C0 -#define REG_IRQINFO 0x07C2 -#define SPDIF_MODE 0x07C6 -#define SPDIF_MEDIA 0x07C8 +#define REG_P_MVOLL 0x0760 +#define REG_P_MVOLR 0x0762 +#define REG_P_EVOLL 0x0764 +#define REG_P_EVOLR 0x0766 +#define REG_P_AVOLL 0x0768 +#define REG_P_AVOLR 0x076A +#define REG_C1_BVOLL 0x0794 +#define REG_C1_BVOLR 0x0796 +#define REG_P_MVOLXL 0x0770 +#define REG_P_MVOLXR 0x0772 +#define SPDIF_OUT 0x07C0 +#define REG_IRQINFO 0x07C2 +#define SPDIF_MODE 0x07C6 +#define SPDIF_MEDIA 0x07C8 #define SPU_AUTODMA_ONESHOT 0 //spu2 #define SPU_AUTODMA_LOOP 1 //spu2 @@ -302,9 +325,9 @@ extern __forceinline void pcsx2_aligned_free(void* pmem) #define SPU2_GET32BIT(lo,hi) (((u32)(spu2Ru16(hi)&0x3f)<<16)|(u32)spu2Ru16(lo)) #define SPU2_SET32BIT(value, lo, hi) { \ - spu2Ru16(hi) = ((value)>>16)&0x3f; \ - spu2Ru16(lo) = (value)&0xffff; \ - } \ + spu2Ru16(hi) = ((value)>>16)&0x3f; \ + spu2Ru16(lo) = (value)&0xffff; \ + } \ #define C0_IRQA SPU2_GET32BIT(REG_C0_IRQA_LO, REG_C0_IRQA_HI) #define C1_IRQA SPU2_GET32BIT(REG_C1_IRQA_LO, REG_C1_IRQA_HI) @@ -315,20 +338,20 @@ extern __forceinline void pcsx2_aligned_free(void* pmem) #define C0_SPUADDR_SET(value) SPU2_SET32BIT(value, REG_C0_SPUADDR_LO, REG_C0_SPUADDR_HI) #define C1_SPUADDR_SET(value) SPU2_SET32BIT(value, REG_C1_SPUADDR_LO, REG_C1_SPUADDR_HI) -#define SPU_NUMBER_VOICES 48 +#define SPU_NUMBER_VOICES 48 struct SPU_CONTROL_ { - u16 extCd : 1; - u16 extAudio : 1; - u16 cdreverb : 1; - u16 extr : 1; // external reverb - u16 dma : 2; // 1 - no dma, 2 - write, 3 - read - u16 irq : 1; - u16 reverb : 1; - u16 noiseFreq : 6; - u16 spuUnmute : 1; - u16 spuon : 1; + u16 extCd : 1; + u16 extAudio : 1; + u16 cdreverb : 1; + u16 extr : 1; // external reverb + u16 dma : 2; // 1 - no dma, 2 - write, 3 - read + u16 irq : 1; + u16 reverb : 1; + u16 noiseFreq : 6; + u16 spuUnmute : 1; + u16 spuon : 1; }; #if defined(_MSC_VER) @@ -337,42 +360,42 @@ struct SPU_CONTROL_ // the layout of each voice in wSpuRegs struct _SPU_VOICE { - union - { - struct { - u16 Vol : 14; - u16 Inverted : 1; - u16 Sweep0 : 1; - } vol; - struct { - u16 Vol : 7; - u16 res1 : 5; - u16 Inverted : 1; - u16 Decrease : 1; // if 0, increase - u16 ExpSlope : 1; // if 0, linear slope - u16 Sweep1 : 1; // always one - } sweep; - u16 word; - } left, right; + union + { + struct { + u16 Vol : 14; + u16 Inverted : 1; + u16 Sweep0 : 1; + } vol; + struct { + u16 Vol : 7; + u16 res1 : 5; + u16 Inverted : 1; + u16 Decrease : 1; // if 0, increase + u16 ExpSlope : 1; // if 0, linear slope + u16 Sweep1 : 1; // always one + } sweep; + u16 word; + } left, right; - u16 pitch : 14; // 1000 - no pitch, 2000 - pitch + 1, etc - u16 res0 : 2; + u16 pitch : 14; // 1000 - no pitch, 2000 - pitch + 1, etc + u16 res0 : 2; - u16 SustainLvl : 4; - u16 DecayRate : 4; - u16 AttackRate : 7; - u16 AttackExp : 1; // if 0, linear - - u16 ReleaseRate : 5; - u16 ReleaseExp : 1; // if 0, linear - u16 SustainRate : 7; - u16 res1 : 1; - u16 SustainDec : 1; // if 0, inc - u16 SustainExp : 1; // if 0, linear - - u16 AdsrVol; - u16 Address; // add / 8 - u16 RepeatAddr; // gets reset when sample starts + u16 SustainLvl : 4; + u16 DecayRate : 4; + u16 AttackRate : 7; + u16 AttackExp : 1; // if 0, linear + + u16 ReleaseRate : 5; + u16 ReleaseExp : 1; // if 0, linear + u16 SustainRate : 7; + u16 res1 : 1; + u16 SustainDec : 1; // if 0, inc + u16 SustainExp : 1; // if 0, linear + + u16 AdsrVol; + u16 Address; // add / 8 + u16 RepeatAddr; // gets reset when sample starts #if defined(_MSC_VER) }; //+22 #else @@ -382,84 +405,84 @@ struct _SPU_VOICE // ADSR INFOS PER CHANNEL struct ADSRInfoEx { - int State; - int AttackModeExp; - int AttackRate; - int DecayRate; - int SustainLevel; - int SustainModeExp; - int SustainIncrease; - int SustainRate; - int ReleaseModeExp; - int ReleaseRate; - int EnvelopeVol; - long lVolume; + int State; + int AttackModeExp; + int AttackRate; + int DecayRate; + int SustainLevel; + int SustainModeExp; + int SustainIncrease; + int SustainRate; + int ReleaseModeExp; + int ReleaseRate; + int EnvelopeVol; + long lVolume; }; #define SPU_VOICE_STATE_SIZE (sizeof(VOICE_PROCESSED)-4*sizeof(void*)) struct VOICE_PROCESSED { - VOICE_PROCESSED() - { - memset(this, 0, sizeof(VOICE_PROCESSED)); - } + VOICE_PROCESSED() + { + memset(this, 0, sizeof(VOICE_PROCESSED)); + } - void SetVolume(int right); - void StartSound(); - void VoiceChangeFrequency(); - void InterpolateUp(); - void InterpolateDown(); - void FModChangeFrequency(int ns); - int iGetNoiseVal(); - void StoreInterpolationVal(int fa); - int iGetInterpolationVal(); - void Stop(); + void SetVolume(int right); + void StartSound(); + void VoiceChangeFrequency(); + void InterpolateUp(); + void InterpolateDown(); + void FModChangeFrequency(int ns); + int iGetNoiseVal(); + void StoreInterpolationVal(int fa); + int iGetInterpolationVal(); + void Stop(); - SPU_CONTROL_* GetCtrl(); + SPU_CONTROL_* GetCtrl(); - // start save state - int leftvol, rightvol; // left right volumes + // start save state + int leftvol, rightvol; // left right volumes - int iSBPos; // mixing stuff - int SB[32+32]; - int spos; - int sinc; + int iSBPos; // mixing stuff + int SB[32+32]; + int spos; + int sinc; - int iIrqDone; // debug irq done flag - int s_1; // last decoding infos - int s_2; - int iOldNoise; // old noise val for this channel - int iActFreq; // current psx pitch - int iUsedFreq; // current pc pitch + int iIrqDone; // debug irq done flag + int s_1; // last decoding infos + int s_2; + int iOldNoise; // old noise val for this channel + int iActFreq; // current psx pitch + int iUsedFreq; // current pc pitch - int iStartAddr, iLoopAddr, iNextAddr; - int bFMod; + int iStartAddr, iLoopAddr, iNextAddr; + int bFMod; - ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) - int memoffset; // if first core, 0, if second, 0x400 - int chanid; // channel id + ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) + int memoffset; // if first core, 0, if second, 0x400 + int chanid; // channel id - bool bIgnoreLoop, bNew, bNoise, bReverb, bOn, bStop, bVolChanged; - bool bVolumeR, bVolumeL; - - // end save state + bool bIgnoreLoop, bNew, bNoise, bReverb, bOn, bStop, bVolChanged; + bool bVolumeR, bVolumeL; + + // end save state - /////////////////// - // Sound Buffers // - /////////////////// - u8* pStart; // start and end addresses - u8* pLoop, *pCurr; + /////////////////// + // Sound Buffers // + /////////////////// + u8* pStart; // start and end addresses + u8* pLoop, *pCurr; - _SPU_VOICE* pvoice; + _SPU_VOICE* pvoice; }; struct ADMA { - unsigned short * MemAddr; - int Index; - int AmountLeft; - int Enabled; // used to make sure that ADMA doesn't get interrupted with a writeDMA call + unsigned short * MemAddr; + int Index; + int AmountLeft; + int Enabled; // used to make sure that ADMA doesn't get interrupted with a writeDMA call }; #endif /* __SPU2_H__ */