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

📄 apu.cpp

📁 著名SFC模拟器Snes9x的源代码。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			      (((byte << 8) + APU.DSP [reg - 1]) & FREQUENCY_MASK) * 8);	break;    case APU_SRCN + 0x00:    case APU_SRCN + 0x10:    case APU_SRCN + 0x20:    case APU_SRCN + 0x30:    case APU_SRCN + 0x40:    case APU_SRCN + 0x50:    case APU_SRCN + 0x60:    case APU_SRCN + 0x70:	if (byte != APU.DSP [reg])	{#ifdef DEBUGGER	    if (Settings.TraceSoundDSP)		S9xTraceSoundDSP ("[%d] %d sample number: %d\n",				  ICPU.Scanline, reg>>4, byte);#endif	    S9xSetSoundSample (reg >> 4, byte);	}	break;	    case APU_ADSR1 + 0x00:    case APU_ADSR1 + 0x10:    case APU_ADSR1 + 0x20:    case APU_ADSR1 + 0x30:    case APU_ADSR1 + 0x40:    case APU_ADSR1 + 0x50:    case APU_ADSR1 + 0x60:    case APU_ADSR1 + 0x70:	if (byte != APU.DSP [reg])	{#ifdef DEBUGGER	    if (Settings.TraceSoundDSP)		S9xTraceSoundDSP ("[%d] %d adsr1: %02x\n",				  ICPU.Scanline, reg>>4, byte);#endif	    {		S9xFixEnvelope (reg >> 4, APU.DSP [reg + 2], byte, 			     APU.DSP [reg + 1]);	    }	}	break;    case APU_ADSR2 + 0x00:    case APU_ADSR2 + 0x10:    case APU_ADSR2 + 0x20:    case APU_ADSR2 + 0x30:    case APU_ADSR2 + 0x40:    case APU_ADSR2 + 0x50:    case APU_ADSR2 + 0x60:    case APU_ADSR2 + 0x70:	if (byte != APU.DSP [reg])	{#ifdef DEBUGGER	    if (Settings.TraceSoundDSP)		S9xTraceSoundDSP ("[%d] %d adsr2: %02x\n", 				  ICPU.Scanline, reg>>4, byte);#endif	    {		S9xFixEnvelope (reg >> 4, APU.DSP [reg + 1], APU.DSP [reg - 1],			     byte);	    }	}	break;    case APU_GAIN + 0x00:    case APU_GAIN + 0x10:    case APU_GAIN + 0x20:    case APU_GAIN + 0x30:    case APU_GAIN + 0x40:    case APU_GAIN + 0x50:    case APU_GAIN + 0x60:    case APU_GAIN + 0x70:	if (byte != APU.DSP [reg])	{#ifdef DEBUGGER	    if (Settings.TraceSoundDSP)		S9xTraceSoundDSP ("[%d] %d gain: %02x\n",				  ICPU.Scanline, reg>>4, byte);#endif	    {		S9xFixEnvelope (reg >> 4, byte, APU.DSP [reg - 2],			     APU.DSP [reg - 1]);	    }	}	break;    case APU_ENVX + 0x00:    case APU_ENVX + 0x10:    case APU_ENVX + 0x20:    case APU_ENVX + 0x30:    case APU_ENVX + 0x40:    case APU_ENVX + 0x50:    case APU_ENVX + 0x60:    case APU_ENVX + 0x70:	break;    case APU_OUTX + 0x00:    case APU_OUTX + 0x10:    case APU_OUTX + 0x20:    case APU_OUTX + 0x30:    case APU_OUTX + 0x40:    case APU_OUTX + 0x50:    case APU_OUTX + 0x60:    case APU_OUTX + 0x70:	break;        case APU_DIR:#ifdef DEBUGGER	if (Settings.TraceSoundDSP)	    S9xTraceSoundDSP ("[%d] Sample directory to: %02x\n",			      ICPU.Scanline, byte);#endif	break;    case APU_PMON:	if (byte != APU.DSP [APU_PMON])	{#ifdef DEBUGGER	    if (Settings.TraceSoundDSP)	    {		S9xTraceSoundDSP ("[%d] FreqMod:", ICPU.Scanline);		uint8 mask = 1;		for (int c = 0; c < 8; c++, mask <<= 1)		{		    if (byte & mask)		    {			if (APU.DSP [reg] & mask)			    S9xTraceSoundDSP ("%d", c);			else			    S9xTraceSoundDSP ("%d(on),", c);		    }		    else		    {			if (APU.DSP [reg] & mask)			    S9xTraceSoundDSP ("%d(off),", c);		    }		}		S9xTraceSoundDSP ("\n");	    }#endif		S9xSetFrequencyModulationEnable (byte);	}	break;    case APU_EON:	if (byte != APU.DSP [APU_EON])	{#ifdef DEBUGGER	    if (Settings.TraceSoundDSP)	    {		S9xTraceSoundDSP ("[%d] Echo:", ICPU.Scanline);		uint8 mask = 1;		for (int c = 0; c < 8; c++, mask <<= 1)		{		    if (byte & mask)		    {			if (APU.DSP [reg] & mask)			    S9xTraceSoundDSP ("%d", c);			else			    S9xTraceSoundDSP ("%d(on),", c);		    }		    else		    {			if (APU.DSP [reg] & mask)			    S9xTraceSoundDSP ("%d(off),", c);		    }		}		S9xTraceSoundDSP ("\n");	    }#endif		S9xSetEchoEnable (byte);	}	break;    case APU_EFB:	S9xSetEchoFeedback ((signed char) byte);	break;    case APU_ESA:	break;    case APU_EDL:	S9xSetEchoDelay (byte & 0xf);	break;    case APU_C0:    case APU_C1:    case APU_C2:    case APU_C3:    case APU_C4:    case APU_C5:    case APU_C6:    case APU_C7:	S9xSetFilterCoefficient (reg >> 4, (signed char) byte);	break;    default:// XXX//printf ("Write %02x to unknown APU register %02x\n", byte, reg);	break;    }    if (reg < 0x80)	APU.DSP [reg] = byte;}void S9xFixEnvelope (int channel, uint8 gain, uint8 adsr1, uint8 adsr2){    if (adsr1 & 0x80)    {	// ADSR mode	static unsigned long AttackRate [16] = {	    4100, 2600, 1500, 1000, 640, 380, 260, 160,	    96, 64, 40, 24, 16, 10, 6, 1	};	static unsigned long DecayRate [8] = {	    1200, 740, 440, 290, 180, 110, 74, 37	};	static unsigned long SustainRate [32] = {	    ~0, 38000, 28000, 24000, 19000, 14000, 12000, 9400,	    7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500,	    1200, 880, 740, 590, 440, 370, 290, 220,	    180, 150, 110, 92, 74, 55, 37, 18	};	// XXX: can DSP be switched to ADSR mode directly from GAIN/INCREASE/	// DECREASE mode? And if so, what stage of the sequence does it start	// at?	if (S9xSetSoundMode (channel, MODE_ADSR))	{	    // Hack for ROMs that use a very short attack rate, key on a 	    // channel, then switch to decay mode. e.g. Final Fantasy II.	    int attack = AttackRate [adsr1 & 0xf];	    if (attack == 1 && (!Settings.SoundSync#ifdef __WIN32__                || Settings.SoundDriver != WIN_SNES9X_DIRECT_SOUND_DRIVER#endif                ))		attack = 0;	    S9xSetSoundADSR (channel, attack,			     DecayRate [(adsr1 >> 4) & 7],			     SustainRate [adsr2 & 0x1f],			     (adsr2 >> 5) & 7, 8);	}    }    else    {	// Gain mode	if ((gain & 0x80) == 0)	{	    if (S9xSetSoundMode (channel, MODE_GAIN))	    {		S9xSetEnvelopeRate (channel, 0, 0, gain & 0x7f);		S9xSetEnvelopeHeight (channel, gain & 0x7f);	    }	}	else	{	    static unsigned long IncreaseRate [32] = {		~0, 4100, 3100, 2600, 2000, 1500, 1300, 1000,		770, 640, 510, 380, 320, 260, 190, 160,		130, 96, 80, 64, 48, 40, 32, 24,		20, 16, 12, 10, 8, 6, 4, 2	    };	    static unsigned long DecreaseRateExp [32] = {		~0, 38000, 28000, 24000, 19000, 14000, 12000, 9400,		7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500,		1200, 880, 740, 590, 440, 370, 290, 220,		180, 150, 110, 92, 74, 55, 37, 18	    };	    if (gain & 0x40)	    {		// Increase mode		if (S9xSetSoundMode (channel, (gain & 0x20) ?					  MODE_INCREASE_BENT_LINE :					  MODE_INCREASE_LINEAR))		{		    S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f],					1, 127);		}	    }	    else	    {		uint32 rate = (gain & 0x20) ? DecreaseRateExp [gain & 0x1f] / 2 :					      IncreaseRate [gain & 0x1f];		int mode = (gain & 0x20) ? MODE_DECREASE_EXPONENTIAL					 : MODE_DECREASE_LINEAR;		if (S9xSetSoundMode (channel, mode))		    S9xSetEnvelopeRate (channel, rate, -1, 0);	    }	}    }}void S9xSetAPUControl (uint8 byte){//if (byte & 0x40)//printf ("*** Special SPC700 timing enabled\n");    if ((byte & 1) != 0 && !APU.TimerEnabled [0])    {	APU.Timer [0] = 0;	IAPU.RAM [0xfd] = 0;	if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0)	    APU.TimerTarget [0] = 0x100;    }    if ((byte & 2) != 0 && !APU.TimerEnabled [1])    {	APU.Timer [1] = 0;	IAPU.RAM [0xfe] = 0;	if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0)	    APU.TimerTarget [1] = 0x100;    }    if ((byte & 4) != 0 && !APU.TimerEnabled [2])    {	APU.Timer [2] = 0;	IAPU.RAM [0xff] = 0;	if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0)	    APU.TimerTarget [2] = 0x100;    }    APU.TimerEnabled [0] = byte & 1;    APU.TimerEnabled [1] = (byte & 2) >> 1;    APU.TimerEnabled [2] = (byte & 4) >> 2;    if (byte & 0x10)	IAPU.RAM [0xF4] = IAPU.RAM [0xF5] = 0;    if (byte & 0x20)	IAPU.RAM [0xF6] = IAPU.RAM [0xF7] = 0;    if (byte & 0x80)    {	if (!APU.ShowROM)	{	    memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM));	    APU.ShowROM = TRUE;	}    }    else    {	if (APU.ShowROM)	{	    APU.ShowROM = FALSE;	    memmove (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM));	}    }    IAPU.RAM [0xf1] = byte;}void S9xSetAPUTimer (uint16 Address, uint8 byte){    IAPU.RAM [Address] = byte;    switch (Address)    {    case 0xfa:	if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0)	    APU.TimerTarget [0] = 0x100;	APU.TimerValueWritten [0] = TRUE;	break;    case 0xfb:	if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0)	    APU.TimerTarget [1] = 0x100;	APU.TimerValueWritten [1] = TRUE;	break;    case 0xfc:	if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0)	    APU.TimerTarget [2] = 0x100;	APU.TimerValueWritten [2] = TRUE;	break;    }}uint8 S9xGetAPUDSP (){    uint8 reg = IAPU.RAM [0xf2] & 0x7f;    uint8 byte = APU.DSP [reg];    switch (reg)    {    case APU_OUTX + 0x00:    case APU_OUTX + 0x10:    case APU_OUTX + 0x20:    case APU_OUTX + 0x30:    case APU_OUTX + 0x40:    case APU_OUTX + 0x50:    case APU_OUTX + 0x60:    case APU_OUTX + 0x70:	if (SoundData.channels [reg >> 4].state == SOUND_SILENT)	    return (0);	return ((SoundData.channels [reg >> 4].sample >> 8) |		(SoundData.channels [reg >> 4].sample & 0xff));    case APU_ENVX + 0x00:    case APU_ENVX + 0x10:    case APU_ENVX + 0x20:    case APU_ENVX + 0x30:    case APU_ENVX + 0x40:    case APU_ENVX + 0x50:    case APU_ENVX + 0x60:    case APU_ENVX + 0x70:	return ((uint8) S9xGetEnvelopeHeight (reg >> 4));    case APU_ENDX:// To fix speech in Magical Drop 2 6/11/00//	APU.DSP [APU_ENDX] = 0;	break;    default:	break;    }    return (byte);}

⌨️ 快捷键说明

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