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

📄 infones_papu.cpp

📁 游戏模拟器InfoNes的原代码。有兴趣的可以将它移植到linux下
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		        ApuC2b    = ApuEventQueue[event].data;
		        break;

		      case 2:
		        ApuC2c = ApuEventQueue[event].data;
		        ApuC2Freq = ( ( ( (WORD)ApuC2d & 0x07 ) << 8 ) + ApuC2c );
		        ApuC2Atl = ApuAtl[ ( ApuC2d & 0xf8 ) >> 3 ];

		        if ( ApuC2Freq )
            {
			        ApuC2Skip = ApuPulseMagic / ApuC2Freq;
		        } else {
			        ApuC2Skip = 0;
		        }
		        break;

		      case 3:
		        ApuC2d = ApuEventQueue[event].data;
		        ApuC2Freq = ( ( ( (WORD)ApuC2d & 0x07 ) << 8 ) + ApuC2c );
		        ApuC2Atl = ApuAtl[ ( ApuC2d & 0xf8 ) >> 3 ];

		        if ( ApuC2Freq )
            {
			        ApuC2Skip = ApuPulseMagic / ApuC2Freq;
		        } else {
			        ApuC2Skip = 0;
		        }
            break;
		    }
	    }
      else if ( ApuEventQueue[event].type == APUET_W_CTRL )
      {
		    ctrl = ApuEventQueue[event].data;
	    }
	    event++;
	  }

    /* Envelope decay at a rate of ( Envelope Delay + 1 ) / 240 secs */
    ApuC2EnvPhase -= 4;
    while ( ApuC2EnvPhase < 0 )
    {
      ApuC2EnvPhase += ApuC2EnvDelay;

      if ( ApuC2Hold )
      {
        ApuC2EnvVol = ( ApuC2EnvVol + 1 ) & 0x0f;
      }
      else if ( ApuC2EnvVol < 0x0f )
      {
        ApuC2EnvVol++;
      }
    }

    /*
     * TODO: using a table of max frequencies is not technically
     * clean, but it is fast and (or should be) accurate
     */
    if ( ApuC2Freq < 8 || ( !ApuC2SweepIncDec && ApuC2Freq > ApuC2FreqLimit ) )
    {
      wave_buffers[1][i] = 0;
      break;
    }

    /* Frequency sweeping at a rate of ( Sweep Delay + 1) / 120 secs */
    if ( ApuC2SweepOn && ApuC2SweepShifts )
    {
      ApuC2SweepPhase -= 2;           /* 120/60 */
      while ( ApuC2SweepPhase < 0)
      {
        ApuC2SweepPhase += ApuC2SweepDelay;

        if ( ApuC2SweepIncDec ) /* ramp up */
        {
          /* Rectangular #1 */
          ApuC2Freq -= ( ApuC2Freq >> ApuC2SweepShifts );
        } else {
          /* ramp down */
          ApuC2Freq += ( ApuC2Freq >> ApuC2SweepShifts );
        }
      }
      ApuC2Skip = ApuPulseMagic / ApuC2Freq;
    }

    /* Wave Rendering */
	  if ( ( ctrl & 0x01 ) && ( ApuC2Atl || ApuC2Hold ) )
    {
	    ApuC2Index += ApuC2Skip;
	    ApuC2Index &= 0x1fffffff;

      if ( ApuC2Env )
      {
        wave_buffers[1][i] = ApuC2Wave[ApuC2Index >> 24] * ( ApuC2Vol + ApuC2EnvVol );
      } else {
        wave_buffers[1][i] = ApuC2Wave[ApuC2Index >> 24] * ApuC2Vol;
      }
	  } else {
	    wave_buffers[1][i] = 0;
	  }
  }
  if ( ApuC2Atl )
  {
	  ApuC2Atl--;
  }
  ApuCtrlNew = ctrl;
}

/*===================================================================*/
/*                                                                   */
/*      InfoNES_pApuWave3() : Rendering Triangle Wave                */
/*                                                                   */
/*===================================================================*/

void InfoNES_pApuWave3( void )
{
  int cycles = 0;
  int event = 0;
  BYTE ctrl = ApuCtrl;

  /* note: 41 CPU cycles occur between increments of i */
  for ( unsigned int i = 0; i < ApuSamplesPerSync; i++)
  {
	  cycles += ApuCyclesPerSample;
	  while (( event < cur_event ) && ( ApuEventQueue[event].time < cycles ) )
    {
	    if ( ( ApuEventQueue[event].type & APUET_MASK ) == APUET_C3 )
      {
		    switch ( ApuEventQueue[event].type & 3 )
        {
		      case 0:
  		      ApuC3a = ApuEventQueue[event].data;
            ApuC3Llc = ApuC3LinearLength;
            break;

		      case 1:
		        ApuC3b = ApuEventQueue[event].data;
		        break;

  		    case 2:
	  	      ApuC3c = ApuEventQueue[event].data;
		        if ( ApuC3Freq )
            {
			        ApuC3Skip = ApuTriangleMagic / ApuC3Freq;
  		      } else {
  			      ApuC3Skip = 0;
  		      }
  		      break;

  		    case 3:
  		      ApuC3d = ApuEventQueue[event].data;
  		      ApuC3Atl = ApuC3LengthCounter;
  		      if ( ApuC3Freq )
            {
  			      ApuC3Skip = ApuTriangleMagic / ApuC3Freq;
  		      } else {
  			      ApuC3Skip = 0;
  		      }
	  	  }
	    } else if ( ApuEventQueue[event].type == APUET_W_CTRL )
      {
		    ctrl = ApuEventQueue[event].data;
	    }
	    event++;
	  }

    /* Cutting Min Frequency */
    if ( ApuC3Freq < 8 )
    {
      wave_buffers[2][i] = 0;
      break;
    }

    /* Wave Rendering */
    if ( ( ctrl & 4 ) && ( ( ApuC3Atl > 0 || ApuC3Holdnote ) && ApuC3Llc > 0 ) )
    {
	    ApuC3Index += ApuC3Skip;
	    ApuC3Index &= 0x1fffffff;
	    wave_buffers[2][i] = triangle_50[ ApuC3Index >> 24 ];
	  } else {
	    wave_buffers[2][i] = 0;
	  }
  }

  /* Counter Control */
  if ( ApuC3CounterStarted )
  {
    if ( ApuC3Atl > 0 && !ApuC3Holdnote )
    {
	    ApuC3Atl--;
    }
    if ( ApuC3Llc > 0)
    {
      ApuC3Llc--;
    }
  } else if ( !ApuC3Holdnote && ApuC3WriteLatency > 0 )
  {
    if ( --ApuC3WriteLatency == 0 )
    {
      ApuC3CounterStarted = 0x01;
    }
  }
  ApuCtrlNew = ctrl;
}

/*===================================================================*/
/*                                                                   */
/*      InfoNES_pApuWave4() : Rendering Noise                        */
/*                                                                   */
/*===================================================================*/

void InfoNES_pApuWave4(void)
{
  int cycles = 0;
  int event = 0;
  BYTE ctrl = ApuCtrl;

  for ( unsigned int i = 0; i < ApuSamplesPerSync; i++ )
  {
	  cycles += ApuCyclesPerSample;
	  while ((event < cur_event) && (ApuEventQueue[event].time < cycles))
    {
	    if ( ( ApuEventQueue[event].type & APUET_MASK ) == APUET_C4 )
      {
		    switch (ApuEventQueue[event].type & 3) {
		      case 0:
		        ApuC4a = ApuEventQueue[event].data;
            break;

		      case 1:
		        ApuC4b = ApuEventQueue[event].data;
		        break;

		      case 2:
		        ApuC4c = ApuEventQueue[event].data;

		        if ( ApuC4Small )
            {
			        ApuC4Sr = 0x001f;
		        } else {
			        ApuC4Sr = 0x01ff;
		        }

            /* Frequency */
		        if ( ApuC4Freq )
            {
			        ApuC4Skip = ApuNoiseMagic / ApuC4Freq;
		        } else {
			        ApuC4Skip = 0;
		        }
		        ApuC4Atl = ApuC4LengthCounter;
		        break;

		      case 3:
		        ApuC4d = ApuEventQueue[event].data;

            /* Frequency */
		        if ( ApuC4Freq )
            {
			        ApuC4Skip = ApuNoiseMagic / ApuC4Freq;
		        } else {
			        ApuC4Skip = 0;
		        }
		        ApuC4Atl = ApuC4LengthCounter;
		    }
	    } else if (ApuEventQueue[event].type == APUET_W_CTRL)
      {
		    ctrl = ApuEventQueue[event].data;
	    }
	    event++;
	  }

    /* Envelope decay at a rate of ( Envelope Delay + 1 ) / 240 secs */
    ApuC4EnvPhase -= 4;
    while ( ApuC4EnvPhase < 0 )
    {
      ApuC4EnvPhase += ApuC4EnvDelay;

      if ( ApuC4Hold )
      {
        ApuC4EnvVol = ( ApuC4EnvVol + 1 ) & 0x0f;
      }
      else if ( ApuC4EnvVol < 0x0f )
      {
        ApuC4EnvVol++;
      }
    }

    /* Wave Rendering */
	  if ( ctrl & 8 )
    {
	    ApuC4Index += ApuC4Skip;
	    if (ApuC4Index > 0x1fffffff)
      {
		    if ( ApuC4Small )            /* FIXME: may be wrong */
        {
		      ApuC4Sr |= ((!(ApuC4Sr & 1)) ^ (!(ApuC4Sr & 4))) << 5;
        } else {
		      ApuC4Sr |= ((!(ApuC4Sr & 1)) ^ (!(ApuC4Sr & 16))) << 9;
		    }
		    ApuC4Sr >>= 1;
	    }
	    ApuC4Index &= 0x1fffffff;

	    if ( ApuC4Atl && ( ApuC4Sr & 1 ) )
      {
        if ( !ApuC4Env )
        {
		      wave_buffers[3][i] = ApuC4Vol;
        } else {
          wave_buffers[3][i] = ApuC4EnvVol ^ 0x0f;
        }
	    } else {
		    wave_buffers[3][i] = 0;
	    }
    } else {
	    wave_buffers[3][i] = 0;
    }
  }
  if ( ApuC4Atl && !ApuC4Hold )
  {
	   ApuC4Atl--;
  }
  ApuCtrlNew = ctrl;
}

/*===================================================================*/
/*                                                                   */
/*     InfoNES_pApuVsync() : Callback Function per Vsync             */
/*                                                                   */
/*===================================================================*/

void InfoNES_pAPUVsync(void)
{
  InfoNES_pApuWave1();
  InfoNES_pApuWave2();
  InfoNES_pApuWave3();
  InfoNES_pApuWave4();

  ApuCtrl = ApuCtrlNew;
#if 0
  {

	static FILE *pLog = fopen("log.txt", "wb");
	int i;

	for(i = 0; i < 735; ++i)
		fputc(wave_buffers[0][i]+'0', pLog);
	fflush(pLog);
  }
#endif
  InfoNES_SoundOutput4(ApuSamplesPerSync, wave_buffers[0], wave_buffers[1], wave_buffers[2], wave_buffers[3]);

  entertime = g_wPassedClocks;
  cur_event = 0;
}

/*===================================================================*/
/*                                                                   */
/*            InfoNES_pApuInit() : Initialize pApu                   */
/*                                                                   */
/*===================================================================*/

void InfoNES_pAPUInit(void)
{
  /* Sound Hardware Init */
  InfoNES_SoundInit();

  ApuQuality = pAPU_QUALITY;            // 1: 22050, 2: 44100 [samples/sec]

  if ( ApuQuality > 0 )
  {
    if ( ApuQuality > 2 )
    {
      ApuQuality = 1;
    }
	else
    {
      ApuQuality--;
    }
    ApuPulseMagic      = ApuQual[ ApuQuality ].pulse_magic;
    ApuTriangleMagic   = ApuQual[ ApuQuality ].triangle_magic;
    ApuNoiseMagic      = ApuQual[ ApuQuality ].noise_magic;
    ApuSamplesPerSync  = ApuQual[ ApuQuality ].samples_per_sync;
    ApuCyclesPerSample = ApuQual[ ApuQuality ].cycles_per_sample;
    ApuSampleRate      = ApuQual[ ApuQuality ].sample_rate;

    InfoNES_SoundOpen( ApuSamplesPerSync, ApuSampleRate );

    ApuC1Wave = pulse_50;
    ApuC2Wave = pulse_50;

    /* Initialize Rectangular Wave's Regs */
    ApuC1EnvPhase = 0;
    ApuC2EnvPhase = 0;
    ApuC4EnvPhase = 0;

    ApuC1EnvVol = 0;
    ApuC2EnvVol = 0;
    ApuC4EnvVol = 0;

    ApuC1SweepPhase = 0;
    ApuC2SweepPhase = 0;

    /* Initialize Triangle Wave's Regs */
    ApuC3WriteLatency = 3;                           /* Magic Number */
    ApuC3CounterStarted = NULL;
  }

  entertime = g_wPassedClocks;
  cur_event = 0;
}

/*===================================================================*/
/*                                                                   */
/*            InfoNES_pApuDone() : Finalize pApu                     */
/*                                                                   */
/*===================================================================*/

void InfoNES_pAPUDone(void)
{
  InfoNES_SoundClose();
}

/*
 * End of InfoNES_pAPU.cpp
 */

⌨️ 快捷键说明

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