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

📄 fmopl.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 3 页
字号:
				}				/* TOP-CY key on/off */				if(rkey&0x02)				{					if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);					else       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);				}				/* HH key on/off */				if(rkey&0x01)				{					if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);					else       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);				}			}			}			return;		}		/* keyon,block,fnum */		if( (r&0x0f) > 8) return;		CH = &OPL->P_CH[r&0x0f];		if(!(r&0x10))		{	/* a0-a8 */			block_fnum  = (CH->block_fnum&0x1f00) | v;		}		else		{	/* b0-b8 */			int keyon = (v>>5)&1;			block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);			if(CH->keyon != keyon)			{				if( (CH->keyon=keyon) )				{					CH->op1_out[0] = CH->op1_out[1] = 0;					OPL_KEYON(&CH->SLOT[SLOT1]);					OPL_KEYON(&CH->SLOT[SLOT2]);				}				else				{					OPL_KEYOFF(&CH->SLOT[SLOT1]);					OPL_KEYOFF(&CH->SLOT[SLOT2]);				}			}		}		/* update */		if(CH->block_fnum != block_fnum)		{			int blockRv = 7-(block_fnum>>10);			int fnum   = block_fnum&0x3ff;			CH->block_fnum = block_fnum;			CH->ksl_base = KSL_TABLE[block_fnum>>6];			CH->fc = OPL->FN_TABLE[fnum]>>blockRv;			CH->kcode = CH->block_fnum>>9;			if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;			CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);			CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);		}		return;	case 0xc0:		/* FB,C */		if( (r&0x0f) > 8) return;		CH = &OPL->P_CH[r&0x0f];		{		int feedback = (v>>1)&7;		CH->FB   = feedback ? (8+1) - feedback : 0;		CH->CON = v&1;		set_algorythm(CH);		}		return;	case 0xe0: /* wave type */		slot = slot_array[r&0x1f];		if(slot == -1) return;		CH = &OPL->P_CH[slot/2];		if(OPL->wavesel)		{			/* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */			CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];		}		return;	}}/* lock/unlock for common table */static int OPL_LockTable(void){	num_lock++;	if(num_lock>1) return 0;	/* first time */	cur_chip = NULL;	/* allocate total level table (128kb space) */	if( !OPLOpenTable() )	{		num_lock--;		return -1;	}	return 0;}static void OPL_UnLockTable(void){	if(num_lock) num_lock--;	if(num_lock) return;	/* last time */	cur_chip = NULL;	OPLCloseTable();}#if (BUILD_YM3812 || BUILD_YM3526)/*******************************************************************************//*		YM3812 local section                                                   *//*******************************************************************************//* ---------- update one of chip ----------- */void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length){    int i;	int data;	OPLSAMPLE *buf = buffer;	UINT32 amsCnt  = OPL->amsCnt;	UINT32 vibCnt  = OPL->vibCnt;	UINT8 rythm = OPL->rythm&0x20;	OPL_CH *CH,*R_CH;	if( (void *)OPL != cur_chip ){		cur_chip = (void *)OPL;		/* channel pointers */		S_CH = OPL->P_CH;		E_CH = &S_CH[9];		/* rythm slot */		SLOT7_1 = &S_CH[7].SLOT[SLOT1];		SLOT7_2 = &S_CH[7].SLOT[SLOT2];		SLOT8_1 = &S_CH[8].SLOT[SLOT1];		SLOT8_2 = &S_CH[8].SLOT[SLOT2];		/* LFO state */		amsIncr = OPL->amsIncr;		vibIncr = OPL->vibIncr;		ams_table = OPL->ams_table;		vib_table = OPL->vib_table;	}	R_CH = rythm ? &S_CH[6] : E_CH;    for( i=0; i < length ; i++ )	{		/*            channel A         channel B         channel C      */		/* LFO */		ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];		vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];		outd[0] = 0;		/* FM part */		for(CH=S_CH ; CH < R_CH ; CH++)			OPL_CALC_CH(CH);		/* Rythn part */		if(rythm)			OPL_CALC_RH(S_CH);		/* limit check */		data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );		/* store to sound buffer */		buf[i] = data >> OPL_OUTSB;	}	OPL->amsCnt = amsCnt;	OPL->vibCnt = vibCnt;#ifdef OPL_OUTPUT_LOG	if(opl_dbg_fp)	{		for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)			if( opl_dbg_opl[opl_dbg_chip] == OPL) break;		fprintf(opl_dbg_fp,"%c%c%c",0x20+opl_dbg_chip,length&0xff,length/256);	}#endif}#endif /* (BUILD_YM3812 || BUILD_YM3526) */#if BUILD_Y8950void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length){    int i;	int data;	OPLSAMPLE *buf = buffer;	UINT32 amsCnt  = OPL->amsCnt;	UINT32 vibCnt  = OPL->vibCnt;	UINT8 rythm = OPL->rythm&0x20;	OPL_CH *CH,*R_CH;	YM_DELTAT *DELTAT = OPL->deltat;	/* setup DELTA-T unit */	YM_DELTAT_DECODE_PRESET(DELTAT);	if( (void *)OPL != cur_chip ){		cur_chip = (void *)OPL;		/* channel pointers */		S_CH = OPL->P_CH;		E_CH = &S_CH[9];		/* rythm slot */		SLOT7_1 = &S_CH[7].SLOT[SLOT1];		SLOT7_2 = &S_CH[7].SLOT[SLOT2];		SLOT8_1 = &S_CH[8].SLOT[SLOT1];		SLOT8_2 = &S_CH[8].SLOT[SLOT2];		/* LFO state */		amsIncr = OPL->amsIncr;		vibIncr = OPL->vibIncr;		ams_table = OPL->ams_table;		vib_table = OPL->vib_table;	}	R_CH = rythm ? &S_CH[6] : E_CH;    for( i=0; i < length ; i++ )	{		/*            channel A         channel B         channel C      */		/* LFO */		ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];		vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];		outd[0] = 0;		/* deltaT ADPCM */		if( DELTAT->portstate )			YM_DELTAT_ADPCM_CALC(DELTAT);		/* FM part */		for(CH=S_CH ; CH < R_CH ; CH++)			OPL_CALC_CH(CH);		/* Rythn part */		if(rythm)			OPL_CALC_RH(S_CH);		/* limit check */		data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );		/* store to sound buffer */		buf[i] = data >> OPL_OUTSB;	}	OPL->amsCnt = amsCnt;	OPL->vibCnt = vibCnt;	/* deltaT START flag */	if( !DELTAT->portstate )		OPL->status &= 0xfe;}#endif/* ---------- reset one of chip ---------- */void OPLResetChip(FM_OPL *OPL){	int c,s;	int i;	/* reset chip */	OPL->mode   = 0;	/* normal mode */	OPL_STATUS_RESET(OPL,0x7f);	/* reset with register write */	OPLWriteReg(OPL,0x01,0); /* wabesel disable */	OPLWriteReg(OPL,0x02,0); /* Timer1 */	OPLWriteReg(OPL,0x03,0); /* Timer2 */	OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */	for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);	/* reset OPerator paramater */	for( c = 0 ; c < OPL->max_ch ; c++ )	{		OPL_CH *CH = &OPL->P_CH[c];		/* OPL->P_CH[c].PAN = OPN_CENTER; */		for(s = 0 ; s < 2 ; s++ )		{			/* wave table */			CH->SLOT[s].wavetable = &SIN_TABLE[0];			/* CH->SLOT[s].evm = ENV_MOD_RR; */			CH->SLOT[s].evc = EG_OFF;			CH->SLOT[s].eve = EG_OFF+1;			CH->SLOT[s].evs = 0;		}	}#if BUILD_Y8950	if(OPL->type&OPL_TYPE_ADPCM)	{		YM_DELTAT *DELTAT = OPL->deltat;		DELTAT->freqbase = OPL->freqbase;		DELTAT->output_pointer = outd;		DELTAT->portshift = 5;		DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;		YM_DELTAT_ADPCM_Reset(DELTAT,0);	}#endif}/* ----------  Create one of vietual YM3812 ----------       *//* 'rate'  is sampling rate and 'bufsiz' is the size of the  */FM_OPL *OPLCreate(int type, int clock, int rate){	char *ptr;	FM_OPL *OPL;	int state_size;	int max_ch = 9; /* normaly 9 channels */	if( OPL_LockTable() ==-1) return NULL;	/* allocate OPL state space */	state_size  = sizeof(FM_OPL);	state_size += sizeof(OPL_CH)*max_ch;#if BUILD_Y8950	if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);#endif	/* allocate memory block */	ptr = malloc(state_size);	if(ptr==NULL) return NULL;	/* clear */	memset(ptr,0,state_size);	OPL        = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);	OPL->P_CH  = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;#if BUILD_Y8950	if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);#endif	/* set channel state pointer */	OPL->type  = type;	OPL->clock = clock;	OPL->rate  = rate;	OPL->max_ch = max_ch;	/* init grobal tables */	OPL_initalize(OPL);	/* reset chip */	OPLResetChip(OPL);#ifdef OPL_OUTPUT_LOG	if(!opl_dbg_fp)	{		opl_dbg_fp = fopen("opllog.opl","wb");		opl_dbg_maxchip = 0;	}	if(opl_dbg_fp)	{		opl_dbg_opl[opl_dbg_maxchip] = OPL;		fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip,			type,			clock&0xff,			(clock/0x100)&0xff,			(clock/0x10000)&0xff,			(clock/0x1000000)&0xff);		opl_dbg_maxchip++;	}#endif	return OPL;}/* ----------  Destroy one of vietual YM3812 ----------       */void OPLDestroy(FM_OPL *OPL){#ifdef OPL_OUTPUT_LOG	if(opl_dbg_fp)	{		fclose(opl_dbg_fp);		opl_dbg_fp = NULL;	}#endif	OPL_UnLockTable();	free(OPL);}/* ----------  Option handlers ----------       */void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset){	OPL->TimerHandler   = TimerHandler;	OPL->TimerParam = channelOffset;}void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param){	OPL->IRQHandler     = IRQHandler;	OPL->IRQParam = param;}void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param){	OPL->UpdateHandler = UpdateHandler;	OPL->UpdateParam = param;}#if BUILD_Y8950void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param){	OPL->porthandler_w = PortHandler_w;	OPL->porthandler_r = PortHandler_r;	OPL->port_param = param;}void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param){	OPL->keyboardhandler_w = KeyboardHandler_w;	OPL->keyboardhandler_r = KeyboardHandler_r;	OPL->keyboard_param = param;}#endif/* ---------- YM3812 I/O interface ---------- */int OPLWrite(FM_OPL *OPL,int a,int v){	if( !(a&1) )	{	/* address port */		OPL->address = v & 0xff;	}	else	{	/* data port */		if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);#ifdef OPL_OUTPUT_LOG	if(opl_dbg_fp)	{		for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)			if( opl_dbg_opl[opl_dbg_chip] == OPL) break;		fprintf(opl_dbg_fp,"%c%c%c",0x10+opl_dbg_chip,OPL->address,v);	}#endif		OPLWriteReg(OPL,OPL->address,v);	}	return OPL->status>>7;}unsigned char OPLRead(FM_OPL *OPL,int a){	if( !(a&1) )	{	/* status port */		return OPL->status & (OPL->statusmask|0x80);	}	/* data port */	switch(OPL->address)	{	case 0x05: /* KeyBoard IN */		if(OPL->type&OPL_TYPE_KEYBOARD)		{			if(OPL->keyboardhandler_r)				return OPL->keyboardhandler_r(OPL->keyboard_param);			else				LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n"));		}		return 0;#if 0	case 0x0f: /* ADPCM-DATA  */		return 0;#endif	case 0x19: /* I/O DATA    */		if(OPL->type&OPL_TYPE_IO)		{			if(OPL->porthandler_r)				return OPL->porthandler_r(OPL->port_param);			else				LOG(LOG_WAR,("OPL:read unmapped I/O port\n"));		}		return 0;	case 0x1a: /* PCM-DATA    */		return 0;	}	return 0;}int OPLTimerOver(FM_OPL *OPL,int c){	if( c )	{	/* Timer B */		OPL_STATUS_SET(OPL,0x20);	}	else	{	/* Timer A */		OPL_STATUS_SET(OPL,0x40);		/* CSM mode key,TL controll */		if( OPL->mode & 0x80 )		{	/* CSM mode total level latch and auto key on */			int ch;			if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);			for(ch=0;ch<9;ch++)				CSMKeyControll( &OPL->P_CH[ch] );		}	}	/* reload timer */	if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);	return OPL->status>>7;}

⌨️ 快捷键说明

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