#include "stdafx.h"
#define _IN_REGISTERS
#include "../peops2/externals.h"
#include "../peops2/registers.h"
#include "../peops2/regs.h"
#include "../peops2/reverb.h"
#define ATTACK_MS 494L
#define DECAYHALF_MS 286L
#define DECAY_MS 572L
#define SUSTAIN_MS 441L
#define RELEASE_MS 437L
void SetVolumeL(unsigned char ch,short vol);
void SetVolumeR(unsigned char ch,short vol);
void ReverbOn(int start,int end,unsigned short val,int iRight);
void SetReverbAddr(int core);
void VolumeOn(int start,int end,unsigned short val,int iRight);
EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val)
{
long r=reg&0xffff;
regArea[r>>1] = val;
if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580)) {
int ch=(r>>4)&0x1f;
if(r>=0x400) ch+=24;
switch(r&0x0f)
{
case 0:
SetVolumeL((unsigned char)ch,val);
break;
case 2:
SetVolumeR((unsigned char)ch,val);
break;
case 4:
SetPitch(ch,val);
break;
case 6:
{
const unsigned long lval=val;unsigned long lx;
s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0;
s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
if(!iDebugMode) break;
s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0;
lx=(((lval>>8) & 0x007f)>>2); lx=min(31,lx); if(lx)
{
lx = (1<<lx);
if(lx<2147483) lx=(lx*ATTACK_MS)/10000L; else lx=(lx/10000L)*ATTACK_MS;
if(!lx) lx=1;
}
s_chan[ch].ADSR.AttackTime=lx;
s_chan[ch].ADSR.SustainLevel= (1024*((lval) & 0x000f))/15;
lx=(lval>>4) & 0x000f; if(lx) {
lx = ((1<<(lx))*DECAY_MS)/10000L;
if(!lx) lx=1;
}
s_chan[ch].ADSR.DecayTime = (lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024;
}
break;
case 8:
{
const unsigned long lval=val;unsigned long lx;
s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;
s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
if(!iDebugMode) break;
s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0;
s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0;
lx=((((lval>>6) & 0x007f)>>2)); lx=min(31,lx); if(lx) { lx = (1<<lx); if(lx<2147483) lx=(lx*SUSTAIN_MS)/10000L; else lx=(lx/10000L)*SUSTAIN_MS; if(!lx) lx=1; }
s_chan[ch].ADSR.SustainTime = lx;
lx=(lval & 0x001f);
s_chan[ch].ADSR.ReleaseVal =lx;
if(lx) { lx = (1<<lx); if(lx<2147483) lx=(lx*RELEASE_MS)/10000L; else lx=(lx/10000L)*RELEASE_MS; if(!lx) lx=1;
}
s_chan[ch].ADSR.ReleaseTime=lx;
if(lval & 0x4000) s_chan[ch].ADSR.SustainModeDec=-1;
else s_chan[ch].ADSR.SustainModeDec=1;
}
break;
}
iSpuAsyncWait=0;
return;
}
if((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0)) {
int ch=0;
if(r>=0x400) {ch=24;r-=0x400;}
ch+=(r-0x1c0)/12;
r-=(ch%24)*12;
switch(r)
{
case 0x1C0:
s_chan[ch].iStartAdr=(((unsigned long)val&0xf)<<16)|(s_chan[ch].iStartAdr&0xFFFF);
s_chan[ch].pStart=spuMemC+(s_chan[ch].iStartAdr<<1);
break;
case 0x1C2:
s_chan[ch].iStartAdr=(s_chan[ch].iStartAdr & 0xF0000) | (val & 0xFFFF);
s_chan[ch].pStart=spuMemC+(s_chan[ch].iStartAdr<<1);
break;
case 0x1C4:
s_chan[ch].iLoopAdr=(((unsigned long)val&0xf)<<16)|(s_chan[ch].iLoopAdr&0xFFFF);
s_chan[ch].pLoop=spuMemC+(s_chan[ch].iLoopAdr<<1);
s_chan[ch].bIgnoreLoop=1;
break;
case 0x1C6:
s_chan[ch].iLoopAdr=(s_chan[ch].iLoopAdr & 0xF0000) | (val & 0xFFFF);
s_chan[ch].pLoop=spuMemC+(s_chan[ch].iLoopAdr<<1);
s_chan[ch].bIgnoreLoop=1;
break;
case 0x1C8:
s_chan[ch].iNextAdr=(((unsigned long)val&0xf)<<16)|(s_chan[ch].iNextAdr&0xFFFF);
break;
case 0x1CA:
s_chan[ch].iNextAdr=(s_chan[ch].iNextAdr & 0xF0000) | (val & 0xFFFF);
break;
}
iSpuAsyncWait=0;
return;
}
switch(r)
{
case PS2_C0_SPUaddr_Hi:
spuAddr2[0] = (((unsigned long)val&0xf)<<16)|(spuAddr2[0]&0xFFFF);
break;
case PS2_C0_SPUaddr_Lo:
spuAddr2[0] = (spuAddr2[0] & 0xF0000) | (val & 0xFFFF);
break;
case PS2_C1_SPUaddr_Hi:
spuAddr2[1] = (((unsigned long)val&0xf)<<16)|(spuAddr2[1]&0xFFFF);
break;
case PS2_C1_SPUaddr_Lo:
spuAddr2[1] = (spuAddr2[1] & 0xF0000) | (val & 0xFFFF);
break;
case PS2_C0_SPUdata:
spuMem[spuAddr2[0]] = val;
spuAddr2[0]++;
if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
break;
case PS2_C1_SPUdata:
spuMem[spuAddr2[1]] = val;
spuAddr2[1]++;
if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;
break;
case PS2_C0_ATTR:
spuCtrl2[0]=val;
break;
case PS2_C1_ATTR:
spuCtrl2[1]=val;
break;
case PS2_C0_SPUstat:
spuStat2[0]=val;
break;
case PS2_C1_SPUstat:
spuStat2[1]=val;
break;
case PS2_C0_ReverbAddr_Hi:
spuRvbAddr2[0] = (((unsigned long)val&0xf)<<16)|(spuRvbAddr2[0]&0xFFFF);
SetReverbAddr(0);
break;
case PS2_C0_ReverbAddr_Lo:
spuRvbAddr2[0] = (spuRvbAddr2[0] & 0xF0000) | (val & 0xFFFF);
SetReverbAddr(0);
break;
case PS2_C0_ReverbAEnd_Hi:
spuRvbAEnd2[0] = (((unsigned long)val&0xf)<<16)|(0xFFFF);
rvb[0].EndAddr=spuRvbAEnd2[0];
break;
case PS2_C1_ReverbAEnd_Hi:
spuRvbAEnd2[1] = (((unsigned long)val&0xf)<<16)|(0xFFFF);
rvb[1].EndAddr=spuRvbAEnd2[1];
break;
case PS2_C1_ReverbAddr_Hi:
spuRvbAddr2[1] = (((unsigned long)val&0xf)<<16)|(spuRvbAddr2[1]&0xFFFF);
SetReverbAddr(1);
break;
case PS2_C1_ReverbAddr_Lo:
spuRvbAddr2[1] = (spuRvbAddr2[1] & 0xF0000) | (val & 0xFFFF);
SetReverbAddr(1);
break;
case PS2_C0_SPUirqAddr_Hi:
spuIrq2[0] = (((unsigned long)val&0xf)<<16)|(spuIrq2[0]&0xFFFF);
pSpuIrq[0]=spuMemC+(spuIrq2[0]<<1);
break;
case PS2_C0_SPUirqAddr_Lo:
spuIrq2[0] = (spuIrq2[0] & 0xF0000) | (val & 0xFFFF);
pSpuIrq[0]=spuMemC+(spuIrq2[0]<<1);
break;
case PS2_C1_SPUirqAddr_Hi:
spuIrq2[1] = (((unsigned long)val&0xf)<<16)|(spuIrq2[1]&0xFFFF);
pSpuIrq[1]=spuMemC+(spuIrq2[1]<<1);
break;
case PS2_C1_SPUirqAddr_Lo:
spuIrq2[1] = (spuIrq2[1] & 0xF0000) | (val & 0xFFFF);
pSpuIrq[1]=spuMemC+(spuIrq2[1]<<1);
break;
case PS2_C0_SPUrvolL:
rvb[0].VolLeft=val;
break;
case PS2_C0_SPUrvolR:
rvb[0].VolRight=val;
break;
case PS2_C1_SPUrvolL:
rvb[1].VolLeft=val;
break;
case PS2_C1_SPUrvolR:
rvb[1].VolRight=val;
break;
case PS2_C0_SPUon1:
SoundOn(0,16,val);
break;
case PS2_C0_SPUon2:
SoundOn(16,24,val);
break;
case PS2_C1_SPUon1:
SoundOn(24,40,val);
break;
case PS2_C1_SPUon2:
SoundOn(40,48,val);
break;
case PS2_C0_SPUoff1:
SoundOff(0,16,val);
break;
case PS2_C0_SPUoff2:
SoundOff(16,24,val);
break;
case PS2_C1_SPUoff1:
SoundOff(24,40,val);
break;
case PS2_C1_SPUoff2:
SoundOff(40,48,val);
break;
case PS2_C0_SPUend1:
case PS2_C0_SPUend2:
if(val) dwEndChannel2[0]=0;
break;
case PS2_C1_SPUend1:
case PS2_C1_SPUend2:
if(val) dwEndChannel2[1]=0;
break;
case PS2_C0_FMod1:
FModOn(0,16,val);
break;
case PS2_C0_FMod2:
FModOn(16,24,val);
break;
case PS2_C1_FMod1:
FModOn(24,40,val);
break;
case PS2_C1_FMod2:
FModOn(40,48,val);
break;
case PS2_C0_Noise1:
NoiseOn(0,16,val);
break;
case PS2_C0_Noise2:
NoiseOn(16,24,val);
break;
case PS2_C1_Noise1:
NoiseOn(24,40,val);
break;
case PS2_C1_Noise2:
NoiseOn(40,48,val);
break;
case PS2_C0_DryL1:
VolumeOn(0,16,val,0);
break;
case PS2_C0_DryL2:
VolumeOn(16,24,val,0);
break;
case PS2_C1_DryL1:
VolumeOn(24,40,val,0);
break;
case PS2_C1_DryL2:
VolumeOn(40,48,val,0);
break;
case PS2_C0_DryR1:
VolumeOn(0,16,val,1);
break;
case PS2_C0_DryR2:
VolumeOn(16,24,val,1);
break;
case PS2_C1_DryR1:
VolumeOn(24,40,val,1);
break;
case PS2_C1_DryR2:
VolumeOn(40,48,val,1);
break;
case PS2_C0_RVBon1_L:
ReverbOn(0,16,val,0);
break;
case PS2_C0_RVBon2_L:
ReverbOn(16,24,val,0);
break;
case PS2_C1_RVBon1_L:
ReverbOn(24,40,val,0);
break;
case PS2_C1_RVBon2_L:
ReverbOn(40,48,val,0);
break;
case PS2_C0_RVBon1_R:
ReverbOn(0,16,val,1);
break;
case PS2_C0_RVBon2_R:
ReverbOn(16,24,val,1);
break;
case PS2_C1_RVBon1_R:
ReverbOn(24,40,val,1);
break;
case PS2_C1_RVBon2_R:
ReverbOn(40,48,val,1);
break;
case PS2_C0_Reverb+0:
rvb[0].FB_SRC_A=(((unsigned long)val&0xf)<<16)|(rvb[0].FB_SRC_A&0xFFFF);
break;
case PS2_C0_Reverb+2:
rvb[0].FB_SRC_A=(rvb[0].FB_SRC_A & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+4:
rvb[0].FB_SRC_B=(((unsigned long)val&0xf)<<16)|(rvb[0].FB_SRC_B&0xFFFF);
break;
case PS2_C0_Reverb+6:
rvb[0].FB_SRC_B=(rvb[0].FB_SRC_B & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+8:
rvb[0].IIR_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_A0&0xFFFF);
break;
case PS2_C0_Reverb+10:
rvb[0].IIR_DEST_A0=(rvb[0].IIR_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+12:
rvb[0].IIR_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_A1&0xFFFF);
break;
case PS2_C0_Reverb+14:
rvb[0].IIR_DEST_A1=(rvb[0].IIR_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+16:
rvb[0].ACC_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_A0&0xFFFF);
break;
case PS2_C0_Reverb+18:
rvb[0].ACC_SRC_A0=(rvb[0].ACC_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+20:
rvb[0].ACC_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_A1&0xFFFF);
break;
case PS2_C0_Reverb+22:
rvb[0].ACC_SRC_A1=(rvb[0].ACC_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+24:
rvb[0].ACC_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_B0&0xFFFF);
break;
case PS2_C0_Reverb+26:
rvb[0].ACC_SRC_B0=(rvb[0].ACC_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+28:
rvb[0].ACC_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_B1&0xFFFF);
break;
case PS2_C0_Reverb+30:
rvb[0].ACC_SRC_B1=(rvb[0].ACC_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+32:
rvb[0].IIR_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_A0&0xFFFF);
break;
case PS2_C0_Reverb+34:
rvb[0].IIR_SRC_A0=(rvb[0].IIR_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+36:
rvb[0].IIR_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_A1&0xFFFF);
break;
case PS2_C0_Reverb+38:
rvb[0].IIR_SRC_A1=(rvb[0].IIR_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+40:
rvb[0].IIR_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_B0&0xFFFF);
break;
case PS2_C0_Reverb+42:
rvb[0].IIR_DEST_B0=(rvb[0].IIR_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+44:
rvb[0].IIR_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_B1&0xFFFF);
break;
case PS2_C0_Reverb+46:
rvb[0].IIR_DEST_B1=(rvb[0].IIR_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+48:
rvb[0].ACC_SRC_C0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_C0&0xFFFF);
break;
case PS2_C0_Reverb+50:
rvb[0].ACC_SRC_C0=(rvb[0].ACC_SRC_C0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+52:
rvb[0].ACC_SRC_C1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_C1&0xFFFF);
break;
case PS2_C0_Reverb+54:
rvb[0].ACC_SRC_C1=(rvb[0].ACC_SRC_C1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+56:
rvb[0].ACC_SRC_D0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_D0&0xFFFF);
break;
case PS2_C0_Reverb+58:
rvb[0].ACC_SRC_D0=(rvb[0].ACC_SRC_D0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+60:
rvb[0].ACC_SRC_D1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_D1&0xFFFF);
break;
case PS2_C0_Reverb+62:
rvb[0].ACC_SRC_D1=(rvb[0].ACC_SRC_D1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+64:
rvb[0].IIR_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_B1&0xFFFF);
break;
case PS2_C0_Reverb+66:
rvb[0].IIR_SRC_B1=(rvb[0].IIR_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+68:
rvb[0].IIR_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_B0&0xFFFF);
break;
case PS2_C0_Reverb+70:
rvb[0].IIR_SRC_B0=(rvb[0].IIR_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+72:
rvb[0].MIX_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_A0&0xFFFF);
break;
case PS2_C0_Reverb+74:
rvb[0].MIX_DEST_A0=(rvb[0].MIX_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+76:
rvb[0].MIX_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_A1&0xFFFF);
break;
case PS2_C0_Reverb+78:
rvb[0].MIX_DEST_A1=(rvb[0].MIX_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+80:
rvb[0].MIX_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_B0&0xFFFF);
break;
case PS2_C0_Reverb+82:
rvb[0].MIX_DEST_B0=(rvb[0].MIX_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_Reverb+84:
rvb[0].MIX_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_B1&0xFFFF);
break;
case PS2_C0_Reverb+86:
rvb[0].MIX_DEST_B1=(rvb[0].MIX_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C0_ReverbX+0: rvb[0].IIR_ALPHA=(short)val; break;
case PS2_C0_ReverbX+2: rvb[0].ACC_COEF_A=(short)val; break;
case PS2_C0_ReverbX+4: rvb[0].ACC_COEF_B=(short)val; break;
case PS2_C0_ReverbX+6: rvb[0].ACC_COEF_C=(short)val; break;
case PS2_C0_ReverbX+8: rvb[0].ACC_COEF_D=(short)val; break;
case PS2_C0_ReverbX+10: rvb[0].IIR_COEF=(short)val; break;
case PS2_C0_ReverbX+12: rvb[0].FB_ALPHA=(short)val; break;
case PS2_C0_ReverbX+14: rvb[0].FB_X=(short)val; break;
case PS2_C0_ReverbX+16: rvb[0].IN_COEF_L=(short)val; break;
case PS2_C0_ReverbX+18: rvb[0].IN_COEF_R=(short)val; break;
case PS2_C1_Reverb+0:
rvb[1].FB_SRC_A=(((unsigned long)val&0xf)<<16)|(rvb[1].FB_SRC_A&0xFFFF);
break;
case PS2_C1_Reverb+2:
rvb[1].FB_SRC_A=(rvb[1].FB_SRC_A & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+4:
rvb[1].FB_SRC_B=(((unsigned long)val&0xf)<<16)|(rvb[1].FB_SRC_B&0xFFFF);
break;
case PS2_C1_Reverb+6:
rvb[1].FB_SRC_B=(rvb[1].FB_SRC_B & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+8:
rvb[1].IIR_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_A0&0xFFFF);
break;
case PS2_C1_Reverb+10:
rvb[1].IIR_DEST_A0=(rvb[1].IIR_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+12:
rvb[1].IIR_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_A1&0xFFFF);
break;
case PS2_C1_Reverb+14:
rvb[1].IIR_DEST_A1=(rvb[1].IIR_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+16:
rvb[1].ACC_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_A0&0xFFFF);
break;
case PS2_C1_Reverb+18:
rvb[1].ACC_SRC_A0=(rvb[1].ACC_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+20:
rvb[1].ACC_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_A1&0xFFFF);
break;
case PS2_C1_Reverb+22:
rvb[1].ACC_SRC_A1=(rvb[1].ACC_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+24:
rvb[1].ACC_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_B0&0xFFFF);
break;
case PS2_C1_Reverb+26:
rvb[1].ACC_SRC_B0=(rvb[1].ACC_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+28:
rvb[1].ACC_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_B1&0xFFFF);
break;
case PS2_C1_Reverb+30:
rvb[1].ACC_SRC_B1=(rvb[1].ACC_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+32:
rvb[1].IIR_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_A0&0xFFFF);
break;
case PS2_C1_Reverb+34:
rvb[1].IIR_SRC_A0=(rvb[1].IIR_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+36:
rvb[1].IIR_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_A1&0xFFFF);
break;
case PS2_C1_Reverb+38:
rvb[1].IIR_SRC_A1=(rvb[1].IIR_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+40:
rvb[1].IIR_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_B0&0xFFFF);
break;
case PS2_C1_Reverb+42:
rvb[1].IIR_DEST_B0=(rvb[1].IIR_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+44:
rvb[1].IIR_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_B1&0xFFFF);
break;
case PS2_C1_Reverb+46:
rvb[1].IIR_DEST_B1=(rvb[1].IIR_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+48:
rvb[1].ACC_SRC_C0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_C0&0xFFFF);
break;
case PS2_C1_Reverb+50:
rvb[1].ACC_SRC_C0=(rvb[1].ACC_SRC_C0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+52:
rvb[1].ACC_SRC_C1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_C1&0xFFFF);
break;
case PS2_C1_Reverb+54:
rvb[1].ACC_SRC_C1=(rvb[1].ACC_SRC_C1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+56:
rvb[1].ACC_SRC_D0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_D0&0xFFFF);
break;
case PS2_C1_Reverb+58:
rvb[1].ACC_SRC_D0=(rvb[1].ACC_SRC_D0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+60:
rvb[1].ACC_SRC_D1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_D1&0xFFFF);
break;
case PS2_C1_Reverb+62:
rvb[1].ACC_SRC_D1=(rvb[1].ACC_SRC_D1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+64:
rvb[1].IIR_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_B1&0xFFFF);
break;
case PS2_C1_Reverb+66:
rvb[1].IIR_SRC_B1=(rvb[1].IIR_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+68:
rvb[1].IIR_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_B0&0xFFFF);
break;
case PS2_C1_Reverb+70:
rvb[1].IIR_SRC_B0=(rvb[1].IIR_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+72:
rvb[1].MIX_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_A0&0xFFFF);
break;
case PS2_C1_Reverb+74:
rvb[1].MIX_DEST_A0=(rvb[1].MIX_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+76:
rvb[1].MIX_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_A1&0xFFFF);
break;
case PS2_C1_Reverb+78:
rvb[1].MIX_DEST_A1=(rvb[1].MIX_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+80:
rvb[1].MIX_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_B0&0xFFFF);
break;
case PS2_C1_Reverb+82:
rvb[1].MIX_DEST_B0=(rvb[1].MIX_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_Reverb+84:
rvb[1].MIX_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_B1&0xFFFF);
break;
case PS2_C1_Reverb+86:
rvb[1].MIX_DEST_B1=(rvb[1].MIX_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
break;
case PS2_C1_ReverbX+0: rvb[1].IIR_ALPHA=(short)val; break;
case PS2_C1_ReverbX+2: rvb[1].ACC_COEF_A=(short)val; break;
case PS2_C1_ReverbX+4: rvb[1].ACC_COEF_B=(short)val; break;
case PS2_C1_ReverbX+6: rvb[1].ACC_COEF_C=(short)val; break;
case PS2_C1_ReverbX+8: rvb[1].ACC_COEF_D=(short)val; break;
case PS2_C1_ReverbX+10: rvb[1].IIR_COEF=(short)val; break;
case PS2_C1_ReverbX+12: rvb[1].FB_ALPHA=(short)val; break;
case PS2_C1_ReverbX+14: rvb[1].FB_X=(short)val; break;
case PS2_C1_ReverbX+16: rvb[1].IN_COEF_L=(short)val; break;
case PS2_C1_ReverbX+18: rvb[1].IN_COEF_R=(short)val; break;
}
iSpuAsyncWait=0;
}
EXPORT_GCC unsigned short CALLBACK SPU2read(unsigned long reg)
{
long r=reg&0xffff;
#ifdef _WINDOWS
#endif
iSpuAsyncWait=0;
if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580)) {
switch(r&0x0f)
{
case 10:
{
int ch=(r>>4)&0x1f;
if(r>=0x400) ch+=24;
if(s_chan[ch].bNew) return 1; if(s_chan[ch].ADSRX.lVolume && !s_chan[ch].ADSRX.EnvelopeVol)
return 1;
return (unsigned short)(s_chan[ch].ADSRX.EnvelopeVol>>16);
}break;
}
}
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;
switch(rx)
{
case 0x1C4:
return (((s_chan[ch].pLoop-spuMemC)>>17)&0xF);
break;
case 0x1C6:
return (((s_chan[ch].pLoop-spuMemC)>>1)&0xFFFF);
break;
case 0x1C8:
return (((s_chan[ch].pCurr-spuMemC)>>17)&0xF);
break;
case 0x1CA:
return (((s_chan[ch].pCurr-spuMemC)>>1)&0xFFFF);
break;
}
}
switch(r)
{
case PS2_C0_SPUend1:
return (unsigned short)((dwEndChannel2[0]&0xFFFF));
case PS2_C0_SPUend2:
return (unsigned short)((dwEndChannel2[0]>>16));
case PS2_C1_SPUend1:
return (unsigned short)((dwEndChannel2[1]&0xFFFF));
case PS2_C1_SPUend2:
return (unsigned short)((dwEndChannel2[1]>>16));
case PS2_C0_ATTR:
return spuCtrl2[0];
break;
case PS2_C1_ATTR:
return spuCtrl2[1];
break;
case PS2_C0_SPUstat:
return spuStat2[0];
break;
case PS2_C1_SPUstat:
return spuStat2[1];
break;
case PS2_C0_SPUdata:
{
unsigned short s=spuMem[spuAddr2[0]];
spuAddr2[0]++;
if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
return s;
}
case PS2_C1_SPUdata:
{
unsigned short s=spuMem[spuAddr2[1]];
spuAddr2[1]++;
if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;
return s;
}
case PS2_C0_SPUaddr_Hi:
return (unsigned short)((spuAddr2[0]>>16)&0xF);
break;
case PS2_C0_SPUaddr_Lo:
return (unsigned short)((spuAddr2[0]&0xFFFF));
break;
case PS2_C1_SPUaddr_Hi:
return (unsigned short)((spuAddr2[1]>>16)&0xF);
break;
case PS2_C1_SPUaddr_Lo:
return (unsigned short)((spuAddr2[1]&0xFFFF));
break;
}
return regArea[r>>1];
}
EXPORT_GCC void CALLBACK SPU2writePS1Port(unsigned long reg, unsigned short val)
{
const u32 r=reg&0xfff;
if(r>=0xc00 && r<0xd80) {
SPU2write(r-0xc00, val);
return;
}
switch(r)
{
case H_SPUaddr:
spuAddr2[0] = (u32) val<<2;
break;
case H_SPUdata:
spuMem[spuAddr2[0]] = BFLIP16(val);
spuAddr2[0]++;
if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
break;
case H_SPUctrl:
break;
case H_SPUstat:
spuStat2[0]=val & 0xf800;
break;
case H_SPUReverbAddr:
spuRvbAddr2[0] = val;
SetReverbAddr(0);
break;
case H_SPUirqAddr:
spuIrq2[0] = val<<2;
pSpuIrq[0]=spuMemC+((u32) val<<1);
break;
case H_SPUrvolL:
rvb[0].VolLeft=(s16)val;
break;
case H_SPUrvolR:
rvb[0].VolRight=(s16)val;
break;
case H_SPUon1:
SoundOn(0,16,val);
break;
case H_SPUon2:
SoundOn(16,24,val);
break;
case H_SPUoff1:
SoundOff(0,16,val);
break;
case H_SPUoff2:
SoundOff(16,24,val);
break;
case H_FMod1:
FModOn(0,16,val);
break;
case H_FMod2:
FModOn(16,24,val);
break;
case H_Noise1:
NoiseOn(0,16,val);
break;
case H_Noise2:
NoiseOn(16,24,val);
break;
case H_RVBon1:
ReverbOn(0,16,val,0);
break;
case H_RVBon2:
ReverbOn(16,24,val,0);
break;
case H_Reverb+0:
rvb[0].FB_SRC_A=val;
break;
case H_Reverb+2 : rvb[0].FB_SRC_B=(s16)val; break;
case H_Reverb+4 : rvb[0].IIR_ALPHA=(s16)val; break;
case H_Reverb+6 : rvb[0].ACC_COEF_A=(s16)val; break;
case H_Reverb+8 : rvb[0].ACC_COEF_B=(s16)val; break;
case H_Reverb+10 : rvb[0].ACC_COEF_C=(s16)val; break;
case H_Reverb+12 : rvb[0].ACC_COEF_D=(s16)val; break;
case H_Reverb+14 : rvb[0].IIR_COEF=(s16)val; break;
case H_Reverb+16 : rvb[0].FB_ALPHA=(s16)val; break;
case H_Reverb+18 : rvb[0].FB_X=(s16)val; break;
case H_Reverb+20 : rvb[0].IIR_DEST_A0=(s16)val; break;
case H_Reverb+22 : rvb[0].IIR_DEST_A1=(s16)val; break;
case H_Reverb+24 : rvb[0].ACC_SRC_A0=(s16)val; break;
case H_Reverb+26 : rvb[0].ACC_SRC_A1=(s16)val; break;
case H_Reverb+28 : rvb[0].ACC_SRC_B0=(s16)val; break;
case H_Reverb+30 : rvb[0].ACC_SRC_B1=(s16)val; break;
case H_Reverb+32 : rvb[0].IIR_SRC_A0=(s16)val; break;
case H_Reverb+34 : rvb[0].IIR_SRC_A1=(s16)val; break;
case H_Reverb+36 : rvb[0].IIR_DEST_B0=(s16)val; break;
case H_Reverb+38 : rvb[0].IIR_DEST_B1=(s16)val; break;
case H_Reverb+40 : rvb[0].ACC_SRC_C0=(s16)val; break;
case H_Reverb+42 : rvb[0].ACC_SRC_C1=(s16)val; break;
case H_Reverb+44 : rvb[0].ACC_SRC_D0=(s16)val; break;
case H_Reverb+46 : rvb[0].ACC_SRC_D1=(s16)val; break;
case H_Reverb+48 : rvb[0].IIR_SRC_B1=(s16)val; break;
case H_Reverb+50 : rvb[0].IIR_SRC_B0=(s16)val; break;
case H_Reverb+52 : rvb[0].MIX_DEST_A0=(s16)val; break;
case H_Reverb+54 : rvb[0].MIX_DEST_A1=(s16)val; break;
case H_Reverb+56 : rvb[0].MIX_DEST_B0=(s16)val; break;
case H_Reverb+58 : rvb[0].MIX_DEST_B1=(s16)val; break;
case H_Reverb+60 : rvb[0].IN_COEF_L=(s16)val; break;
case H_Reverb+62 : rvb[0].IN_COEF_R=(s16)val; break;
}
}
EXPORT_GCC unsigned short CALLBACK SPU2readPS1Port(unsigned long reg)
{
const u32 r=reg&0xfff;
if(r>=0x0c00 && r<0x0d80)
{
return SPU2read(r-0xc00);
}
switch(r)
{
break;
case H_SPUstat:
return spuStat2[0];
break;
case H_SPUaddr:
return (u16)(spuAddr2[0]>>2);
break;
case H_SPUdata:
{
u16 s=BFLIP16(spuMem[spuAddr2[0]]);
spuAddr2[0]++;
if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
return s;
}
break;
case H_SPUirqAddr:
return spuIrq2[0]>>2;
break;
}
return 0;
}
void SoundOn(int start,int end,unsigned short val) {
int ch;
for(ch=start;ch<end;ch++,val>>=1) {
if((val&1) && s_chan[ch].pStart) {
s_chan[ch].bIgnoreLoop=0;
s_chan[ch].bNew=1;
dwNewChannel2[ch/24]|=(1<<(ch%24)); }
}
}
void SoundOff(int start,int end,unsigned short val) {
int ch;
for(ch=start;ch<end;ch++,val>>=1) {
if(val&1) {
s_chan[ch].bStop=1;
}
}
}
void FModOn(int start,int end,unsigned short val) {
int ch;
for(ch=start;ch<end;ch++,val>>=1) {
if(val&1) {
if(ch>0)
{
s_chan[ch].bFMod=1; s_chan[ch-1].bFMod=2; }
}
else
{
s_chan[ch].bFMod=0; }
}
}
void NoiseOn(int start,int end,unsigned short val) {
int ch;
for(ch=start;ch<end;ch++,val>>=1) {
if(val&1) {
s_chan[ch].bNoise=1;
}
else
{
s_chan[ch].bNoise=0;
}
}
}
void SetVolumeL(unsigned char ch,short vol) {
s_chan[ch].iLeftVolRaw=vol;
if(vol&0x8000) {
short sInc=1; if(vol&0x2000) sInc=-1; if(vol&0x1000) vol^=0xffff; vol=((vol&0x7f)+1)/2; vol+=vol/(2*sInc); vol*=128;
}
else {
if(vol&0x4000) vol=0x3fff-(vol&0x3fff);
}
vol&=0x3fff;
s_chan[ch].iLeftVolume=vol; }
void SetVolumeR(unsigned char ch,short vol) {
s_chan[ch].iRightVolRaw=vol;
if(vol&0x8000) {
short sInc=1;
if(vol&0x2000) sInc=-1;
if(vol&0x1000) vol^=0xffff;
vol=((vol&0x7f)+1)/2;
vol+=vol/(2*sInc);
vol*=128;
}
else
{
if(vol&0x4000) vol=0x3fff-(vol&0x3fff);
}
vol&=0x3fff;
s_chan[ch].iRightVolume=vol;
}
void SetPitch(int ch,unsigned short val) {
int NP;
double intr;
if(val>0x3fff) NP=0x3fff; else NP=val;
intr = (double)48000.0f / (double)44100.0f * (double)NP;
NP = (UINT32)intr;
s_chan[ch].iRawPitch=NP;
NP=(44100L*NP)/4096L;
if(NP<1) NP=1; s_chan[ch].iActFreq=NP; }
void ReverbOn(int start,int end,unsigned short val,int iRight) {
int ch;
for(ch=start;ch<end;ch++,val>>=1) {
if(val&1) {
if(iRight) s_chan[ch].bReverbR=1;
else s_chan[ch].bReverbL=1;
}
else
{
if(iRight) s_chan[ch].bReverbR=0;
else s_chan[ch].bReverbL=0;
}
}
}
void SetReverbAddr(int core)
{
long val=spuRvbAddr2[core];
if(rvb[core].StartAddr!=val)
{
if(val<=0x27ff)
{
rvb[core].StartAddr=rvb[core].CurrAddr=0;
}
else
{
rvb[core].StartAddr=val;
rvb[core].CurrAddr=rvb[core].StartAddr;
}
}
}
void VolumeOn(int start,int end,unsigned short val,int iRight) {
int ch;
for(ch=start;ch<end;ch++,val>>=1) {
if(val&1) {
if(iRight) s_chan[ch].bVolumeR=1;
else s_chan[ch].bVolumeL=1;
}
else
{
if(iRight) s_chan[ch].bVolumeR=0;
else s_chan[ch].bVolumeL=0;
}
}
}