⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emu2413.c

📁 最好的任天堂模拟器
💻 C
📖 第 1 页 / 共 3 页
字号:
        egout = 0 ;
        slot->eg_phase= 0 ;
        slot->eg_mode = DECAY ;
        UPDATE_EG(slot) ;
      }
      else
      {
        egout = AR_ADJUST_TABLE[HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS)] ;
      }
      break;

    case DECAY:
      slot->eg_phase += slot->eg_dphase ;
      egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS) ;
      if(slot->eg_phase >= SL[slot->patch->SL])
      {
        if(slot->patch->EG)
        {
          slot->eg_phase = SL[slot->patch->SL] ;
	        slot->eg_mode = SUSHOLD ;
          UPDATE_EG(slot) ;
        }
        else
        {
          slot->eg_phase = SL[slot->patch->SL] ;
          slot->eg_mode = SUSTINE ;
          UPDATE_EG(slot) ;
        }
        egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS) ;
      }
      break;

    case SUSHOLD:
      egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS) ;
      if(slot->patch->EG == 0)
      {
        slot->eg_mode = SUSTINE ;
        UPDATE_EG(slot) ;
      }
      break;

    case SUSTINE:
    case RELEASE:
      slot->eg_phase += slot->eg_dphase ;
      egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS) ; 
      if(egout >= (1<<EG_BITS))
      {
        slot->eg_mode = FINISH ;
        egout = (1<<EG_BITS) - 1 ;
      }
      break;

    case FINISH:
      egout = (1<<EG_BITS) - 1 ;
      break ;

    default:
      egout = (1<<EG_BITS) - 1 ;
      break;
  }

  if(slot->patch->AM) egout = EG2DB(egout+slot->tll) + *(slot->plfo_am) ;
  else egout = EG2DB(egout+slot->tll)  ;

  if(egout >= DB_MUTE) egout = DB_MUTE-1;
  return egout ;

}

INLINE static int32 calc_slot_car(OPLL_SLOT *slot, int32 fm)
{
  slot->egout = calc_envelope(slot) ; 
  slot->pgout = calc_phase(slot) ;
  if(slot->egout>=(DB_MUTE-1)) return 0 ;

  return DB2LIN_TABLE[slot->sintbl[(slot->pgout+wave2_8pi(fm))&(PG_WIDTH-1)] + slot->egout] ;
}


INLINE static int32 calc_slot_mod(OPLL_SLOT *slot)
{
  int32 fm ;

  slot->output[1] = slot->output[0] ;
  slot->egout = calc_envelope(slot) ; 
  slot->pgout = calc_phase(slot) ;

  if(slot->egout>=(DB_MUTE-1))
  {
    slot->output[0] = 0 ;
  }
  else if(slot->patch->FB!=0)
  {
    fm = wave2_4pi(slot->feedback) >> (7 - slot->patch->FB) ;
    slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+fm)&(PG_WIDTH-1)] + slot->egout] ;
  }
  else
  {
    slot->output[0] = DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout] ;
  }

  slot->feedback = (slot->output[1] + slot->output[0])>>1 ;

  return slot->feedback ;

}

INLINE static int32 calc_slot_tom(OPLL_SLOT *slot)
{

  slot->egout = calc_envelope(slot) ; 
  slot->pgout = calc_phase(slot) ;
  if(slot->egout>=(DB_MUTE-1)) return 0 ;
  
  return DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout] ;

}

/* calc SNARE slot */
INLINE static int32 calc_slot_snare(OPLL_SLOT *slot, uint32 whitenoise)
{
  slot->egout = calc_envelope(slot) ; 
  slot->pgout = calc_phase(slot) ;
  if(slot->egout>=(DB_MUTE-1)) return 0 ;

  if(whitenoise)
	  return DB2LIN_TABLE[snaretable[slot->pgout] + slot->egout] + DB2LIN_TABLE[slot->egout + 6] ;
  else
	  return DB2LIN_TABLE[snaretable[slot->pgout] + slot->egout] ;
}

INLINE static int32 calc_slot_cym(OPLL_SLOT *slot, int32 a, int32 b, int32 c)
{
  slot->egout = calc_envelope(slot) ;
  if(slot->egout>=(DB_MUTE-1)) return 0 ;

  return DB2LIN_TABLE[slot->egout+a] 
    + (( DB2LIN_TABLE[slot->egout+b] + DB2LIN_TABLE[slot->egout+c] ) >> 2 );
}

INLINE static int32 calc_slot_hat(OPLL_SLOT *slot, int32 a, int32 b, int32 c, uint32 whitenoise)
{
  slot->egout = calc_envelope(slot) ;
  if(slot->egout>=(DB_MUTE-1)) return 0 ;

  if(whitenoise)
  {
    return DB2LIN_TABLE[slot->egout+a] 
      + (( DB2LIN_TABLE[slot->egout+b] + DB2LIN_TABLE[slot->egout+c] ) >> 2 );
  }
  else
  {
    return 0  ;
  }
}

int16 OPLL_calc(OPLL *opll)
{
  int32 inst = 0 , perc = 0 , out = 0 ;
  int32 rythmC = 0, rythmH = 0;
  int i ;

  update_ampm(opll) ;
  update_noise(opll) ;

  for(i = 0 ; i < 6 ; i++)
    if(!(opll->mask&OPLL_MASK_CH(i))&&(opll->CAR(i)->eg_mode!=FINISH))
      inst += calc_slot_car(opll->CAR(i),calc_slot_mod(opll->MOD(i))) ;

  if(!opll->rythm_mode)
  {
    for(i = 6 ; i < 9 ; i++)
      if(!(opll->mask&OPLL_MASK_CH(i))&&(opll->CAR(i)->eg_mode!=FINISH))
        inst += calc_slot_car(opll->CAR(i),calc_slot_mod(opll->MOD(i))) ;
  }
  else
  {
    opll->MOD(7)->pgout = calc_phase(opll->MOD(7)) ;
    opll->CAR(8)->pgout = calc_phase(opll->CAR(8)) ;
    if(opll->MOD(7)->phase<256) rythmH = DB_NEG(12.0) ; else rythmH = DB_MUTE - 1 ;
    if(opll->CAR(8)->phase<256) rythmC = DB_NEG(12.0) ; else rythmC = DB_MUTE - 1 ;

    if(!(opll->mask&OPLL_MASK_BD)&&(opll->CAR(6)->eg_mode!=FINISH))
      perc += calc_slot_car(opll->CAR(6),calc_slot_mod(opll->MOD(6))) ;

    if(!(opll->mask&OPLL_MASK_HH)&&(opll->MOD(7)->eg_mode!=FINISH))
        perc += calc_slot_hat(opll->MOD(7), opll->noiseA, opll->noiseB, rythmH, opll->whitenoise) ;

    if(!(opll->mask&OPLL_MASK_SD)&&(opll->CAR(7)->eg_mode!=FINISH))
        perc += calc_slot_snare(opll->CAR(7), opll->whitenoise) ;
    
    if(!(opll->mask&OPLL_MASK_TOM)&&(opll->MOD(8)->eg_mode!=FINISH))
       perc += calc_slot_tom(opll->MOD(8)) ;

    if(!(opll->mask&OPLL_MASK_CYM)&&(opll->CAR(8)->eg_mode!=FINISH))
       perc += calc_slot_cym(opll->CAR(8), opll->noiseA, opll->noiseB, rythmC) ;
  }

#if SLOT_AMP_BITS > 8
  inst = (inst >> (SLOT_AMP_BITS - 8)) ;
  perc = (perc >> (SLOT_AMP_BITS - 9)) ;
#else
  inst = (inst << (8 - SLOT_AMP_BITS)) ;
  perc = (perc << (9 - SLOT_AMP_BITS)) ;
#endif

  out = ((inst + perc) * opll->masterVolume ) >> 2 ;

  if(out>32767) return 32767 ;
  if(out<-32768) return -32768 ;

  return (int16)out ;

}

uint32 OPLL_setMask(OPLL *opll, uint32 mask)
{
  uint32 ret ;
  
  if(opll)
  {
    ret = opll->mask ;
    opll->mask = mask ;
    return ret ;
  }
  else return 0 ;
}

uint32 OPLL_toggleMask(OPLL *opll, uint32 mask)
{
  uint32 ret ;
  
  if(opll)
  {
    ret = opll->mask ;
    opll->mask ^= mask ;
    return ret ;
  }
  else return 0 ;
}

/****************************************************

                       Interfaces

*****************************************************/

void OPLL_writeReg(OPLL *opll, uint32 reg, uint32 data){

  int i,v,ch ;

  data = data&0xff ;
  reg = reg&0x3f ;

  switch(reg)
  {
    case 0x00:
      opll->patch[0]->AM = (data>>7)&1 ;
      opll->patch[0]->PM = (data>>6)&1 ;
      opll->patch[0]->EG = (data>>5)&1 ;
      opll->patch[0]->KR = (data>>4)&1 ;
      opll->patch[0]->ML = (data)&15 ;
      for(i=0;i<9;i++)
      {
        if(opll->ch[i]->patch_number==0)
        {
          UPDATE_PG(opll->MOD(i)) ;
          UPDATE_RKS(opll->MOD(i)) ;
          UPDATE_EG(opll->MOD(i)) ;
        }
      }
      break ;

    case 0x01:
      opll->patch[1]->AM = (data>>7)&1 ;
      opll->patch[1]->PM = (data>>6)&1 ;
      opll->patch[1]->EG = (data>>5)&1 ;
      opll->patch[1]->KR = (data>>4)&1 ;
      opll->patch[1]->ML = (data)&15 ;
      for(i=0;i<9;i++)
      {
        if(opll->ch[i]->patch_number==0)
        {
          UPDATE_PG(opll->CAR(i)) ;
          UPDATE_RKS(opll->CAR(i)) ;
          UPDATE_EG(opll->CAR(i)) ;
        }
      }
      break;

    case 0x02:
      opll->patch[0]->KL = (data>>6)&3 ;
      opll->patch[0]->TL = (data)&63 ;
      for(i=0;i<9;i++)
      {
        if(opll->ch[i]->patch_number==0)
        {
          UPDATE_TLL(opll->MOD(i)) ;
        }
      }
      break ;

    case 0x03:
      opll->patch[1]->KL = (data>>6)&3 ;
      opll->patch[1]->WF = (data>>4)&1 ;
      opll->patch[0]->WF = (data>>3)&1 ;
      opll->patch[0]->FB = (data)&7 ;
      for(i=0;i<9;i++)
      {
        if(opll->ch[i]->patch_number==0)
        {
          UPDATE_WF(opll->MOD(i)) ;
          UPDATE_WF(opll->CAR(i)) ;
        }
      }
      break ;

    case 0x04:
      opll->patch[0]->AR = (data>>4)&15 ;
      opll->patch[0]->DR = (data)&15 ;
      for(i=0;i<9;i++)
      {
        if(opll->ch[i]->patch_number==0)
        {
          UPDATE_EG(opll->MOD(i)) ;
        }
      }
      break ;

    case 0x05:
      opll->patch[1]->AR = (data>>4)&15 ;
      opll->patch[1]->DR = (data)&15 ;
      for(i=0;i<9;i++)
      {
        if(opll->ch[i]->patch_number==0)
        {
          UPDATE_EG(opll->CAR(i)) ;
        }
      }
      break ;

    case 0x06:
      opll->patch[0]->SL = (data>>4)&15 ;
      opll->patch[0]->RR = (data)&15 ;
      for(i=0;i<9;i++)
      {
        if(opll->ch[i]->patch_number==0)
        {
          UPDATE_EG(opll->MOD(i)) ;
        }
      }
      break ;

    case 0x07:
      opll->patch[1]->SL = (data>>4)&15 ;
      opll->patch[1]->RR = (data)&15 ;
      for(i=0;i<9;i++)
      {
        if(opll->ch[i]->patch_number==0)
        {
          UPDATE_EG(opll->CAR(i)) ;
        }
      }
      break ;

    case 0x0e:

      if(opll->rythm_mode)
      {
        opll->slot_on_flag[SLOT_BD1] = (opll->reg[0x0e]&0x10) | (opll->reg[0x26]&0x10) ;
        opll->slot_on_flag[SLOT_BD2] = (opll->reg[0x0e]&0x10) | (opll->reg[0x26]&0x10) ;
        opll->slot_on_flag[SLOT_SD]  = (opll->reg[0x0e]&0x08) | (opll->reg[0x27]&0x10) ;
        opll->slot_on_flag[SLOT_HH]  = (opll->reg[0x0e]&0x01) | (opll->reg[0x27]&0x10) ;
        opll->slot_on_flag[SLOT_TOM] = (opll->reg[0x0e]&0x04) | (opll->reg[0x28]&0x10) ;
        opll->slot_on_flag[SLOT_CYM] = (opll->reg[0x0e]&0x02) | (opll->reg[0x28]&0x10) ;
      }
      else
      {
        opll->slot_on_flag[SLOT_BD1] = (opll->reg[0x26]&0x10) ;
        opll->slot_on_flag[SLOT_BD2] = (opll->reg[0x26]&0x10) ;
        opll->slot_on_flag[SLOT_SD]  = (opll->reg[0x27]&0x10) ;
        opll->slot_on_flag[SLOT_HH]  = (opll->reg[0x27]&0x10) ;
        opll->slot_on_flag[SLOT_TOM] = (opll->reg[0x28]&0x10) ;
        opll->slot_on_flag[SLOT_CYM] = (opll->reg[0x28]&0x10) ;
      }

      if(((data>>5)&1)^(opll->rythm_mode))
      {
        setRythmMode(opll,(data&32)>>5) ;
      }

      if(opll->rythm_mode)
      {
        if(data&0x10) keyOn_BD(opll) ; else keyOff_BD(opll) ;
        if(data&0x8) keyOn_SD(opll) ; else keyOff_SD(opll) ;
        if(data&0x4) keyOn_TOM(opll) ; else keyOff_TOM(opll) ;
        if(data&0x2) keyOn_CYM(opll) ; else keyOff_CYM(opll) ;
        if(data&0x1) keyOn_HH(opll) ; else keyOff_HH(opll) ;
      }    

      UPDATE_ALL(opll->MOD(6)) ;
      UPDATE_ALL(opll->CAR(6)) ;
      UPDATE_ALL(opll->MOD(7)) ;  
      UPDATE_ALL(opll->CAR(7)) ;
      UPDATE_ALL(opll->MOD(8)) ;
      UPDATE_ALL(opll->CAR(8)) ;
      break ;

    case 0x0f:
      break ;

    case 0x10:  case 0x11:  case 0x12:  case 0x13:
    case 0x14:  case 0x15:  case 0x16:  case 0x17:
    case 0x18:
       ch = reg-0x10 ;
      setFnumber(opll, ch, data + ((opll->reg[0x20+ch]&1)<<8)) ;
      UPDATE_ALL(opll->MOD(ch));
      UPDATE_ALL(opll->CAR(ch));
      switch(reg)
      {
      case 0x17:
        opll->noiseA_dphase = (data + ((opll->reg[0x27]&1)<<8)) << ((opll->reg[0x27]>>1)&7) ;
        break ;
      case 0x18:
        opll->noiseB_dphase = (data + ((opll->reg[0x28]&1)<<8)) << ((opll->reg[0x28]>>1)&7) ;
        break;
      default:
        break ;
      }
      break ;

    case 0x20:  case 0x21:  case 0x22:  case 0x23:
    case 0x24:  case 0x25:  case 0x26:  case 0x27:
    case 0x28:

      ch = reg - 0x20 ;
      setFnumber(opll, ch, ((data&1)<<8) + opll->reg[0x10+ch]) ;
      setBlock(opll, ch, (data>>1)&7 ) ;
      opll->slot_on_flag[ch*2] = opll->slot_on_flag[ch*2+1] = (opll->reg[reg])&0x10 ;
      
      if(opll->rythm_mode)
      {
        switch(reg)
        {
        case 0x26:      
          opll->slot_on_flag[SLOT_BD1] |= (opll->reg[0x0e])&0x10 ;
          opll->slot_on_flag[SLOT_BD2] |= (opll->reg[0x0e])&0x10 ;
          break ;
      
        case 0x27:
          opll->noiseA_dphase = (((data&1)<<8) + opll->reg[0x17] ) << ((data>>1)&7) ;
          opll->slot_on_flag[SLOT_SD]  |= (opll->reg[0x0e])&0x08 ;
          opll->slot_on_flag[SLOT_HH]  |= (opll->reg[0x0e])&0x01 ;
          break;

        case 0x28:
          opll->noiseB_dphase = (((data&1)<<8) + opll->reg[0x18] ) << ((data>>1)&7);
          opll->slot_on_flag[SLOT_TOM] |= (opll->reg[0x0e])&0x04 ;
          opll->slot_on_flag[SLOT_CYM] |= (opll->reg[0x0e])&0x02 ;
          break ;

        default:
          break ;
        }
      }
      
      if((opll->reg[reg]^data)&0x20) setSustine(opll, ch, (data>>5)&1) ;
      if(data&0x10) keyOn(opll, ch) ; else keyOff(opll, ch) ;
      UPDATE_ALL(opll->MOD(ch)) ;
      UPDATE_ALL(opll->CAR(ch)) ;
      break ;

    case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
    case 0x35: case 0x36: case 0x37: case 0x38:
      i = (data>>4)&15 ;
      v = data&15 ;
      if((opll->rythm_mode)&&(reg>=0x36))
      {
        switch(reg)
        {
         case 0x37 :
            setSlotVolume(opll->MOD(7), i<<2) ;
            break ;
         case 0x38 :
           setSlotVolume(opll->MOD(8), i<<2) ;
           break ;
        }
      }
      else
      { 
        setPatch(opll, reg-0x30, i) ;
      }
    
      setVolume(opll, reg-0x30, v<<2) ;
      UPDATE_ALL(opll->MOD(reg-0x30)) ;
      UPDATE_ALL(opll->CAR(reg-0x30)) ;
      break ;

    default:
      break ;

  }

  opll->reg[reg] = (unsigned char)data ;

}

void OPLL_writeIO(OPLL *opll, uint32 adr, uint32 val)
{
  adr &= 0xff ;
  if(adr == 0x7C) opll->adr = val ;
  else if(adr == 0x7D) OPLL_writeReg(opll, opll->adr, val) ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -