#include "stdafx.h"
#define _IN_REGISTERS
#include "../peops/externals.h"
#include "../peops/registers.h"
#include "../peops/regs.h"
void SPUwriteRegister(u32 reg, u16 val)
{
const u32 r=reg&0xfff;
regArea[(r-0xc00)>>1] = val;
if(r>=0x0c00 && r<0x0d80) {
int ch=(r>>4)-0xc0;
switch(r&0x0f)
{
case 0:
SetVolumeLR(0,(u8)ch,val);
break;
case 2:
SetVolumeLR(1,(u8)ch,val);
break;
case 4:
SetPitch(ch,val);
break;
case 6:
s_chan[ch].pStart=spuMemC+((u32) val<<3);
break;
case 8:
{
const u32 lval=val; 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;
}
break;
case 10:
{
const u32 lval=val;
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;
}
break;
case 0xE: s_chan[ch].pLoop=spuMemC+((u32) val<<3);
s_chan[ch].bIgnoreLoop=1;
break;
}
return;
}
switch(r)
{
case H_SPUaddr:
spuAddr = (u32) val<<3;
break;
case H_SPUdata:
spuMem[spuAddr>>1] = BFLIP16(val);
spuAddr+=2;
if(spuAddr>0x7ffff) spuAddr=0;
break;
case H_SPUctrl:
spuCtrl=val;
break;
case H_SPUstat:
spuStat=val & 0xf800;
break;
case H_SPUReverbAddr:
if(val==0xFFFF || val<=0x200)
{rvb.StartAddr=rvb.CurrAddr=0;}
else
{
const s32 iv=(u32)val<<2;
if(rvb.StartAddr!=iv)
{
rvb.StartAddr=(u32)val<<2;
rvb.CurrAddr=rvb.StartAddr;
}
}
break;
case H_SPUirqAddr:
spuIrq = val;
pSpuIrq=spuMemC+((u32) val<<3);
break;
case H_SPUrvolL:
rvb.VolLeft=(s16)val;
break;
case H_SPUrvolR:
rvb.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:
rvb.Enabled&=~0xFFFF;
rvb.Enabled|=val;
break;
case H_RVBon2:
rvb.Enabled&=0xFFFF;
rvb.Enabled|=val<<16;
break;
case H_Reverb+0:
rvb.FB_SRC_A=val;
break;
case H_Reverb+2 : rvb.FB_SRC_B=(s16)val; break;
case H_Reverb+4 : rvb.IIR_ALPHA=(s16)val; break;
case H_Reverb+6 : rvb.ACC_COEF_A=(s16)val; break;
case H_Reverb+8 : rvb.ACC_COEF_B=(s16)val; break;
case H_Reverb+10 : rvb.ACC_COEF_C=(s16)val; break;
case H_Reverb+12 : rvb.ACC_COEF_D=(s16)val; break;
case H_Reverb+14 : rvb.IIR_COEF=(s16)val; break;
case H_Reverb+16 : rvb.FB_ALPHA=(s16)val; break;
case H_Reverb+18 : rvb.FB_X=(s16)val; break;
case H_Reverb+20 : rvb.IIR_DEST_A0=(s16)val; break;
case H_Reverb+22 : rvb.IIR_DEST_A1=(s16)val; break;
case H_Reverb+24 : rvb.ACC_SRC_A0=(s16)val; break;
case H_Reverb+26 : rvb.ACC_SRC_A1=(s16)val; break;
case H_Reverb+28 : rvb.ACC_SRC_B0=(s16)val; break;
case H_Reverb+30 : rvb.ACC_SRC_B1=(s16)val; break;
case H_Reverb+32 : rvb.IIR_SRC_A0=(s16)val; break;
case H_Reverb+34 : rvb.IIR_SRC_A1=(s16)val; break;
case H_Reverb+36 : rvb.IIR_DEST_B0=(s16)val; break;
case H_Reverb+38 : rvb.IIR_DEST_B1=(s16)val; break;
case H_Reverb+40 : rvb.ACC_SRC_C0=(s16)val; break;
case H_Reverb+42 : rvb.ACC_SRC_C1=(s16)val; break;
case H_Reverb+44 : rvb.ACC_SRC_D0=(s16)val; break;
case H_Reverb+46 : rvb.ACC_SRC_D1=(s16)val; break;
case H_Reverb+48 : rvb.IIR_SRC_B1=(s16)val; break;
case H_Reverb+50 : rvb.IIR_SRC_B0=(s16)val; break;
case H_Reverb+52 : rvb.MIX_DEST_A0=(s16)val; break;
case H_Reverb+54 : rvb.MIX_DEST_A1=(s16)val; break;
case H_Reverb+56 : rvb.MIX_DEST_B0=(s16)val; break;
case H_Reverb+58 : rvb.MIX_DEST_B1=(s16)val; break;
case H_Reverb+60 : rvb.IN_COEF_L=(s16)val; break;
case H_Reverb+62 : rvb.IN_COEF_R=(s16)val; break;
}
}
u16 SPUreadRegister(u32 reg)
{
const u32 r=reg&0xfff;
if(r>=0x0c00 && r<0x0d80)
{
switch(r&0x0f)
{
case 0xC: {
const int ch=(r>>4)-0xc0;
if(s_chan[ch].bNew) return 1; if(s_chan[ch].ADSRX.lVolume && !s_chan[ch].ADSRX.EnvelopeVol)
return 1;
return (u16)(s_chan[ch].ADSRX.EnvelopeVol>>16);
}
case 0xE: {
const int ch=(r>>4)-0xc0;
if(s_chan[ch].pLoop==NULL) return 0;
return (u16)((s_chan[ch].pLoop-spuMemC)>>3);
}
}
}
switch(r)
{
case H_SPUctrl:
return spuCtrl;
case H_SPUstat:
return spuStat;
case H_SPUaddr:
return (u16)(spuAddr>>3);
case H_SPUdata:
{
u16 s=BFLIP16(spuMem[spuAddr>>1]);
spuAddr+=2;
if(spuAddr>0x7ffff) spuAddr=0;
return s;
}
case H_SPUirqAddr:
return spuIrq;
}
return regArea[(r-0xc00)>>1];
}
static void SoundOn(int start,int end,u16 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;
}
}
}
static void SoundOff(int start,int end,u16 val) {
int ch;
for(ch=start;ch<end;ch++,val>>=1) {
if(val&1) {
s_chan[ch].bStop=1;
}
}
}
static void FModOn(int start,int end,u16 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; }
}
}
static void NoiseOn(int start,int end,u16 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;
}
}
}
static void SetVolumeLR(int right, u8 ch,s16 vol) {
if(right)
s_chan[ch].iRightVolRaw=vol;
else
s_chan[ch].iLeftVolRaw=vol;
if(vol&0x8000) {
s16 sInc=1; if(vol&0x2000) sInc=-1; if(vol&0x1000) vol^=0xffff; vol=((vol&0x7f)+1)/2; vol+=vol/(2*sInc); vol*=128;
vol&=0x3fff;
}
else {
if(vol&0x4000)
vol=(vol&0x3FFF)-0x4000;
else
vol&=0x3FFF;
}
if(right)
s_chan[ch].iRightVolume=vol;
else
s_chan[ch].iLeftVolume=vol; }
static void SetPitch(int ch,u16 val) {
int NP;
if(val>0x3fff) NP=0x3fff; else NP=val;
s_chan[ch].iRawPitch=NP;
NP=(44100L*NP)/4096L; if(NP<1) NP=1; s_chan[ch].iActFreq=NP; }