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

📄 ym2151.c

📁 十七种模拟器源代码 非常有用的作课程设计不可缺少的
💻 C
📖 第 1 页 / 共 4 页
字号:
			chip->noise_f = chip->noise_tab[ v & 0x1f ];			#if 0			if (v){				usrintf_showmessage("YM2151 noise mode = %02x",v);				logerror("YM2151 noise (%02x)\n",v);			}			#endif			break;		case 0x10: /*timer A hi*/			chip->TimAIndex = (chip->TimAIndex & 0x003) | (v<<2);			break;		case 0x11: /*timer A low*/			chip->TimAIndex = (chip->TimAIndex & 0x3fc) | (v & 3);			break;		case 0x12: /*timer B*/			chip->TimBIndex = v;			break;		case 0x14: /*CSM, irq flag reset, irq enable, timer start/stop*/			chip->IRQenable = v;	/*bit 3-timer B, bit 2-timer A, bit 7 - CSM */			if (v&0x20)	/*reset timer B irq flag*/			{				int oldstate = chip->status & 3;				chip->status &= 0xfd;				if ((oldstate==2) && (chip->irqhandler)) (*chip->irqhandler)(0);			}			if (v&0x10)	/*reset timer A irq flag*/			{				int oldstate = chip->status & 3;				chip->status &= 0xfe;				if ((oldstate==1) && (chip->irqhandler)) (*chip->irqhandler)(0);			}			if (v&0x02){	/*load and start timer B*/				#ifdef USE_MAME_TIMERS				/* ASG 980324: added a real timer */				/* start timer _only_ if it wasn't already started (it will reload time value next round)*/					if (!chip->TimBTimer)					{						chip->TimBTimer = timer_set (chip->TimerBTime[ chip->TimBIndex ], n, timer_callback_b);						chip->TimBOldIndex = chip->TimBIndex;					}					#if 0					else					{						/*check if timer value has changed since last start and update if necessary*/						if (chip->TimBIndex!=chip->TimBOldIndex)						{							double timepassed = timer_timeelapsed(chip->TimBTimer);							timer_remove (chip->TimBTimer);							chip->TimBTimer = timer_set (chip->TimerBTime[ chip->TimBIndex ] - timepassed, n, timer_callback_b);							chip->TimBOldIndex = chip->TimBIndex;						}					}					#endif				#else					if (!chip->TimB)					{						chip->TimB = 1;						chip->TimBVal = chip->TimerB[ chip->TimBIndex ];					}				#endif			}else{		/*stop timer B*/				#ifdef USE_MAME_TIMERS				/* ASG 980324: added a real timer */					if (chip->TimBTimer) timer_remove (chip->TimBTimer);					chip->TimBTimer = 0;				#else					chip->TimB = 0;				#endif			}			if (v&0x01){	/*load and start timer A*/				#ifdef USE_MAME_TIMERS				/* ASG 980324: added a real timer */				/* start timer _only_ if it wasn't already started (it will reload time value next round)*/					if (!chip->TimATimer)					{						chip->TimATimer = timer_set (chip->TimerATime[ chip->TimAIndex ], n, timer_callback_a);						chip->TimAOldIndex = chip->TimAIndex;					}					#if 0					else					{						/*check if timer value has changed since last start and update if necessary*/						if (chip->TimAIndex!=chip->TimAOldIndex)						{							double timepassed = timer_timeelapsed(chip->TimATimer);							timer_remove (chip->TimATimer);							chip->TimATimer = timer_set (chip->TimerATime[ chip->TimAIndex ] - timepassed, n, timer_callback_a);							chip->TimAOldIndex = chip->TimAIndex;						}					}					#endif				#else					if (!chip->TimA)					{						chip->TimA = 1;						chip->TimAVal = chip->TimerA[ chip->TimAIndex ];					}				#endif			}else{		/*stop timer A*/				#ifdef USE_MAME_TIMERS				/* ASG 980324: added a real timer */					if (chip->TimATimer) timer_remove (chip->TimATimer);					chip->TimATimer = 0;				#else					chip->TimA = 0;				#endif			}			break;		case 0x18: /*LFO frequency*/			chip->LFOfrq = chip->LFOfreq[ v ];			break;		case 0x19: /*PMD (bit 7==1) or AMD (bit 7==0)*/			if (v&0x80)				chip->PMD = lfo_md_tab[ v&0x7f ] + 512;			else				chip->AMD = lfo_md_tab[ v&0x7f ];			break;		case 0x1b: /*CT2, CT1, LFO waveform*/			chip->CT = v;			chip->LFOwave = (v & 3) * LFO_LEN*2;			if (chip->porthandler) (*chip->porthandler)(0 , (chip->CT) >> 6 );			break;		default:		  //logerror("YM2151 Write %02x to undocumented register #%02x\n",v,r);			break;		}		break;	case 0x20:		op = &chip->Oscils[r & 7];		switch(r & 0x18){		case 0x00: /*RL enable, Feedback, Connection */			op->FeedBack = ((v>>3)&7) ? ((v>>3)&7)+6:0;			chip->PAN[ (r&7)*2    ] = (v & 0x40) ? 0xffffffff : 0x0;			chip->PAN[ (r&7)*2 +1 ] = (v & 0x80) ? 0xffffffff : 0x0;			set_connect(op, v, r&7);			break;		case 0x08: /*Key Code*/			v &= 0x7f;			if ((unsigned int)v != op->KC)			{				unsigned int kc, kc_channel;				kc_channel = (v - (v>>2))*64;				kc_channel += 768;				kc_channel |= (op->KCindex & 63);				(op+ 0)->KC = v;				(op+ 0)->KCindex = kc_channel;				(op+ 8)->KC = v;				(op+ 8)->KCindex = kc_channel;				(op+16)->KC = v;				(op+16)->KCindex = kc_channel;				(op+24)->KC = v;				(op+24)->KCindex = kc_channel;				kc = v>>2;				(op+ 0)->DT1v = chip->DT1freq[ (op+ 0)->DT1 + kc ];				(op+ 0)->freq = ( (chip->freq[ kc_channel + (op+ 0)->DT2 ] + (op+ 0)->DT1v) * (op+ 0)->MUL ) >> 1;				(op+ 8)->DT1v = chip->DT1freq[ (op+ 8)->DT1 + kc ];				(op+ 8)->freq = ( (chip->freq[ kc_channel + (op+ 8)->DT2 ] + (op+ 8)->DT1v) * (op+ 8)->MUL ) >> 1;				(op+16)->DT1v = chip->DT1freq[ (op+16)->DT1 + kc ];				(op+16)->freq = ( (chip->freq[ kc_channel + (op+16)->DT2 ] + (op+16)->DT1v) * (op+16)->MUL ) >> 1;				(op+24)->DT1v = chip->DT1freq[ (op+24)->DT1 + kc ];				(op+24)->freq = ( (chip->freq[ kc_channel + (op+24)->DT2 ] + (op+24)->DT1v) * (op+24)->MUL ) >> 1;				refresh_EG( chip, op );			}			break;		case 0x10: /*Key Fraction*/			v >>= 2;			if ((unsigned int)v !=  (op->KCindex & 63))			{				unsigned int kc_channel;				kc_channel = v;				kc_channel |= (op->KCindex & ~63);				(op+ 0)->KCindex = kc_channel;				(op+ 8)->KCindex = kc_channel;				(op+16)->KCindex = kc_channel;				(op+24)->KCindex = kc_channel;				(op+ 0)->freq = ( (chip->freq[ kc_channel + (op+ 0)->DT2 ] + (op+ 0)->DT1v) * (op+ 0)->MUL ) >> 1;				(op+ 8)->freq = ( (chip->freq[ kc_channel + (op+ 8)->DT2 ] + (op+ 8)->DT1v) * (op+ 8)->MUL ) >> 1;				(op+16)->freq = ( (chip->freq[ kc_channel + (op+16)->DT2 ] + (op+16)->DT1v) * (op+16)->MUL ) >> 1;				(op+24)->freq = ( (chip->freq[ kc_channel + (op+24)->DT2 ] + (op+24)->DT1v) * (op+24)->MUL ) >> 1;			}			break;		case 0x18: /*PMS,AMS*/			op->PMS = (v>>4) & 7;			op->AMS = v & 3;			break;		}		break;	case 0x40: /*DT1, MUL*/		{			unsigned int oldDT1 = op->DT1;			unsigned int oldMUL = op->MUL;			op->DT1 = (v&0x70)<<1;			op->MUL = (v&0x0f) ? (v&0x0f)<<1: 1;			if (oldDT1 != op->DT1)			{				op->DT1v = chip->DT1freq[ op->DT1 + (op->KC>>2) ];			}			if ( (oldDT1 != op->DT1) || (oldMUL != op->MUL) )			{				op->freq = ( (chip->freq[ op->KCindex + op->DT2 ] + op->DT1v) * op->MUL ) >> 1;			}		}		break;	case 0x60: /*TL*/		op->TL = (v&0x7f)<<(ENV_BITS-7); /*7bit TL*/		break;	case 0x80: /*KS, AR*/		{			int oldKS = op->KS;			int oldAR = op->AR;			op->KS = 5-(v>>6);			op->AR = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;			if ( (op->AR != (unsigned int)oldAR) || (op->KS != (unsigned int)oldKS) )			{				if ((op->AR + (op->KC>>op->KS)) < 32+62)					op->delta_AR  = chip->EG_tab[op->AR  + (op->KC>>op->KS) ];				else					op->delta_AR  = MAX_ATT_INDEX+1;			}			if (op->KS != (unsigned int)oldKS)			{				op->delta_D1R = chip->EG_tab[op->D1R + (op->KC>>op->KS) ];				op->delta_D2R = chip->EG_tab[op->D2R + (op->KC>>op->KS) ];				op->delta_RR  = chip->EG_tab[op->RR  + (op->KC>>op->KS) ];			}		}		break;	case 0xa0: /*AMS-EN, D1R*/		op->AMSmask = (v&0x80) ? 0xffffffff : 0;		op->D1R     = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;		op->delta_D1R = chip->EG_tab[op->D1R + (op->KC>>op->KS) ];		break;	case 0xc0: /*DT2, D2R*/		{			unsigned int oldDT2 = op->DT2;			op->DT2 = DT2_tab[ v>>6 ];			if (op->DT2 != oldDT2)			{				op->freq = ( (chip->freq[ op->KCindex + op->DT2 ] + op->DT1v) * op->MUL ) >> 1;			}		}		op->D2R = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;		op->delta_D2R = chip->EG_tab[op->D2R + (op->KC>>op->KS) ];		break;	case 0xe0: /*D1L, RR*/		op->D1L = D1L_tab[ v>>4 ];		op->RR  = 34 + ((v&0x0f)<<2);		op->delta_RR  = chip->EG_tab[op->RR  + (op->KC>>op->KS) ];		break;	}}#ifdef LOG_CYM_FILEstatic void cymfile_callback (int n){	if (cymfile)	{		fputc( (unsigned char)0, cymfile );	}}#endifint YM2151ReadStatus( int n ){	return YMPSG[n].status;}/*** Initialize YM2151 emulator(s).**** 'num' is the number of virtual YM2151's to allocate** 'clock' is the chip clock in Hz** 'rate' is sampling rate*/int YM2151Init(int num, int clock, int rate){	int i;	if (YMPSG) return (-1);	/* duplicate init. */	YMNumChips = num;	YMPSG = (YM2151 *)malloc(sizeof(YM2151) * YMNumChips);	if (YMPSG == NULL) return (1);	memset(YMPSG, 0, sizeof(YM2151) * YMNumChips);#if 0	TL_TAB = (signed int *)malloc(sizeof(signed int) * TL_TAB_LEN );	if (TL_TAB == NULL)	{		free(YMPSG);		YMPSG=NULL;		return (1);	}#endif	init_tables();	for (i=0 ; (unsigned int)i<YMNumChips; i++)	{		YMPSG[i].clock = clock;		/*rate = clock/64;*/		YMPSG[i].sampfreq = rate ? rate : 44100;	/* avoid division by 0 in init_chip_tables() */		YMPSG[i].irqhandler = NULL;					/*interrupt handler */		YMPSG[i].porthandler = NULL;				/*port write handler*/		init_chip_tables(&YMPSG[i]);#ifdef USE_MAME_TIMERS/*this must be done _before_ a call to YM2151ResetChip() */		YMPSG[i].TimATimer = 0;		YMPSG[i].TimBTimer = 0;#else		YMPSG[i].TimA      = 0;		YMPSG[i].TimB      = 0;#endif		YM2151ResetChip(i);		/*logerror("YM2151[init] clock=%i sampfreq=%i\n", YMPSG[i].clock, YMPSG[i].sampfreq);*/	}#ifdef LOG_CYM_FILE	cymfile = fopen("2151_.cym","wb");	if (cymfile)		cymfiletimer = timer_pulse ( TIME_IN_HZ(110), 0, cymfile_callback); /*110 Hz pulse timer*/	else		logerror("Could not create file 2151_.cym\n");#endif	return(0);}void YM2151Shutdown(){	if (!YMPSG) return;	free(YMPSG);	YMPSG = NULL;#if 0	if (TL_TAB)	{		free(TL_TAB);		TL_TAB=NULL;	}#endif#ifdef LOG_CYM_FILE	fclose(cymfile);	cymfile = NULL;	if (cymfiletimer) timer_remove (cymfiletimer);	cymfiletimer = 0;#endif#ifdef SAVE_SAMPLE	fclose(sample[8]);#endif#ifdef SAVE_SEPARATE_CHANNELS	fclose(sample[0]);	fclose(sample[1]);	fclose(sample[2]);	fclose(sample[3]);	fclose(sample[4]);	fclose(sample[5]);	fclose(sample[6]);	fclose(sample[7]);#endif}/*** reset all chip registers.*/void YM2151ResetChip(int num){	int i;	YM2151 *chip = &YMPSG[num];	/* initialize hardware registers */	for (i=0; i<32; i++)	{		memset(&chip->Oscils[i],'\0',sizeof(OscilRec));		chip->Oscils[i].volume = MAX_ATT_INDEX;	}	chip->LFOphase = 0;	chip->LFOfrq   = 0;	chip->LFOwave  = 0;	chip->PMD = lfo_md_tab[ 0 ] + 512;	chip->AMD = lfo_md_tab[ 0 ];	chip->LFA = 0;	chip->LFP = 0;	chip->test= 0;	chip->IRQenable = 0;#ifdef USE_MAME_TIMERS	/* ASG 980324 -- reset the timers before writing to the registers */	if (chip->TimATimer) timer_remove (chip->TimATimer);	chip->TimATimer = 0;	if (chip->TimBTimer) timer_remove (chip->TimBTimer);	chip->TimBTimer = 0;#else	chip->TimA      = 0;	chip->TimB      = 0;	chip->TimAVal   = 0;	chip->TimBVal   = 0;#endif	chip->TimAIndex = 0;	chip->TimBIndex = 0;	chip->TimAOldIndex = 0;	chip->TimBOldIndex = 0;	chip->noise     = 0;	chip->noiseRNG  = 0;	chip->noise_p   = 0;	chip->noise_f   = chip->noise_tab[0];	chip->CSMreq	= 0;	chip->status    = 0;	YM2151WriteReg(num, 0x1b, 0); /*only because of CT1, CT2 output pins*/	for (i=0x20; i<0x100; i++)   /*just to set the PM operators */	{		YM2151WriteReg(num, i, 0);	}}INLINE void lfo_calc(void){unsigned int phase, lfx;	if (PSG->test&2)	{		PSG->LFOphase = 0;		phase = PSG->LFOwave;	}	else	{		phase = (PSG->LFOphase>>LFO_SH) & LFO_MASK;		phase = phase*2 + PSG->LFOwave;	}	lfx = lfo_tab[phase] + PSG->AMD;	PSG->LFA = 0;	if (lfx < TL_TAB_LEN)		PSG->LFA = TL_TAB[ lfx ];	lfx = lfo_tab[phase+1] + PSG->PMD;	PSG->LFP = 0;	if (lfx < TL_TAB_LEN)		PSG->LFP = TL_TAB[ lfx ];}INLINE void calc_lfo_pm(OscilRec *op){signed int mod_ind, pom;	mod_ind = PSG->LFP; /* -128..+127 (8bits signed)*/	if (op->PMS < 6)		mod_ind >>= (6 - op->PMS);	else		mod_ind <<= (op->PMS - 5);	if (mod_ind)	{		unsigned int kc_channel;		kc_channel = op->KCindex + mod_ind;		pom = ( (PSG->freq[ kc_channel + op->DT2 ] + op->DT1v) * op->MUL ) >> 1;		op->phase += (pom - op->freq);		op+=8;		pom = ( (PSG->freq[ kc_channel + op->DT2 ] + op->DT1v) * op->MUL ) >> 1;		op->phase += (pom - op->freq);		op+=8;

⌨️ 快捷键说明

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