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

📄 nes_vrc6.cpp

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

static int32 VRC6SoundSquareRender(VRC6_SQUARE *ch)
{
	uint32 output;
	if (ch->update)
	{
		if (ch->update & (2 | 4))
		{
			ch->spd = (((ch->regs[2] & 0x0F) << 8) + ch->regs[1] + 1) << 18;
		}
		ch->update = 0;
	}

	if (!ch->spd) return 0;

	ch->cycles -= ch->cps;
	while (ch->cycles < 0)
	{
		ch->cycles += ch->spd;
		ch->adr++;
	}
	ch->adr &= 0xF;

	if (ch->mute || !(ch->regs[2] & 0x80)) return 0;

	output = LinearToLog(ch->regs[0] & 0x0F) + apu->vrc6s.mastervolume;
	if (!(ch->regs[0] & 0x80) && (ch->adr < ((ch->regs[0] >> 4) + 1)))
	{
#if 1
		return 0;	/* and array gate */
#else
		output++;	/* negative gate */
#endif
	}
	return LogToLinear(output, LOG_LIN_BITS - LIN_BITS - 16 - 1);
}

static int32 VRC6SoundSawRender(VRC6_SAW *ch)
{
	uint32 output;

	if (ch->update)
	{
		if (ch->update & (2 | 4))
		{
			ch->spd = (((ch->regs[2] & 0x0F) << 8) + ch->regs[1] + 1) << 18;
		}
		ch->update = 0;
	}

	if (!ch->spd) return 0;

	ch->cycles -= ch->cps;
	while (ch->cycles < 0)
	{
		ch->cycles += ch->spd;
		ch->output += (ch->regs[0] & 0x3F);
		if (7 == ++ch->adr)
		{
			ch->adr = 0;
			ch->output = 0;
		}
	}

	if (ch->mute || !(ch->regs[2] & 0x80)) return 0;

	output = LinearToLog((ch->output >> 3) & 0x1F) + apu->vrc6s.mastervolume;
	return LogToLinear(output, LOG_LIN_BITS - LIN_BITS - 16 - 1);
}

static int32 VRC6SoundRender(void)
{
	int32 accum = 0;
	accum += VRC6SoundSquareRender(&apu->vrc6s.square[0]);
	accum += VRC6SoundSquareRender(&apu->vrc6s.square[1]);
	accum += VRC6SoundSawRender(&apu->vrc6s.saw);
	return accum;
}

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

static void VRC6SoundWrite9000(uint32 address, uint8 value)
{
	apu->vrc6s.square[0].regs[address & 3] = value;
	apu->vrc6s.square[0].update |= 1 << (address & 3); 
}
static void VRC6SoundWriteA000(uint32 address, uint8 value)
{
	apu->vrc6s.square[1].regs[address & 3] = value;
	apu->vrc6s.square[1].update |= 1 << (address & 3); 
}
static void VRC6SoundWriteB000(uint32 address, uint8 value)
{
	apu->vrc6s.saw.regs[address & 3] = value;
	apu->vrc6s.saw.update |= 1 << (address & 3); 
}

static void VRC6SoundWrite(uint32 address, uint8 value)
{
	switch(address & 0xF000) {
		case 0x9000:
			VRC6SoundWrite9000(address, value);
			break;
		case 0xA000:
			VRC6SoundWriteA000(address, value);
			break;
		case 0xB000:
			VRC6SoundWriteB000(address, value);
			break;
	}
}

static void VRC6SoundSquareReset(VRC6_SQUARE *ch)
{
	ch->cps = DivFix(NES_BASECYCLES, 12 * SAMPLE_RATE, 18);
}

static void VRC6SoundSawReset(VRC6_SAW *ch)
{
	ch->cps = DivFix(NES_BASECYCLES, 24 * SAMPLE_RATE, 18);
}

static void VRC6SoundReset(void)
{
	memset(&apu->vrc6s, 0, sizeof(VRC6SOUND));
	VRC6SoundSquareReset(&apu->vrc6s.square[0]);
	VRC6SoundSquareReset(&apu->vrc6s.square[1]);
	VRC6SoundSawReset(&apu->vrc6s.saw);
}

⌨️ 快捷键说明

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