spuAddr+=2;\r
if(spuAddr>0x7ffff) spuAddr=0;\r
\r
- iSpuAsyncWait=0;\r
-\r
return s;\r
}\r
\r
spuAddr+=2; // inc spu addr\r
if(spuAddr>0x7ffff) spuAddr=0; // wrap\r
}\r
-\r
- iSpuAsyncWait=0;\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
spuAddr+=2; // inc spu addr\r
if(spuAddr>0x7ffff) spuAddr=0; // wrap\r
-\r
- iSpuAsyncWait=0;\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize)\r
{\r
int i;\r
+ \r
+ had_dma = 1;\r
+\r
+ if(spuAddr + iSize*2 < 0x80000)\r
+ {\r
+ memcpy(&spuMem[spuAddr>>1], pusPSXMem, iSize*2);\r
+ spuAddr += iSize*2;\r
+ return;\r
+ }\r
\r
for(i=0;i<iSize;i++)\r
{\r
spuMem[spuAddr>>1] = *pusPSXMem++; // spu addr got by writeregister\r
spuAddr+=2; // inc spu addr\r
- if(spuAddr>0x7ffff) spuAddr=0; // wrap\r
+ spuAddr&=0x7ffff; // wrap\r
}\r
- \r
- iSpuAsyncWait=0;\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
} while (0)
#endif
+#define PSXCLK 33868800 /* 33.8688 MHz */
+
/*
#if defined (USEMACOSX)
static char * libraryName = N_("Mac OS X Sound");
unsigned int dwNoiseVal; // global noise generator
unsigned int dwNoiseCount;
-int iSpuAsyncWait=0;
unsigned short spuCtrl=0; // some vars to store psx reg infos
unsigned short spuStat=0;
int iCycle = 0;
short * pS;
+int had_dma;
int lastch=-1; // last channel processed on spu irq in timer mode
static int lastns=0; // last ns pos
+static int cycles_since_update;
#define CDDA_BUFFER_SIZE (16384 * sizeof(uint32_t)) // must be power of 2
// basically the whole sound processing is done in this fat func!
////////////////////////////////////////////////////////////////////////
-static int do_samples(void)
+static int do_samples(int forced_updates)
{
int volmult = iVolume;
int ns,ns_from,ns_to;
// until enuff free place is available/a new channel gets
// started
- if(!dwNewChannel && SoundGetBytesBuffered()) // still enuff data in sound buffer?
+ if(!forced_updates && SoundGetBytesBuffered()) // still enuff data in sound buffer?
{
return 0;
}
+ cycles_since_update = 0;
+ if(forced_updates > 0)
+ forced_updates--;
+
//--------------------------------------------------// continue from irq handling in timer mode?
ns_from=0;
unsigned char *start = s_chan[ch].pCurr;
// no need for bIRQReturn since the channel is silent
- iSpuAsyncWait |= skip_block(ch);
+ skip_block(ch);
if(start == s_chan[ch].pCurr)
{
// looping on self
}
if(bIRQReturn && iSPUIRQWait) // special return for "spu irq - wait for cpu action"
- {
- iSpuAsyncWait=1;
- bIRQReturn=0;
return 0;
- }
//---------------------------------------------------//
void CALLBACK SPUasync(unsigned long cycle)
{
+ int forced_updates = 0;
+ int do_update = 0;
+
if(!bSpuInit) return; // -> no init, no call
- if(iSpuAsyncWait)
+ cycles_since_update += cycle;
+
+ if(dwNewChannel || had_dma)
{
- iSpuAsyncWait++;
- if(iSpuAsyncWait<=16/FRAG_MSECS) return;
- iSpuAsyncWait=0;
+ forced_updates = 1;
+ do_update = 1;
+ had_dma = 0;
}
- do_samples();
+ // once per frame should be fine (using a bit more because of BIAS)
+ if(cycles_since_update > PSXCLK/60 * 5/4)
+ do_update = 1;
+
+ if(do_update)
+ do_samples(forced_updates);
}
// SPU UPDATE... new epsxe func