// WRITE REGISTERS: called by main emu
void SPU_writeRegister(unsigned long reg, unsigned short val)
{
 	const unsigned long r=reg&0xfff;

 	regArea[(r-0xc00)>>1] = val;

 	if(r>=0x0c00 && r<0x0d80)                             // some channel info?
  	{
   		int ch=(r>>4)-0xc0;                           // calc channel
   		switch(r&0x0f)
    		{
     			case 0:                                           
       				SetVolumeL((unsigned char)ch,val);			// l volume
       				break;
     			case 2:                                           
       				SetVolumeR((unsigned char)ch,val);			// r volume
       				break;
     			case 4:                                           
       				SetPitch(ch,val);					// pitch
       				break;
     			case 6:      
       				s_chan[ch].pStart=spuMemC+((unsigned long) val<<3);	// start
       				break;
     			case 8:								// level with pre-calcs
       			{
        			const unsigned long lval=val;unsigned long lx;
        			s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; 
        			s_chan[ch].ADSRX.AttackRate = ((lval>>8) & 0x007f)^0x7f;
        			s_chan[ch].ADSRX.DecayRate = 4*(((lval>>4) & 0x000f)^0x1f);
        			s_chan[ch].ADSRX.SustainLevel = (lval & 0x000f) << 27;
         			break;
       			}
     			case 10:							// adsr times with pre-calcs
      			{
       				const unsigned long lval=val;unsigned long lx;
       				s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
       				s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
       				s_chan[ch].ADSRX.SustainRate = ((lval>>6) & 0x007f)^0x7f;
       				s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
       				s_chan[ch].ADSRX.ReleaseRate = 4*((lval & 0x001f)^0x1f);
      				break;
      			}
     			case 12: // adsr volume... mmm have to investigate this
       				break; 
     			case 14: // loop?
       				s_chan[ch].pLoop=spuMemC+((unsigned long) val<<3);
       				s_chan[ch].bIgnoreLoop=1;
       				break;
    		}
   		return;
  	}
Exemplo n.º 2
0
EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val)
{
 long r=reg&0xffff;

 regArea[r>>1] = val;

//	printf("SPU2: %04x to %08x\n", val, reg);

 if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580))  // some channel info?
  {
   int ch=(r>>4)&0x1f;
   if(r>=0x400) ch+=24;

   switch(r&0x0f)
    {
     //------------------------------------------------// r volume
     case 0:
       SetVolumeL((unsigned char)ch,val);
       break;
     //------------------------------------------------// l volume
     case 2:
       SetVolumeR((unsigned char)ch,val);
       break;
     //------------------------------------------------// pitch
     case 4:
       SetPitch(ch,val);
       break;
     //------------------------------------------------// level with pre-calcs
     case 6:
       {
        const unsigned long lval=val;unsigned long lx;
        //---------------------------------------------//
        s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0;
        s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
        s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
        s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
        //---------------------------------------------//
        if(!iDebugMode) break;
        //---------------------------------------------// stuff below is only for debug mode

        s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0;        //0x007f

        lx=(((lval>>8) & 0x007f)>>2);                  // attack time to run from 0 to 100% volume
        lx = (lx < 31) ? lx : 31;                      // no overflow on shift!
        if(lx)
         {
          lx = (1<<lx);
          if(lx<2147483) lx=(lx*ATTACK_MS)/10000L;     // another overflow check
          else           lx=(lx/10000L)*ATTACK_MS;
          if(!lx) lx=1;
         }
        s_chan[ch].ADSR.AttackTime=lx;

        s_chan[ch].ADSR.SustainLevel=                 // our adsr vol runs from 0 to 1024, so scale the sustain level
         (1024*((lval) & 0x000f))/15;

        lx=(lval>>4) & 0x000f;                         // decay:
        if(lx)                                         // our const decay value is time it takes from 100% to 0% of volume
         {
          lx = ((1<<(lx))*DECAY_MS)/10000L;
          if(!lx) lx=1;
         }
        s_chan[ch].ADSR.DecayTime =                   // so calc how long does it take to run from 100% to the wanted sus level
         (lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024;
       }
      break;
     //------------------------------------------------// adsr times with pre-calcs
     case 8:
      {
       const unsigned long lval=val;unsigned long lx;

       //----------------------------------------------//
       s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
       s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
       s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;
       s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
       s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
       //----------------------------------------------//
       if(!iDebugMode) break;
       //----------------------------------------------// stuff below is only for debug mode

       s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0;
       s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0;

       lx=((((lval>>6) & 0x007f)>>2));                 // sustain time... often very high
       lx = (lx < 31) ? lx : 31;                       // values are used to hold the volume
       if(lx)                                          // until a sound stop occurs
        {                                              // the highest value we reach (due to
         lx = (1<<lx);                                 // overflow checking) is:
         if(lx<2147483) lx=(lx*SUSTAIN_MS)/10000L;     // 94704 seconds = 1578 minutes = 26 hours...
         else           lx=(lx/10000L)*SUSTAIN_MS;     // should be enuff... if the stop doesn't
         if(!lx) lx=1;                                 // come in this time span, I don't care :)
        }
       s_chan[ch].ADSR.SustainTime = lx;

       lx=(lval & 0x001f);
       s_chan[ch].ADSR.ReleaseVal     =lx;
       if(lx)                                          // release time from 100% to 0%
        {                                              // note: the release time will be
         lx = (1<<lx);                                 // adjusted when a stop is coming,
         if(lx<2147483) lx=(lx*RELEASE_MS)/10000L;     // so at this time the adsr vol will
         else           lx=(lx/10000L)*RELEASE_MS;     // run from (current volume) to 0%
         if(!lx) lx=1;
        }
       s_chan[ch].ADSR.ReleaseTime=lx;

       if(lval & 0x4000)                               // add/dec flag
            s_chan[ch].ADSR.SustainModeDec=-1;
       else s_chan[ch].ADSR.SustainModeDec=1;
      }
     break;
     //------------------------------------------------//
    }

   iSpuAsyncWait=0;

   return;
  }
Exemplo n.º 3
0
void CALLBACK SPUsetVolumeL(unsigned char ch, short vol)
{
 SetVolumeR(ch,vol);
}
Exemplo n.º 4
0
void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val)
{
 const unsigned long r=reg&0xfff;
 regArea[(r-0xc00)>>1] = val;

 if(r>=0x0c00 && r<0x0d80)                             // some channel info?
  {
   int ch=(r>>4)-0xc0;                                 // calc channel
   switch(r&0x0f)
    {
     //------------------------------------------------// r volume
     case 0:                                           
       SetVolumeL((unsigned char)ch,val);
       break;
     //------------------------------------------------// l volume
     case 2:                                           
       SetVolumeR((unsigned char)ch,val);
       break;
     //------------------------------------------------// pitch
     case 4:                                           
       SetPitch(ch,val);
       break;
     //------------------------------------------------// start
     case 6:      
       s_chan[ch].pStart=spuMemC+((unsigned long) val<<3);
       break;
     //------------------------------------------------// level with pre-calcs
     case 8:
       {
        const unsigned long lval=val;unsigned long lx;
        //---------------------------------------------//
        s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; 
        s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
        s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
        s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
        //---------------------------------------------//
        if(!iDebugMode) break;
        //---------------------------------------------// stuff below is only for debug mode

        s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0;        //0x007f

        lx=(((lval>>8) & 0x007f)>>2);                  // attack time to run from 0 to 100% volume
        lx=min(31,lx);                                 // no overflow on shift!
        if(lx) 
         { 
          lx = (1<<lx);
          if(lx<2147483) lx=(lx*ATTACK_MS)/10000L;     // another overflow check
          else           lx=(lx/10000L)*ATTACK_MS;
          if(!lx) lx=1;
         }
        s_chan[ch].ADSR.AttackTime=lx;                

        s_chan[ch].ADSR.SustainLevel=                 // our adsr vol runs from 0 to 1024, so scale the sustain level
         (1024*((lval) & 0x000f))/15;

        lx=(lval>>4) & 0x000f;                         // decay:
        if(lx)                                         // our const decay value is time it takes from 100% to 0% of volume
         {
          lx = ((1<<(lx))*DECAY_MS)/10000L;
          if(!lx) lx=1;
         }
        s_chan[ch].ADSR.DecayTime =                   // so calc how long does it take to run from 100% to the wanted sus level
         (lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024;
       }
      break;
     //------------------------------------------------// adsr times with pre-calcs
     case 10:
      {
       const unsigned long lval=val;unsigned long lx;

       //----------------------------------------------//
       s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
       s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
       s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;
       s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
       s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
       //----------------------------------------------//
       if(!iDebugMode) break;
       //----------------------------------------------// stuff below is only for debug mode

       s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0;
       s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0;
                   
       lx=((((lval>>6) & 0x007f)>>2));                 // sustain time... often very high
       lx=min(31,lx);                                  // values are used to hold the volume
       if(lx)                                          // until a sound stop occurs
        {                                              // the highest value we reach (due to 
         lx = (1<<lx);                                 // overflow checking) is: 
         if(lx<2147483) lx=(lx*SUSTAIN_MS)/10000L;     // 94704 seconds = 1578 minutes = 26 hours... 
         else           lx=(lx/10000L)*SUSTAIN_MS;     // should be enuff... if the stop doesn't 
         if(!lx) lx=1;                                 // come in this time span, I don't care :)
        }
       s_chan[ch].ADSR.SustainTime = lx;

       lx=(lval & 0x001f);
       s_chan[ch].ADSR.ReleaseVal     =lx;
       if(lx)                                          // release time from 100% to 0%
        {                                              // note: the release time will be
         lx = (1<<lx);                                 // adjusted when a stop is coming,
         if(lx<2147483) lx=(lx*RELEASE_MS)/10000L;     // so at this time the adsr vol will 
         else           lx=(lx/10000L)*RELEASE_MS;     // run from (current volume) to 0%
         if(!lx) lx=1;
        }
       s_chan[ch].ADSR.ReleaseTime=lx;

       if(lval & 0x4000)                               // add/dec flag
            s_chan[ch].ADSR.SustainModeDec=-1;
       else s_chan[ch].ADSR.SustainModeDec=1;
      }
     break;
     //------------------------------------------------// adsr volume... mmm have to investigate this
     case 12:
       break;
     //------------------------------------------------//
     case 14:                                          // loop?
       //WaitForSingleObject(s_chan[ch].hMutex,2000);        // -> no multithread fuckups
       s_chan[ch].pLoop=spuMemC+((unsigned long) val<<3);
       s_chan[ch].bIgnoreLoop=1;
       //ReleaseMutex(s_chan[ch].hMutex);                    // -> oki, on with the thread
       break;
     //------------------------------------------------//
    }
   iSpuAsyncWait=0;
   return;
  }