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

📄 nes_n106.cpp

📁 一个最快NFC的模拟器
💻 CPP
字号:
/*
** Namco 106 ExSound by TAKEDA, toshiya
**
** original: s_n106.c in nezp0922
*/

__inline static void UPDATE(N106_WM *chp)
{
	if (chp->update & 3)
	{
		uint32 freq;
		freq  = ((int)chp->freql);
		freq += ((int)chp->freqm) << 8;
		freq += ((int)chp->freqh) << 16;
		chp->spd = freq & 0x3ffff;
	}
	if (chp->update & 2)
	{
		uint32 tlen;
		tlen = (0x20 - (chp->freqh & 0x1c)) << 18;
		if (chp->tlen != tlen)
		{
			chp->tlen = tlen;
			chp->phase = 0;
		}
	}
	if (chp->update & 4)
	{
		chp->logvol = LinearToLog((chp->vreg & 0x0f) << 2);
	}
	chp->update = 0;
}

static int32 N106SoundRender(void)
{
	N106_WM *chp;
	int32 accum = 0;

	uint32 *tone = apu->n106s.tone;
	uint32 chinuse = apu->n106s.chinuse;
	uint32 cps = apu->n106s.cps;
	uint32 cyclesspd = chinuse << 20;
	uint32 mastervolume = apu->n106s.mastervolume;
	//for (chp = &apu->n106s.ch[8 - apu->n106s.chinuse]; chp < &apu->n106s.ch[8]; chp++)
	for (chp = &apu->n106s.ch[8 - chinuse]; chp < &apu->n106s.ch[8]; chp++)
	{
		//uint32 cyclesspd = apu->n106s.chinuse << 20;
		if (chp->update) UPDATE(chp);
		chp->cycles -= cps;
		while (chp->cycles < 0)
		{
			chp->cycles += cyclesspd;
			chp->phase += chp->spd;
		}
		while (chp->phase >= chp->tlen) chp->phase -= chp->tlen;
		if (chp->mute) continue;
		//accum += LogToLinear(apu->n106s.tone[((chp->phase >> 18) + chp->tadr) & 0xff] + chp->logvol + apu->n106s.mastervolume, LOG_LIN_BITS - LIN_BITS - LIN_BITS - 10);
		accum += LogToLinear(tone[((chp->phase >> 18) + chp->tadr) & 0xff] + chp->logvol + mastervolume, LOG_LIN_BITS - LIN_BITS - LIN_BITS - 10);
	}
	return accum;
}

static void N106SoundVolume(uint32 volume)
{
	apu->n106s.mastervolume = (volume << (LOG_BITS - 8)) << 1;
}

static void N106SoundWriteAddr(uint32 address, uint8 value)
{
	apu->n106s.address     = value & 0x7f;
	apu->n106s.addressauto = (value & 0x80) ? 1 : 0;
}

static void N106SoundWriteData(uint32 address, uint8 value)
{
	apu->n106s.data[apu->n106s.address] = value;
	apu->n106s.tone[apu->n106s.address * 2]     = LinearToLog(((int)(value & 0xf) << 2) - 0x20);
	apu->n106s.tone[apu->n106s.address * 2 + 1] = LinearToLog(((int)(value >>  4) << 2) - 0x20);
	if (apu->n106s.address >= 0x40)
	{
		N106_WM *chp = &apu->n106s.ch[(apu->n106s.address - 0x40) >> 3];
		switch (apu->n106s.address & 7)
		{
			case 0:
				chp->update |= 1;
				chp->freql = value;
				break;
			case 2:
				chp->update |= 1;
				chp->freqm = value;
				break;
			case 4:
				chp->update |= 2;
				chp->freqh = value;
				break;
			case 6:
				chp->tadr = value & 0xff;
				break;
			case 7:
				chp->update |= 4;
				chp->vreg = value;
				chp->nazo = (value >> 4) & 0x07;
				if (chp == &apu->n106s.ch[7])
					apu->n106s.chinuse = 1 + chp->nazo;
				break;
		}
	}
	if (apu->n106s.addressauto)
	{
		apu->n106s.address = (apu->n106s.address + 1) & 0x7f;
	}
}

static void N106SoundWrite(uint32 address, uint8 value)
{
	if (address == 0x4800)
	{
		N106SoundWriteData(address, value);
	}
	else if (address == 0xF800)
	{
		N106SoundWriteAddr(address, value);
	}
}

static uint8 N106SoundReadData(uint32 address)
{
	uint8 ret = apu->n106s.data[apu->n106s.address];
	if (apu->n106s.addressauto)
	{
		apu->n106s.address = (apu->n106s.address + 1) & 0x7f;
	}
	return ret;
}

static uint8 N106SoundRead(uint32 address)
{
	if (address == 0x4800)
	{
		return N106SoundReadData(address);
	}
	else
	{
		return 0x00;
	}
}

static void N106SoundReset(void)
{
	int i;

	apu_t *apu;
	apu = apu_getcontext ();

	memset (&apu->n106s, 0, sizeof(N106SOUND));
	for (i = 0; i < 8; i++)
	{
		apu->n106s.ch[i].tlen = 0x10 << 18;
		apu->n106s.ch[i].logvol = LinearToLog(0);
	}

	apu->n106s.addressauto = 1;
	apu->n106s.chinuse = 8;
	apu->n106s.cps = DivFix(NES_BASECYCLES, 45 * SAMPLE_RATE, 20);
}

⌨️ 快捷键说明

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