From: notaz Date: Sun, 8 Jul 2012 21:28:04 +0000 (+0300) Subject: spu: add decode buffer and reverb read handling X-Git-Tag: r15~34 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b72f17a1320e9038c8416343ce270b0f676c757c;p=pcsx_rearmed.git spu: add decode buffer and reverb read handling --- diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h index 3cb388c5..f844b259 100644 --- a/plugins/dfsound/externals.h +++ b/plugins/dfsound/externals.h @@ -21,6 +21,14 @@ // generic defines ///////////////////////////////////////////////////////// +#if 0 //def __GNUC__ +#define noinline __attribute__((noinline)) +#define unlikely(x) __builtin_expect((x), 0) +#else +#define noinline +#define unlikely(x) x +#endif + #define PSE_LT_SPU 4 #define PSE_SPU_ERR_SUCCESS 0 #define PSE_SPU_ERR -60 @@ -202,6 +210,7 @@ extern int iUseInterpolation; // MISC extern int had_dma; +extern int decode_pos; extern SPUCHAN s_chan[]; extern REVERBInfo rvb; diff --git a/plugins/dfsound/registers.c b/plugins/dfsound/registers.c index 45df2ebc..54e4000f 100644 --- a/plugins/dfsound/registers.c +++ b/plugins/dfsound/registers.c @@ -212,6 +212,9 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val) { rvb.StartAddr=(unsigned long)val<<2; rvb.CurrAddr=rvb.StartAddr; + // sync-with-decode-buffers hack.. + if(rvb.StartAddr==0x3ff00) + rvb.CurrAddr+=decode_pos/2; } } rvb.dirty = 1; diff --git a/plugins/dfsound/reverb.c b/plugins/dfsound/reverb.c index 2d65a694..ebb709bd 100644 --- a/plugins/dfsound/reverb.c +++ b/plugins/dfsound/reverb.c @@ -157,11 +157,44 @@ static void MixREVERB(void) s_buffer(MIX_DEST_B0, mix_dest_b0); s_buffer(MIX_DEST_B1, mix_dest_b1); - l = (mix_dest_a0 + mix_dest_b0) / 3; - r = (mix_dest_a1 + mix_dest_b1) / 3; + l = (mix_dest_a0 + mix_dest_b0) / 2; + r = (mix_dest_a1 + mix_dest_b1) / 2; - l = (l * rvb.VolLeft) >> 14; - r = (r * rvb.VolRight) >> 14; + l = (l * rvb.VolLeft) >> 15; // 15? + r = (r * rvb.VolRight) >> 15; + + SSumLR[ns++] += (l + l_old) / 2; + SSumLR[ns++] += (r + r_old) / 2; + SSumLR[ns++] += l; + SSumLR[ns++] += r; + + l_old = l; + r_old = r; + + curr_addr++; + if (curr_addr >= 0x40000) curr_addr = rvb.StartAddr; + } + + rvb.iRVBLeft = l; + rvb.iRVBRight = r; + rvb.CurrAddr = curr_addr; +} + +static void MixREVERB_off(void) +{ + int l_old = rvb.iRVBLeft; + int r_old = rvb.iRVBRight; + int curr_addr = rvb.CurrAddr; + int space = 0x40000 - rvb.StartAddr; + int l, r, ns; + + for (ns = 0; ns < NSSIZE*2; ) + { + l = (g_buffer(MIX_DEST_A0) + g_buffer(MIX_DEST_B0)) / 2; + r = (g_buffer(MIX_DEST_A1) + g_buffer(MIX_DEST_B1)) / 2; + + l = (l * rvb.VolLeft) >> 15; + r = (r * rvb.VolRight) >> 15; SSumLR[ns++] += (l + l_old) / 2; SSumLR[ns++] += (r + r_old) / 2; @@ -235,14 +268,21 @@ INLINE void REVERBDo(void) if (spuCtrl & 0x80) // -> reverb on? oki { - if (rvb.dirty) + if (unlikely(rvb.dirty)) prepare_offsets(); MixREVERB(); } + else if (rvb.VolLeft || rvb.VolRight) + { + if (unlikely(rvb.dirty)) + prepare_offsets(); + + MixREVERB_off(); + } else // -> reverb off { - // supposedly runs anyway? + // reverb runs anyway rvb.CurrAddr += NSSIZE/2; while (rvb.CurrAddr >= 0x40000) rvb.CurrAddr -= 0x40000 - rvb.StartAddr; diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index d5a82159..bf029461 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -75,7 +75,6 @@ unsigned short spuMem[256*1024]; unsigned char * spuMemC; unsigned char * pSpuIrq=0; unsigned char * pSpuBuffer; -unsigned char * pMixIrq=0; // user settings @@ -120,6 +119,8 @@ int iFMod[NSSIZE]; int iCycle = 0; short * pS; +static int decode_dirty_ch; +int decode_pos; int had_dma; int lastch=-1; // last channel processed on spu irq in timer mode static int lastns=0; // last ns pos @@ -657,6 +658,23 @@ static void mix_chan_rvb(int start, int count, int lv, int rv) } #endif +// 0x0800-0x0bff Voice 1 +// 0x0c00-0x0fff Voice 3 +static void noinline do_decode_bufs(int which, int start, int count) +{ + const int *src = ChanBuf + start; + unsigned short *dst = &spuMem[0x800/2 + which*0x400/2]; + int cursor = decode_pos; + + while (count-- > 0) + { + dst[cursor] = *src++; + cursor = (cursor + 1) & 0x1ff; + } + + // decode_pos is updated and irqs are checked later, after voice loop +} + //////////////////////////////////////////////////////////////////////// // MAIN SPU FUNCTION // here is the main job handler... @@ -728,6 +746,12 @@ static int do_samples(int forced_updates) MixADSR(ch, ns_from, ns_to); + if(ch==1 || ch==3) + { + do_decode_bufs(ch/2, ns_from, ns_to-ns_from); + decode_dirty_ch |= 1< 0x200 && irq_pos < ((decode_pos+NSSIZE) & 0x1ff))) { - for(ch=0;ch<4;ch++) - { - if(pSpuIrq>=pMixIrq+(ch*0x400) && pSpuIrqspuMemC+0x3ff) pMixIrq=spuMemC; + //printf("decoder irq %x\n", decode_pos); + do_irq(); } } + decode_pos = (decode_pos + NSSIZE) & 0x1ff; InitREVERB(); @@ -966,8 +999,6 @@ void SetupStreams(void) s_chan[i].pCurr=spuMemC; } - pMixIrq=spuMemC; // enable decoded buffer irqs by setting the address - ClearWorkingState(); bSpuInit=1; // flag: we are inited @@ -998,7 +1029,7 @@ long CALLBACK SPUinit(void) spuIrq = 0; spuAddr = 0xffffffff; spuMemC = (unsigned char *)spuMem; - pMixIrq = 0; + decode_pos = 0; memset((void *)s_chan, 0, (MAXCHAN + 1) * sizeof(SPUCHAN)); pSpuIrq = 0; lastch = -1;