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

📄 s_vrc7.c

📁 一款游戏机的模拟器
💻 C
字号:
#include	"..\..\interface.h"
#include	"s_vrc7.h"

/* #define	REALOPL	/* Use real OPL2 instead of software emulation */

#ifndef	REALOPL
#include	"s_fmopl.h"
#endif

#define	REGSET	5

static	struct
{
	const u8 InstTrans[6];
	u8 Instrument[16][8];
	u8 Chan1x[6], Chan2x[6], Chan3x[6];
	u8 Latch;
}	VRC7sound = {
	{0x00,0x01,0x02,0x08,0x09,0x0A},
#if (REGSET == 1)					// Quietust
{	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},	/* The custom instrument */
	{0x03,0x01,0x14,0x80,0xC2,0x90,0x43,0x14},	/* Currently working on this one */
	{0x13,0x41,0x10,0x0B,0xFF,0xF2,0x32,0xD6},
	{0x01,0x01,0x10,0x08,0xF0,0xF4,0x00,0x04},	/* 90% perfect */
	{0x21,0x41,0x1B,0x08,0x66,0x80,0x30,0x85},
	{0x22,0x21,0x20,0x03,0x75,0x70,0x24,0x14},
	{0x02,0x01,0x06,0x00,0xF0,0xF2,0x03,0x95},	/* Do not touch! 98% perfect! */
	{0x21,0x41,0x18,0x10,0x93,0xE0,0x21,0x15},
	{0x01,0x22,0x13,0x00,0xF0,0x82,0x00,0x15},
	{0x05,0x01,0x22,0x00,0x60,0xE3,0xA0,0xF5},	/* 90% perfect */
	{0x85,0x01,0x20,0x00,0xD7,0xA2,0x22,0xF5},	/* 90% perfect */
	{0x07,0x81,0x2B,0x05,0xF4,0xF2,0x14,0xF4},	/* 95% perfect */
	{0x21,0x41,0x20,0x18,0xF3,0x80,0x13,0x95},
	{0x01,0x02,0x20,0x00,0xF9,0x92,0x41,0x75},	/* Do not touch! 98% perfect! */
	{0x21,0x62,0x0E,0x00,0x84,0x85,0x45,0x15},	/* 90% perfect */
	{0x21,0x62,0x0E,0x00,0xA1,0xA0,0x34,0x16}	}
#elif (REGSET == 2)					// MAME
{	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
	{0x01,0x22,0x23,0x00,0xF0,0xF0,0x07,0x18},
	{0x23,0x01,0x68,0x00,0xF2,0x74,0x6C,0x89},
	{0x13,0x11,0x25,0x03,0xD2,0xB2,0xF4,0xF4},
	{0x22,0x21,0x1B,0x00,0xC0,0xA1,0x18,0x08},
	{0x22,0x21,0x2C,0x00,0xD2,0xA1,0x18,0x57},
	{0x01,0x22,0xBA,0x03,0xF1,0xF1,0x1E,0x04},
	{0x21,0x21,0x28,0x00,0xF1,0xF1,0x6B,0x3E},
	{0x27,0x21,0x60,0x00,0xF0,0xF0,0x0D,0x0F},
	{0x20,0x21,0x2B,0x00,0x85,0xF1,0x6D,0x89},
	{0x01,0x21,0xBF,0x08,0x53,0x62,0x5F,0xAE},
	{0x23,0x21,0x70,0x0D,0xD4,0xA3,0x4E,0x64},
	{0x2B,0x21,0xA4,0x00,0xF6,0x93,0x5C,0x4D},
	{0x21,0x23,0xAD,0x00,0x77,0xF1,0x18,0x37},
	{0x21,0x21,0x2A,0x00,0xF3,0xE2,0x29,0x46},
	{0x21,0x23,0x37,0x00,0xF3,0xE2,0x29,0x46}	}
#elif (REGSET == 3)					// EMU2413
{	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
	{0x61,0x61,0x1E,0x17,0xF0,0x7F,0x07,0x17},
	{0x13,0x41,0x0F,0x0D,0xCE,0xD2,0x43,0x13},
	{0x03,0x01,0x99,0x04,0xFF,0xC3,0x03,0x73},
	{0x21,0x61,0x1B,0x07,0xAF,0x63,0x40,0x28},
	{0x22,0x21,0x1E,0x06,0xF0,0x76,0x08,0x28},
	{0x31,0x22,0x16,0x05,0x90,0x7F,0x00,0x08},
	{0x21,0x61,0x1D,0x07,0x82,0x81,0x10,0x17},
	{0x23,0x21,0x2D,0x16,0xC0,0x70,0x07,0x07},
	{0x61,0x21,0x1B,0x06,0x64,0x65,0x18,0x18},
	{0x61,0x61,0x0C,0x18,0x85,0xA0,0x79,0x07},
	{0x23,0x21,0x87,0x11,0xF0,0xA4,0x00,0xF7},
	{0x97,0xE1,0x28,0x07,0xFF,0xF3,0x02,0xF8},
	{0x61,0x10,0x0C,0x05,0xF2,0xC4,0x40,0xC8},
	{0x01,0x01,0x56,0x03,0xB4,0xB2,0x23,0x58},
	{0x49,0x4C,0x4C,0x32,0x00,0x00,0x00,0x00}	}
#elif (REGSET == 4)					// Allegro
{	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
	{0x31,0x21,0x15,0x0C,0xDD,0x56,0x13,0x26},
	{0x03,0x11,0x54,0x0E,0xF3,0xF1,0x9A,0xE7},
	{0x21,0x21,0x8F,0x04,0xF2,0xF2,0x45,0x76},
	{0xE1,0xE1,0x46,0x00,0x88,0x65,0x5F,0x1A},
	{0x32,0x21,0x90,0x02,0x9B,0x72,0x21,0x17},
	{0x21,0x21,0x4B,0x0C,0xAA,0x8F,0x16,0x0A},
	{0x21,0x21,0x92,0x06,0x85,0x8F,0x17,0x09},
	{0x23,0xB1,0x93,0x0A,0x97,0x55,0x23,0x14},
	{0x21,0x21,0x9B,0x01,0x61,0x7F,0x6A,0x0A},
	{0x71,0x72,0x57,0x06,0x54,0x7A,0x05,0x05},
	{0x21,0x36,0x80,0x04,0xA2,0xF1,0x01,0xD5},
	{0x18,0x81,0x62,0x00,0xF3,0xF2,0xE6,0xF6},
	{0x31,0x31,0x8B,0x05,0xF4,0xF1,0xE8,0x78},
	{0x21,0xA2,0x1E,0x01,0x94,0xC3,0x06,0xA6},
	{0x03,0x21,0x87,0x8B,0xF6,0xF3,0x22,0xF8}	}
#elif (REGSET == 5)					// Some MSX emulator
{	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
	{0x33,0x01,0x09,0x0E,0x94,0x90,0x40,0x01},
	{0x13,0x41,0x0F,0x0D,0xCD,0xD3,0x43,0x13},
	{0x01,0x12,0x1B,0x06,0xFF,0xD2,0x00,0x32},
	{0x61,0x61,0x1B,0x07,0xAF,0x63,0x20,0x28},
	{0x22,0x21,0x1E,0x06,0xF0,0x76,0x08,0x28},
//	{0x66,0x21,0x15,0x00,0x93,0x94,0x20,0xF8},
		{0x02,0x01,0x06,0x00,0xF0,0xF2,0x03,0x95},	/* My version sounds better */
	{0x21,0x61,0x1C,0x07,0x82,0x81,0x10,0x17},
	{0x23,0x21,0x20,0x1F,0xC0,0x71,0x07,0x47},
	{0x25,0x31,0x26,0x05,0x64,0x41,0x18,0xF8},
	{0x17,0x21,0x28,0x07,0xFF,0x83,0x02,0xF8},
//	{0x97,0x81,0x25,0x07,0xCF,0xC8,0x02,0x14},
		{0x07,0x81,0x2B,0x05,0xF4,0xF2,0x14,0xF4},	/* My version sounds better */
	{0x21,0x21,0x54,0x0F,0x80,0x7F,0x07,0x07},
//	{0x01,0x01,0x56,0x03,0xD3,0xB2,0x43,0x58},
		{0x01,0x02,0x20,0x00,0xF9,0x92,0x41,0x75},	/* My version sounds better */
	{0x31,0x21,0x0C,0x03,0x82,0xC0,0x40,0x07},
	{0x21,0x01,0x0C,0x03,0xD4,0xD3,0x40,0x84}	}

#endif
};

#ifndef	REALOPL
static	FM_OPL	*OPL = NULL;
#endif

static	void	OPL2_setreg (u8 reg,u8 value)
{
#ifdef	REALOPL
	_outp(0x388,reg);
	_outp(0x389,value);
#else
	if (OPL)
	{
		OPLWrite(OPL,0x388,reg);
		OPLWrite(OPL,0x389,value);
	}
#endif
}

static	void	VRC7_LoadInstrument(u8 Chan)
{
	u8 x = VRC7sound.InstTrans[Chan];
	u8 y = (VRC7sound.Chan3x[Chan] >> 4) & 0xF;

	OPL2_setreg((u8)(0x20+x),(u8)(VRC7sound.Instrument[y][0]));
	OPL2_setreg((u8)(0x23+x),(u8)(VRC7sound.Instrument[y][1]));
	OPL2_setreg((u8)(0x40+x),(u8)(VRC7sound.Instrument[y][2]));
/*	OPL2_setreg((u8)(0x43+x),(u8)((VRC7sound.Instrument[y][3] & 0xC0) | ((VRC7sound.Chan3x[Chan] << 0) & 0x3C)));	/* really loud */
/*	OPL2_setreg((u8)(0x43+x),(u8)((VRC7sound.Instrument[y][3] & 0xC0) | ((VRC7sound.Chan3x[Chan] << 1) & 0x3C)));	/* loud */
	OPL2_setreg((u8)(0x43+x),(u8)((VRC7sound.Instrument[y][3] & 0xC0) | ((VRC7sound.Chan3x[Chan] << 2) & 0x3C)));	/* quiet */
	OPL2_setreg((u8)(0xe0+x),(u8)((VRC7sound.Instrument[y][3] >> 3) & 0x01));
	OPL2_setreg((u8)(0xe3+x),(u8)((VRC7sound.Instrument[y][3] >> 4) & 0x01));
	OPL2_setreg((u8)(0xC0+Chan),(u8)((VRC7sound.Instrument[y][3] << 1) & 0x0E));
	OPL2_setreg((u8)(0x60+x),(u8)(VRC7sound.Instrument[y][4]));
	OPL2_setreg((u8)(0x63+x),(u8)(VRC7sound.Instrument[y][5]));
	OPL2_setreg((u8)(0x80+x),(u8)(VRC7sound.Instrument[y][6]));
	OPL2_setreg((u8)(0x83+x),(u8)(VRC7sound.Instrument[y][7]));
}

void	VRC7sound_Init (void)
{
	u8 x;
#ifdef	REALOPL
	int i;
	for (i = 0; i < 256; i++)
	{
		_outp(0x388,i);
		_outp(0x389,0);
	}
#else
	if (OPL)
	{
		MessageBox(NULL,"Error! Attempted to initialize more than one OPL2!","NESten",MB_OK | MB_ICONERROR);
		return;
	}
	OPL = OPLCreate(3579545,44100);
	if (!OPL)
	{
		MessageBox(NULL,"Unable to create OPL2!","NESten",MB_OK | MB_ICONERROR);
		return;
	}
#endif

#ifdef	REALOPL
	for (x = 0x20; x <= 0xFF; x++)
		OPL2_setreg(x,0);
#else
	OPLResetChip(OPL);
#endif
	OPL2_setreg(0x01,0x20);	/* Allow select waveform */
	OPL2_setreg(0x08,0x00);	/* Clear CSM/keyboard split */
	OPL2_setreg(0xBD,0xC0);	/* Set tremolo/vibrato depth */
	for (x = 0; x < 6; x++)
		VRC7sound.Chan1x[x] = VRC7sound.Chan2x[x] = VRC7sound.Chan3x[x] = 0;
	VRC7sound.Latch = 0;
}

void	VRC7sound_Write (int Where, int What)
{
	u8 x = VRC7sound.Latch & 0x0F, y;
	switch (Where & 0xF030)
	{
	case 0x9010:	VRC7sound.Latch = What;	break;
	case 0x9030:	switch ((VRC7sound.Latch & 0xF0) >> 4)
			{
			case 0:	if (x & 0x08)		break;
				VRC7sound.Instrument[0][x] = What;
				for (y = 0; y < 6; y++)
					if (!(VRC7sound.Chan3x[y] & 0xF0))
						VRC7_LoadInstrument(y);
							break;
			case 1:	if (x > 5)		break;
				VRC7sound.Chan1x[x] = What;
				OPL2_setreg((u8)(0xA0 + x),(u8)((VRC7sound.Chan1x[x] << 1) & 0xFE));
				OPL2_setreg((u8)(0xB0 + x),(u8)(((VRC7sound.Chan1x[x] >> 7) & 0x01) | ((VRC7sound.Chan2x[x] << 1) & 0x3E)));
							break;
			case 2:	if (x > 5)		break;
				VRC7sound.Chan2x[x] = What;
				OPL2_setreg((u8)(0xB0 + x),(u8)(((VRC7sound.Chan1x[x] >> 7) & 0x01) | ((VRC7sound.Chan2x[x] << 1) & 0x3E)));
							break;
			case 3:	if (x > 5)		break;
				VRC7sound.Chan3x[x] = What;
				VRC7_LoadInstrument(x);	break;
			}			break;
	}
}

void	VRC7sound_Get (s16 *Target, int Size)
{
#ifndef	REALOPL
	YM3812UpdateOne(OPL,Target,Size);
#endif
}

int	VRC7sound_SaveMI (Ar128 MI, int x)
{
	u8 i;
			MI[x++] = VRC7sound.Latch;
for (i = 0; i < 8; i++)	MI[x++] = VRC7sound.Instrument[0][i];
for (i = 0; i < 6; i++)	MI[x++] = VRC7sound.Chan1x[i];
for (i = 0; i < 6; i++)	MI[x++] = VRC7sound.Chan2x[i];
for (i = 0; i < 6; i++)	MI[x++] = VRC7sound.Chan3x[i];
	return x;
}

int	VRC7sound_LoadMI (const Ar128 MI, int x)
{
	u8 i;
			VRC7sound.Latch			= MI[x++];
for (i = 0; i < 8; i++)	VRC7sound.Instrument[0][i]	= MI[x++];
for (i = 0; i < 6; i++)	VRC7sound.Chan1x[i]		= MI[x++];
for (i = 0; i < 6; i++)	VRC7sound.Chan2x[i]		= MI[x++];
for (i = 0; i < 6; i++)	VRC7sound.Chan3x[i]		= MI[x++];

for (x = 0; x < 6; x++){VRC7_LoadInstrument((u8)x);
			VRC7sound_Write((u8)(0x10 + x),VRC7sound.Chan1x[x]);}
	return x;
}

void	VRC7sound_Destroy (void)
{
#ifndef	REALOPL
	if (OPL)
	{
		OPLDestroy(OPL);
		OPL = NULL;
	}
	else	MessageBox(NULL,"Error! Attempted to destroy nonexistant OPL2!","NESten",MB_OK | MB_ICONERROR);
#endif
}

⌨️ 快捷键说明

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