- // advance "stopped" channels that can cause irqs
- // (all chans are always playing on the real thing..)
- if(!bIRQReturn && (spuCtrl&CTRL_IRQ))
- for(ch=0;ch<MAXCHAN;ch++)
- {
- if(dwChannelOn&(1<<ch)) continue; // already handled
- if(s_chan[ch].pCurr == (unsigned char *)-1)
- continue;
- if(s_chan[ch].pCurr > pSpuIrq && s_chan[ch].pLoop > pSpuIrq)
- continue;
-
- if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq) // new psx frequency?
- VoiceChangeFrequency(ch);
-
- s_chan[ch].spos += s_chan[ch].sinc * NSSIZE;
- while(s_chan[ch].spos >= 28 * 0x10000)
- {
- unsigned char *start=s_chan[ch].pCurr;
-
- // no need for bIRQReturn since the channel is silent
- iSpuAsyncWait |= skip_block(ch);
- if(start == s_chan[ch].pCurr)
- {
- // looping on self
- s_chan[ch].pCurr=(unsigned char *)-1;
- break;
- }
-
- s_chan[ch].spos -= 28 * 0x10000;
- }
- }
+ if (s_chan[ch].bFMod == 2) // fmod freq channel
+ memcpy(iFMod, &ChanBuf, ns_to * sizeof(iFMod[0]));
+ if (s_chan[ch].bRVBActive)
+ mix_chan_rvb(0, ns_to, s_chan[ch].iLeftVolume, s_chan[ch].iRightVolume, spu.sRVBStart);
+ else
+ mix_chan(0, ns_to, s_chan[ch].iLeftVolume, s_chan[ch].iRightVolume);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// MAIN SPU FUNCTION
+// here is the main job handler...
+////////////////////////////////////////////////////////////////////////
+
+void do_samples_finish(int ns_to, int silentch);
+
+void do_samples(unsigned int cycles_to)
+{
+ unsigned int mask;
+ int ch, ns_to;
+ int silentch;
+ int cycle_diff;
+
+ cycle_diff = cycles_to - spu.cycles_played;
+ if (cycle_diff < -2*1048576 || cycle_diff > 2*1048576)
+ {
+ //xprintf("desync %u %d\n", cycles_to, cycle_diff);
+ spu.cycles_played = cycles_to;
+ return;
+ }
+
+ if (cycle_diff < 2 * 768)
+ return;
+
+ ns_to = (cycle_diff / 768 + 1) & ~1;
+ if (ns_to > NSSIZE) {
+ // should never happen
+ //xprintf("ns_to oflow %d %d\n", ns_to, NSSIZE);
+ ns_to = NSSIZE;
+ }
+
+ //////////////////////////////////////////////////////
+ // special irq handling in the decode buffers (0x0000-0x1000)
+ // we know:
+ // the decode buffers are located in spu memory in the following way:
+ // 0x0000-0x03ff CD audio left
+ // 0x0400-0x07ff CD audio right
+ // 0x0800-0x0bff Voice 1
+ // 0x0c00-0x0fff Voice 3
+ // and decoded data is 16 bit for one sample
+ // we assume:
+ // even if voices 1/3 are off or no cd audio is playing, the internal
+ // play positions will move on and wrap after 0x400 bytes.
+ // Therefore: we just need a pointer from spumem+0 to spumem+3ff, and
+ // increase this pointer on each sample by 2 bytes. If this pointer
+ // (or 0x400 offsets of this pointer) hits the spuirq address, we generate
+ // an IRQ.