X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=plugins%2Fdfsound%2Fregisters.c;h=e0693064db57616b716464fdd304ec2d1359f42b;hp=2f5774944b2fcc172bc0e5b69f6b57fc3db5225f;hb=HEAD;hpb=53d4b74d2fa40b17d4c692b9f3ed74fe40428926 diff --git a/plugins/dfsound/registers.c b/plugins/dfsound/registers.c index 2f577494..5565317d 100644 --- a/plugins/dfsound/registers.c +++ b/plugins/dfsound/registers.c @@ -22,6 +22,7 @@ #include "externals.h" #include "registers.h" #include "spu_config.h" +#include "spu.h" static void SoundOn(int start,int end,unsigned short val); static void SoundOff(int start,int end,unsigned short val); @@ -36,28 +37,30 @@ static void ReverbOn(int start,int end,unsigned short val); // WRITE REGISTERS: called by main emu //////////////////////////////////////////////////////////////////////// -static const uint32_t ignore_dupe[8] = { +static const uint32_t ignore_dupe[16] = { // ch 0-15 c40 c80 cc0 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, // ch 16-24 d40 control reverb - 0x7f7f7f7f, 0x7f7f7f7f, 0xff05ff0f, 0xffffffff + 0x7f7f7f7f, 0x7f7f7f7f, 0xff05ff0f, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, unsigned int cycles) { - int r = reg & 0xfff; + int r = reg & 0xffe; int rofs = (r - 0xc00) >> 1; int changed = spu.regArea[rofs] != val; spu.regArea[rofs] = val; - if (!changed && (ignore_dupe[rofs >> 5] & (1 << (rofs & 0x1f)))) + if (!changed && (ignore_dupe[rofs >> 5] & (1u << (rofs & 0x1f)))) return; // zero keyon/keyoff? if (val == 0 && (r & 0xff8) == 0xd88) return; - do_samples_if_needed(cycles, 0); + do_samples_if_needed(cycles, 0, 16); if(r>=0x0c00 && r<0x0d80) // some channel info? { @@ -118,23 +121,32 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, } return; } + else if (0x0e00 <= r && r < 0x0e60) + { + int ch = (r >> 2) & 0x1f; + log_unhandled("c%02d w %cvol %04x\n", ch, (r & 2) ? 'r' : 'l', val); + spu.s_chan[ch].iVolume[(r >> 1) & 1] = (signed short)val >> 1; + } switch(r) { //-------------------------------------------------// case H_SPUaddr: - spu.spuAddr = (unsigned long) val<<3; + spu.spuAddr = (unsigned int)val << 3; + //check_irq_io(spu.spuAddr); break; //-------------------------------------------------// case H_SPUdata: - *(unsigned short *)(spu.spuMemC + spu.spuAddr) = val; + *(unsigned short *)(spu.spuMemC + spu.spuAddr) = HTOLE16(val); spu.spuAddr += 2; spu.spuAddr &= 0x7fffe; + check_irq_io(spu.spuAddr); break; //-------------------------------------------------// case H_SPUctrl: + spu.spuStat = (spu.spuStat & ~0xbf) | (val & 0x3f) | ((val << 2) & 0x80); + spu.spuStat &= ~STAT_IRQ | val; if (!(spu.spuCtrl & CTRL_IRQ)) { - spu.spuStat&=~STAT_IRQ; if (val & CTRL_IRQ) schedule_next_irq(); } @@ -142,7 +154,7 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, break; //-------------------------------------------------// case H_SPUstat: - spu.spuStat=val&0xf800; + //spu.spuStat=val&0xf800; break; //-------------------------------------------------// case H_SPUReverbAddr: @@ -151,23 +163,35 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, case H_SPUirqAddr: //if (val & 1) // log_unhandled("w irq with lsb: %08lx %04x\n", reg, val); - spu.pSpuIrq=spu.spuMemC+(((unsigned long) val<<3)&~0xf); + spu.pSpuIrq = spu.spuMemC + (((int)val << 3) & ~0xf); + //check_irq_io(spu.spuAddr); goto upd_irq; //-------------------------------------------------// case H_SPUrvolL: - spu.rvb->VolLeft=val; + spu.rvb->VolLeft = (int16_t)val; break; //-------------------------------------------------// case H_SPUrvolR: - spu.rvb->VolRight=val; + spu.rvb->VolRight = (int16_t)val; break; //-------------------------------------------------// case H_SPUmvolL: - case H_SPUmvolR: - if (val & 0x8000) + case H_SPUmvolR: { + int ofs = H_SPUcmvolL - H_SPUmvolL; + unsigned short *cur = ®AreaGet(r + ofs); + if (val & 0x8000) { + // this (for now?) lacks an update mechanism, so is instant log_unhandled("w master sweep: %08lx %04x\n", reg, val); + int was_neg = (*cur >> 14) & 1; + int dec = (val >> 13) & 1; + int inv = (val >> 12) & 1; + *cur = (was_neg ^ dec ^ inv) ? 0x7fff : 0; + } + else + *cur = val << 1; break; + } case 0x0dac: if (val != 4) @@ -183,14 +207,6 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, //auxprintf("ER %d\n",val); break; //-------------------------------------------------// - case H_SPUmvolL: - //auxprintf("ML %d\n",val); - break; - //-------------------------------------------------// - case H_SPUmvolR: - //auxprintf("MR %d\n",val); - break; - //-------------------------------------------------// case H_SPUMute1: //auxprintf("M0 %04x\n",val); break; @@ -201,28 +217,44 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, */ //-------------------------------------------------// case H_SPUon1: + spu.last_keyon_cycles = cycles; + do_samples_if_needed(cycles, 0, 2); SoundOn(0,16,val); break; //-------------------------------------------------// - case H_SPUon2: + case H_SPUon2: + spu.last_keyon_cycles = cycles; + do_samples_if_needed(cycles, 0, 2); SoundOn(16,24,val); break; //-------------------------------------------------// case H_SPUoff1: + if (cycles - spu.last_keyon_cycles < 786u) { + if (val & regAreaGet(H_SPUon1)) + log_unhandled("koff1 %04x %d\n", val, cycles - spu.last_keyon_cycles); + val &= ~regAreaGet(H_SPUon1); + } + do_samples_if_needed(cycles, 0, 2); SoundOff(0,16,val); break; //-------------------------------------------------// case H_SPUoff2: + if (cycles - spu.last_keyon_cycles < 786u) { + if (val & regAreaGet(H_SPUon1)) + log_unhandled("koff2 %04x %d\n", val, cycles - spu.last_keyon_cycles); + val &= ~regAreaGet(H_SPUon2); + } + do_samples_if_needed(cycles, 0, 2); SoundOff(16,24,val); break; //-------------------------------------------------// case H_CDLeft: spu.iLeftXAVol=(int16_t)val; - if(spu.cddavCallback) spu.cddavCallback(0,(int16_t)val); + //if(spu.cddavCallback) spu.cddavCallback(0,(int16_t)val); break; case H_CDRight: spu.iRightXAVol=(int16_t)val; - if(spu.cddavCallback) spu.cddavCallback(1,(int16_t)val); + //if(spu.cddavCallback) spu.cddavCallback(1,(int16_t)val); break; //-------------------------------------------------// case H_FMod1: @@ -249,38 +281,38 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, ReverbOn(16,24,val); break; //-------------------------------------------------// - case H_Reverb+0 : goto rvbd; - case H_Reverb+2 : goto rvbd; - case H_Reverb+4 : spu.rvb->IIR_ALPHA=(short)val; break; - case H_Reverb+6 : spu.rvb->ACC_COEF_A=(short)val; break; - case H_Reverb+8 : spu.rvb->ACC_COEF_B=(short)val; break; - case H_Reverb+10 : spu.rvb->ACC_COEF_C=(short)val; break; - case H_Reverb+12 : spu.rvb->ACC_COEF_D=(short)val; break; - case H_Reverb+14 : spu.rvb->IIR_COEF=(short)val; break; - case H_Reverb+16 : spu.rvb->FB_ALPHA=(short)val; break; - case H_Reverb+18 : spu.rvb->FB_X=(short)val; break; - case H_Reverb+20 : goto rvbd; - case H_Reverb+22 : goto rvbd; - case H_Reverb+24 : goto rvbd; - case H_Reverb+26 : goto rvbd; - case H_Reverb+28 : goto rvbd; - case H_Reverb+30 : goto rvbd; - case H_Reverb+32 : goto rvbd; - case H_Reverb+34 : goto rvbd; - case H_Reverb+36 : goto rvbd; - case H_Reverb+38 : goto rvbd; - case H_Reverb+40 : goto rvbd; - case H_Reverb+42 : goto rvbd; - case H_Reverb+44 : goto rvbd; - case H_Reverb+46 : goto rvbd; - case H_Reverb+48 : goto rvbd; - case H_Reverb+50 : goto rvbd; - case H_Reverb+52 : goto rvbd; - case H_Reverb+54 : goto rvbd; - case H_Reverb+56 : goto rvbd; - case H_Reverb+58 : goto rvbd; - case H_Reverb+60 : spu.rvb->IN_COEF_L=(short)val; break; - case H_Reverb+62 : spu.rvb->IN_COEF_R=(short)val; break; + case H_Reverb + 0x00 : goto rvbd; + case H_Reverb + 0x02 : goto rvbd; + case H_Reverb + 0x04 : spu.rvb->vIIR = (signed short)val; break; + case H_Reverb + 0x06 : spu.rvb->vCOMB1 = (signed short)val; break; + case H_Reverb + 0x08 : spu.rvb->vCOMB2 = (signed short)val; break; + case H_Reverb + 0x0a : spu.rvb->vCOMB3 = (signed short)val; break; + case H_Reverb + 0x0c : spu.rvb->vCOMB4 = (signed short)val; break; + case H_Reverb + 0x0e : spu.rvb->vWALL = (signed short)val; break; + case H_Reverb + 0x10 : spu.rvb->vAPF1 = (signed short)val; break; + case H_Reverb + 0x12 : spu.rvb->vAPF2 = (signed short)val; break; + case H_Reverb + 0x14 : goto rvbd; + case H_Reverb + 0x16 : goto rvbd; + case H_Reverb + 0x18 : goto rvbd; + case H_Reverb + 0x1a : goto rvbd; + case H_Reverb + 0x1c : goto rvbd; + case H_Reverb + 0x1e : goto rvbd; + case H_Reverb + 0x20 : goto rvbd; + case H_Reverb + 0x22 : goto rvbd; + case H_Reverb + 0x24 : goto rvbd; + case H_Reverb + 0x26 : goto rvbd; + case H_Reverb + 0x28 : goto rvbd; + case H_Reverb + 0x2a : goto rvbd; + case H_Reverb + 0x2c : goto rvbd; + case H_Reverb + 0x2e : goto rvbd; + case H_Reverb + 0x30 : goto rvbd; + case H_Reverb + 0x32 : goto rvbd; + case H_Reverb + 0x34 : goto rvbd; + case H_Reverb + 0x36 : goto rvbd; + case H_Reverb + 0x38 : goto rvbd; + case H_Reverb + 0x3a : goto rvbd; + case H_Reverb + 0x3c : spu.rvb->vLIN = (signed short)val; break; + case H_Reverb + 0x3e : spu.rvb->vRIN = (signed short)val; break; } return; @@ -297,9 +329,9 @@ rvbd: // READ REGISTER: called by main emu //////////////////////////////////////////////////////////////////////// -unsigned short CALLBACK SPUreadRegister(unsigned long reg) +unsigned short CALLBACK SPUreadRegister(unsigned long reg, unsigned int cycles) { - const unsigned long r=reg&0xfff; + const unsigned long r = reg & 0xffe; if(r>=0x0c00 && r<0x0d80) { @@ -307,12 +339,13 @@ unsigned short CALLBACK SPUreadRegister(unsigned long reg) { case 12: // get adsr vol { - const int ch=(r>>4)-0xc0; - if(spu.dwNewChannel&(1<>16); + // this used to return 1 immediately after keyon to deal with + // some poor timing, but that causes Rayman 2 to lose track of + // it's channels on busy scenes and start looping some of them forever + const int ch = (r>>4) - 0xc0; + if (spu.s_chan[ch].bStarting) + do_samples_if_needed(cycles, 0, 2); + return (unsigned short)(spu.s_chan[ch].ADSRX.EnvelopeVol >> 16); } case 14: // get loop address @@ -322,6 +355,13 @@ unsigned short CALLBACK SPUreadRegister(unsigned long reg) } } } + else if (0x0e00 <= r && r < 0x0e60) + { + int ch = (r >> 2) & 0x1f; + int v = spu.s_chan[ch].iVolume[(r >> 1) & 1] << 1; + log_unhandled("c%02d r %cvol %04x\n", ch, (r & 2) ? 'r' : 'l', v); + return v; + } switch(r) { @@ -329,16 +369,18 @@ unsigned short CALLBACK SPUreadRegister(unsigned long reg) return spu.spuCtrl; case H_SPUstat: - return (spu.spuStat & ~0x3F) | (spu.spuCtrl & 0x3F); + return spu.spuStat; case H_SPUaddr: return (unsigned short)(spu.spuAddr>>3); + // this reportedly doesn't work on real hw case H_SPUdata: { - unsigned short s = *(unsigned short *)(spu.spuMemC + spu.spuAddr); + unsigned short s = LE16TOH(*(unsigned short *)(spu.spuMemC + spu.spuAddr)); spu.spuAddr += 2; spu.spuAddr &= 0x7fffe; + //check_irq_io(spu.spuAddr); return s; } @@ -350,7 +392,25 @@ unsigned short CALLBACK SPUreadRegister(unsigned long reg) case H_SPUMute1: case H_SPUMute2: - log_unhandled("r isOn: %08lx\n", reg); + log_unhandled("spu r isOn: %08lx %04x\n", reg, regAreaGet(r)); + break; + + case H_SPUmvolL: + case H_SPUmvolR: + log_unhandled("spu r mvol: %08lx %04x\n", reg, regAreaGet(r)); + break; + + case 0x0dac: + case H_SPUirqAddr: + case H_CDLeft: + case H_CDRight: + case H_ExtLeft: + case H_ExtRight: + break; + + default: + if (r >= 0xda0) + log_unhandled("spu r %08lx %04x\n", reg, regAreaGet(r)); break; } @@ -370,6 +430,7 @@ static void SoundOn(int start,int end,unsigned short val) if((val&1) && regAreaGetCh(ch, 6)) // mmm... start has to be set before key on !?! { spu.s_chan[ch].bIgnoreLoop = 0; + spu.s_chan[ch].bStarting = 1; spu.dwNewChannel|=(1<>=1) // loop channels + for (ch = start; val && ch < end; ch++, val >>= 1) // loop channels { if(val&1) { @@ -464,6 +525,7 @@ static void SetVolumeL(unsigned char ch,short vol) // LEFT VOLUME vol&=0x3fff; spu.s_chan[ch].iLeftVolume=vol; // store volume + //spu.regArea[(0xe00-0xc00)/2 + ch*2 + 0] = vol << 1; } //////////////////////////////////////////////////////////////////////// @@ -491,6 +553,7 @@ static void SetVolumeR(unsigned char ch,short vol) // RIGHT VOLUME vol&=0x3fff; spu.s_chan[ch].iRightVolume=vol; + //spu.regArea[(0xe00-0xc00)/2 + ch*2 + 1] = vol << 1; } //////////////////////////////////////////////////////////////////////// @@ -506,7 +569,6 @@ static void SetPitch(int ch,unsigned short val) // SET PITCH spu.s_chan[ch].iRawPitch = NP; spu.s_chan[ch].sinc = NP << 4; spu.s_chan[ch].sinc_inv = 0; - spu.s_chan[ch].bNewPitch = 1; // don't mess spu.dwChannelsAudible as adsr runs independently } @@ -524,3 +586,5 @@ static void ReverbOn(int start,int end,unsigned short val) spu.s_chan[ch].bReverb=val&1; // -> reverb on/off } } + +// vim:shiftwidth=1:expandtab