aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authornotaz2012-07-09 00:28:04 +0300
committernotaz2012-07-15 20:30:10 +0300
commitb72f17a1320e9038c8416343ce270b0f676c757c (patch)
treed76c24a36957c1a1491344641f6ab5fa094cc0cb /plugins
parente4f075af4e4ba79332c72809d3bb4ba6e2895253 (diff)
downloadpcsx_rearmed-b72f17a1320e9038c8416343ce270b0f676c757c.tar.gz
pcsx_rearmed-b72f17a1320e9038c8416343ce270b0f676c757c.tar.bz2
pcsx_rearmed-b72f17a1320e9038c8416343ce270b0f676c757c.zip
spu: add decode buffer and reverb read handling
Diffstat (limited to 'plugins')
-rw-r--r--plugins/dfsound/externals.h9
-rw-r--r--plugins/dfsound/registers.c3
-rw-r--r--plugins/dfsound/reverb.c52
-rw-r--r--plugins/dfsound/spu.c55
4 files changed, 101 insertions, 18 deletions
diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h
index 3cb388c..f844b25 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 45df2eb..54e4000 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 2d65a69..ebb709b 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 d5a8215..bf02946 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<<ch;
+ }
+
if(s_chan[ch].bFMod==2) // fmod freq channel
memcpy(iFMod, ChanBuf, sizeof(iFMod));
else if(s_chan[ch].bRVBActive)
@@ -769,6 +793,16 @@ static int do_samples(int forced_updates)
if(bIRQReturn) // special return for "spu irq - wait for cpu action"
return 0;
+ if(unlikely(silentch & decode_dirty_ch & (1<<1))) // must clear silent channel decode buffers
+ {
+ memset(&spuMem[0x800/2], 0, 0x400);
+ decode_dirty_ch &= ~(1<<1);
+ }
+ if(unlikely(silentch & decode_dirty_ch & (1<<3)))
+ {
+ memset(&spuMem[0xc00/2], 0, 0x400);
+ decode_dirty_ch &= ~(1<<3);
+ }
//---------------------------------------------------//
//- here we have another 1 ms of sound data
@@ -822,18 +856,17 @@ static int do_samples(int forced_updates)
// an IRQ. Only problem: the "wait for cpu" option is kinda hard to do here
// in some of Peops timer modes. So: we ignore this option here (for now).
- if(pMixIrq && (spuCtrl&CTRL_IRQ) && pSpuIrq && pSpuIrq<spuMemC+0x1000)
+ if(unlikely((spuCtrl&CTRL_IRQ) && pSpuIrq && pSpuIrq<spuMemC+0x1000))
{
- for(ns=0;ns<NSSIZE;ns++)
+ int irq_pos=(pSpuIrq-spuMemC)/2 & 0x1ff;
+ if((decode_pos <= irq_pos && irq_pos < decode_pos+NSSIZE)
+ || (decode_pos+NSSIZE > 0x200 && irq_pos < ((decode_pos+NSSIZE) & 0x1ff)))
{
- for(ch=0;ch<4;ch++)
- {
- if(pSpuIrq>=pMixIrq+(ch*0x400) && pSpuIrq<pMixIrq+(ch*0x400)+2)
- do_irq();
- }
- pMixIrq+=2;if(pMixIrq>spuMemC+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;