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

📄 ym3812.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	return cFALSE;	/* Bad timer*/}/*$DEADSERIOUSCLAN$********************************************************************** ROUTINE*	ym3812_KeyOn( ym3812 *pOPL, nChannel )* FUNCTION*	Set Key On State for both slots related to this channel* NOTES****************************************************************************************/void ym3812_KeyOn( ym3812 *pOPL, int nChannel ){	int nSlot;	if( !pOPL->fKeyDown[nChannel] )	{		pOPL->fKeyDown[nChannel]=cTRUE;		for( nSlot=nChannel*2; nSlot<nChannel*2+2; nSlot++ )		{			pOPL->vEnvTime[nSlot] = 0.0f;			pOPL->nEnvState[nSlot] = ADSR_Attack;		}	}}/*$DEADSERIOUSCLAN$********************************************************************** ROUTINE*  ym3812_KeyOff( ym3812 *pOPL, int nChannel )* FUNCTION* NOTES****************************************************************************************/void ym3812_KeyOff( ym3812 *pOPL, int nChannel ){	pOPL->fKeyDown[nChannel] = cFALSE;}/*$DEADSERIOUS$******************************************************************** ROUTINE*	int ym3812_ReadStatus( ym3812 *pOPL )* AUTHOR*	Carl-Henrik Skarstedt* FUNCTION/NOTES*	Returns the status of interrupts and timer overflow flags.**********************************************************************************/int ym3812_ReadStatus( ym3812 *pOPL ){	return pOPL->nStatus;}/*$DEADSERIOUS$******************************************************************** ROUTINE*	int ym3812_ReadReg( ym3812 *pOPL )* AUTHOR*	Carl-Henrik Skarstedt* FUNCTION/NOTES*	Reads back register contents.**********************************************************************************/int ym3812_ReadReg( ym3812 *pOPL ){	return pOPL->aRegArray[pOPL->nReg];}/*$DEADSERIOUSCLAN$********************************************************************** ROUTINE*  ym3812_SetReg( ym3812 *pOPL, unsigned char nReg )* FUNCTION* NOTES****************************************************************************************/void ym3812_SetReg( ym3812 *pOPL, unsigned char nReg ){	pOPL->nReg = nReg;}/*$DEADSERIOUSCLAN$********************************************************************** ROUTINE*  ym3812_WriteReg( ym3812 *pOPL, unsigned char nData)* FUNCTION* NOTES****************************************************************************************/void ym3812_WriteReg( ym3812 *pOPL, unsigned char nData){	int 	nReg, nCh, nSlot, nTemp;	nReg = pOPL->nReg;	pOPL->aRegArray[nReg] = nData;	switch( nReg )	{		case 0x01:		/* TEST - bit 5 means ym3812 mode on, not means ym3526 full compatibility*/			pOPL->fWave = nData & 0x20;			return;		case 0x02:		/* DATA OF TIMER 1*/			pOPL->vTimer1 = TIME_IN_USEC ((256-nData) * 80) * ( (double)ym3812_StdClock / (double)pOPL->nYM3812Clk );			return;		case 0x03:		/* DATA OF TIMER 2*/			pOPL->vTimer2 = TIME_IN_USEC ((256-nData) * 320) * ( (double)ym3812_StdClock / (double)pOPL->nYM3812Clk );			return;		case 0x04:		/* IRQ-RESET/CONTROL OF TIMER 1 AND 2*/			if( nData & ym3812_TCIRQRES )			{				nData &= ~ym3812_TCIRQRES;				pOPL->nStatus &= ~(ym3812_STIRQ|ym3812_STFLAG1|ym3812_STFLAG2);			}			pOPL->nStatus &= ~(nData & 0x60);			nTemp = pOPL->nTimerCtrl;			pOPL->nTimerCtrl = nData;			if( (nData&(~nTemp)) & ym3812_TCST1 )			{			/* Start new timer if START TIMER1 was set this write.*/				if(pOPL->SetTimer!=NULL) (*pOPL->SetTimer)( 1, pOPL->vTimer1, pOPL, cFALSE );			}			else if( ((~nData)&nTemp) & ym3812_TCST1 )			{			/* Remove existing timer if START TIMER1 was cleared this write.*/				if(pOPL->SetTimer!=NULL) (*pOPL->SetTimer)( 1, pOPL->vTimer1, pOPL, cTRUE );			}			if( (nData&(~nTemp)) & ym3812_TCST2 )			{			/* Start new timer if START TIMER2 was set this write.*/				if(pOPL->SetTimer!=NULL) (*pOPL->SetTimer)( 2, pOPL->vTimer2, pOPL, cFALSE );			}			else if( ((~nData)&nTemp) & ym3812_TCST2 )			{			/* Remove existing timer if START TIMER2 was cleared this write.*/				if(pOPL->SetTimer!=NULL) (*pOPL->SetTimer)( 2, pOPL->vTimer2, pOPL, cTRUE );			}			return;		case 0x08:		/* CSM SPEECH SYNTHESIS MODE/NOTE SELECT*/			pOPL->nCSM = nData;			return;		case 0xbd:		/* DEPTH(AM/VIB)/RHYTHM(BD, SD, TOM, TC, HH)*/			nTemp = pOPL->nDepthRhythm;			pOPL->nDepthRhythm=nData;		/* 0xbd - control of depth and rhythm*/			nData &= ~nTemp;			if( nData&0x10 ) pOPL->nDrumOffs[0] = 0;	/* Bass Drum*/			if( nData&0x08 ) pOPL->nDrumOffs[1] = 0;	/* Snare Drum*/			if( nData&0x04 ) pOPL->nDrumOffs[2] = 0;	/* Tom tom*/			if( nData&0x02 ) pOPL->nDrumOffs[3] = 0;	/* Top cymbal*/			if( nData&0x01 ) pOPL->nDrumOffs[4] = 0;	/* Hihat*/			return;	}	nCh = nReg & 0x0f;	if( nCh < 9 )	{		switch( nReg & 0xf0 )		{			case 0xa0:		/* F-NUMBER (LOW 8 BITS) a0-a8*/				pOPL->nFNumber[nCh] = (pOPL->nFNumber[nCh] & 0x300) + (nData&0xff);				return;			case 0xb0:		/* KEY-ON/BLOCK/F-NUMER(LOW 2 BITS) b0-b8*/				pOPL->nFNumber[nCh] = (pOPL->nFNumber[nCh] & 0x0ff) + ((nData&0x3)<<8);				pOPL->nOctave[nCh] = (nData&0x1c)>>2;				if( nData & 0x20 )				{					ym3812_KeyOn( pOPL, nCh );				}				else				{					ym3812_KeyOff( pOPL, nCh );				}				return;			case 0xc0:		/* FEEDBACK/CONNECTION*/				pOPL->fConnection[nCh] = nData & 0x01;				nData >>= 1;				if( !nData )	/* Calculate Feedback RATIO!*/				{					pOPL->nFeedback[nCh] = 0;				}				else				{					nData &= 7;					pOPL->nFeedback[nCh] = SINTABLE_SHIFT-SINTABLE_SIZESHIFT+7-nData+14;				}				return;		}	}	nSlot = RegSlot_Relation[nReg&0x1f];	if( nSlot != -1 )	{		switch( nReg & 0xe0 )		{			case 0x20:		/* AM-MOD/VIBRATO/EG-TYP/KEY-SCALE-RATE/MULTIPLE*/				pOPL->fAM[nSlot] = nData & 0x80;				pOPL->fVibrato[nSlot] = nData & 0x40;				pOPL->fEGTyp[nSlot] = nData & 0x20;				pOPL->fKSR[nSlot] = nData & 0x10;				pOPL->nMulti[nSlot] = nData & 0x0f;				return;			case 0x40:		/* KEY-SCALE LEVEL/TOTAL LEVEL*/				pOPL->nTotalLevel[nSlot] = nData&0x3f;				pOPL->nKSL[nSlot] = (nData&0xc0)>>6;				return;			case 0x60:		/* ATTACK RATE/DECAY RATE*/				if( nData&0xf0 ) pOPL->nAttack[nSlot] = nData >> 4;				if( nData&0x0f ) pOPL->nDecay[nSlot] = nData & 0x0f;				return;			case 0x80:		/* SYSTAIN LEVEL/RELEASE RATE*/				if( nData&0xf0 ) pOPL->nSustain[nSlot] = (nData >> 4)^0x0f;				if( nData&0x0f ) pOPL->nRelease[nSlot] = nData & 0x0f;				return;			case 0xE0:		/* WAVE SELECT*/				if( pOPL->fWave )	pOPL->nWave[nSlot] = nData & 0x03;				else				pOPL->nWave[nSlot] = 0;				return;		}	}	return; /* Writing to unused register - probably a bug*/}/*$DEADSERIOUS$********************************************* ROUTINE*	void ym3812_Update_stream( int nChipID, void *pBuffer_in, int nLength )** FUNCTION*	This routine plays streamed audio rather than a*	set size buffer. Tailored for Mame streaming sounds.************************************************************/void ym3812_Update_stream( ym3812* pOPL, void *pBuffer_in, int nLength ){	int 		nCurrVol[18],nCurrAdd[18];		/* Volume for each slot, Frequency per channel*/	int 		fPlaying[9];					/* Is channel X playing??*/	int 		nVibMul,nAMAdd; 				/* Vibrato and Amplitude modulation numbers*/	int 		nRhythm,l,samp,Value,f16Bit;	int 		nSlot,nSlot2,nOffs,nOffs2,nDiffAdd[5],nAdd[5];	int 		nSubDiv,nBufSize,nBufferLeft,nCh;	float		vMulLevel,vTime;				/* Temporary max volume level in envelope generator*/	int			nElapseTime;	signed char *pRhythm[5];	char		*pBuffer;	short		*pBuffer16;	if( nLength == 0 ) return;/* 16bit or 8bit samples?*/	f16Bit = pOPL->f16Bit;	pBuffer = pBuffer_in;	pBuffer16 = (short*)pBuffer;	nBufferLeft = nLength;	if( pOPL->nReplayFrq == 0 ) return;	nElapseTime = (nLength<<16) / pOPL->nReplayFrq;	/* Time is in 16:16 format in seconds.*//* Do the subdivision stuff*/	for( nSubDiv=0; nSubDiv<pOPL->nSubDivide; nSubDiv++ )	{		nBufSize = (nLength / pOPL->nSubDivide) + 1;		nBufferLeft -= nBufSize;		if (nBufferLeft < 0) nBufSize += nBufferLeft;/* Check how many of the Rhythm sounds are playing..*/		nRhythm = 0;		for( l=0; l<5; l++ )		{			if( pOPL->nDrumOffs[l]>=0 )			{				if( (pOPL->pDrum[l]!=NULL)&&(pOPL->nDrumOffs[l]<pOPL->nDrumSize[l]) )				{					pRhythm[nRhythm] = pOPL->pDrum[l]+pOPL->nDrumOffs[l];					pOPL->nDrumOffs[l] += (pOPL->nDrumRate[l] * nElapseTime) >> 16;					nDiffAdd[nRhythm] = (pOPL->nDrumRate[l]<<8)/(pOPL->nReplayFrq);					nAdd[nRhythm] = nDiffAdd[nRhythm]>>1;					nRhythm += 1;				}				else				{					pOPL->nDrumOffs[l] = -1;				}			}		}/* Get values from and then update Vibrato and AMDepth sinus offsets.*/		pOPL->nVibratoOffs += (int)(SINTABLE_SIZE * 6.4 * pOPL->nYM3812Clk / ym3812_StdClock / pOPL->nSubDivide * nElapseTime)>>16;	/* Vibrato @ 6.4 Hz (3.6 MHz OPL)*/		pOPL->nAMDepthOffs += (int)(SINTABLE_SIZE * 3.7 * pOPL->nYM3812Clk / ym3812_StdClock / pOPL->nSubDivide * nElapseTime)>>16;	/* AMDepth @ 3.7 Hz (3.6 MHz OPL)*/		nVibMul = (int)(ym3812_aSinTable[0][pOPL->nVibratoOffs] * 0.007f);		if( pOPL->nDepthRhythm & 0x40 ) nVibMul *= 2;		if( pOPL->nDepthRhythm & 0x80 )		{	/* 4.8 dB max Amplitude Modulation*/			nAMAdd = (int)(ym3812_aSinTable[0][pOPL->nAMDepthOffs] * 4.8 / (47.25*(SINTABLE_MAX/256)));		}		else		{	/* 1.0 dB max Amplitude Modulation*/			nAMAdd = (int)(ym3812_aSinTable[0][pOPL->nAMDepthOffs] / (47.25*(SINTABLE_MAX/256)));		}		pOPL->nVibratoOffs &= SINTABLE_SIZE-1;		pOPL->nAMDepthOffs &= SINTABLE_SIZE-1;/* Calculate frequency for each slot*/		for( l=0; l<18; l++ )		{			nCurrAdd[l] = ( ym3812_Multi[pOPL->nMulti[l]] * pOPL->nFNumber[l>>1] * pOPL->nYM3812DivClk / pOPL->nReplayFrq ) << ( (SINTABLE_SIZESHIFT-20+7)+pOPL->nOctave[l>>1] );			if( pOPL->fVibrato[l] ) nCurrAdd[l] += (nCurrAdd[l]*nVibMul)>>SINTABLE_SHIFT;		}/* Update currently playing envelopes (one per slot)*/		for( l=0; l<18 ; l++ )		{			if( (l&1)==0 ) fPlaying[l>>1] = cFALSE;			if( pOPL->nEnvState[l] == ADSR_Silent )			{				nCurrVol[l] = 0;			}			else			{				nCh = l>>1;				vMulLevel = (float)(0x3f-pOPL->nTotalLevel[l]);				/* Emulate KSL*/				switch( pOPL->nKSL[l] )				{					case 3:						vMulLevel += pOPL->nOctave[nCh]*(6.0f*64.0f/47.5f);						break;					case 2:						vMulLevel += pOPL->nOctave[nCh]*(1.5f*64.0f/47.5f);						break;					case 1:						vMulLevel += pOPL->nOctave[nCh]*(3.0f*64.0f/47.5f);						break;				}				/* Emulate amplitude modulation*/				if( pOPL->fAM[l] ) vMulLevel += nAMAdd;				vMulLevel *= 4.0f;			/* Original volume 0-64 my volume 0-256*/				if( vMulLevel>255.0f ) vMulLevel = 255.0f;				if( vMulLevel<0.0f ) vMulLevel = 0.0f;				switch( pOPL->nEnvState[l] )				{					case ADSR_Attack:						vTime = ym3812_aAttackTime[pOPL->nAttack[l]];						if( pOPL->vEnvTime[l] < vTime )						{	/* The attack is actually linear, so this is not a typo.*/							nCurrVol[l] = (int)(pOPL->aVolumes[(int)vMulLevel] * pOPL->vEnvTime[l] / vTime);							break;	/* Do not fall through to Decay*/						}						else						{							pOPL->vEnvTime[l] -= vTime;							pOPL->nEnvState[l] = ADSR_Decay;						}	/* Fall through to Decay..*/					case ADSR_Decay:						if( (!pOPL->fEGTyp[l])||(pOPL->fKeyDown[nCh]) )						{							vTime = ym3812_aDecayTime[pOPL->nDecay[l]];							if( pOPL->vEnvTime[l] < vTime )							{								nCurrVol[l] = pOPL->aVolumes[(int)( vMulLevel * ((1.0f - pOPL->vEnvTime[l]/vTime) *									(15 - pOPL->nSustain[l]) + (pOPL->nSustain[l])))>>4];								break;	/* Do not fall through to Sustain/Release*/							}							else							{								pOPL->vEnvTime[l] -= vTime;								pOPL->nEnvState[l] = ADSR_Sustain;							}						}						/* Fall through to Sustain/Release..*/					case ADSR_Sustain:						if( (pOPL->fEGTyp[l])&&(pOPL->fKeyDown[nCh]) )						{	/* Wait forever (until KeyOff)*/							nCurrVol[l] = pOPL->aVolumes[(int)(vMulLevel*pOPL->nSustain[l])>>4];							break; /* No fall through to release*/						}						else						{	/* No hold state in Sustain (Ignore KeyOff)*/							pOPL->vEnvTime[l] = 0.0f;							pOPL->nEnvState[l] = ADSR_Release;						}					case ADSR_Release:						vTime = ym3812_aDecayTime[pOPL->nRelease[l]];	/* Release timing = decay timing*/						if( pOPL->vEnvTime[l] < vTime )						{							nCurrVol[l] = pOPL->aVolumes[(int)(vMulLevel * (1.0f-pOPL->vEnvTime[l]/vTime)*pOPL->nSustain[l])>>4];							break;						}						else						{	/* Envelop has played and died*/							nCurrVol[l] = 0;							pOPL->vEnvTime[l] = 0.0f;		/* This Correct???*/							pOPL->nEnvState[l] = ADSR_Silent;							break;						}				}				/* Update envelop time for _NEXT_ frame*/				pOPL->vEnvTime[l] += (float)nElapseTime/65536.0f/(float)pOPL->nSubDivide;				if( nCurrVol[l]>0 ) fPlaying[nCh] = cTRUE;			}		}		/* Generate sample buffer*/		for( samp=nBufSize; samp>=0; --samp )		{			/* Calculate one sample from all active FM channels*/			Value = 0;			for( l=8; l>=0; --l )												/* Do all channels*/			{				if( fPlaying[l] )												/* Is this channel playing at all?*/				{					nSlot = l<<1;												/* Set Slot A*/					nSlot2 = nSlot+1;											/* Set Slot B*/					nOffs = ( pOPL->nCurrPos[nSlot] >> 8);						/* Calculate sintable offset this frame Slot A*/					nOffs2 = ( pOPL->nCurrPos[nSlot2] >> 8);					/* Calculate sintable offset this frame Slot B*/					if( pOPL->nFeedback[l]!=0 ) 								/* Fix feedback*/					{						nOffs += (pOPL->nSinValue[nSlot])>>(pOPL->nFeedback[l]);/* Add feedback offset*/					}					nOffs &= SINTABLE_SIZE-1;					pOPL->nSinValue[nSlot] = nCurrVol[nSlot]*ym3812_aSinTable[pOPL->nWave[nSlot]][nOffs];			/* Set old sample value*/					if( pOPL->fConnection[l] )									/* Connect or Parallell?*/					{						Value += nCurrVol[nSlot] * ym3812_aSinTable[pOPL->nWave[nSlot]][nOffs] +								 nCurrVol[nSlot2] * ym3812_aSinTable[pOPL->nWave[nSlot2]][nOffs2&(SINTABLE_SIZE-1)];					}					else					{						Value += nCurrVol[nSlot2]*ym3812_aSinTable[pOPL->nWave[nSlot2]][(nOffs2 +							((nCurrVol[nSlot]*ym3812_aSinTable[pOPL->nWave[nSlot]][nOffs])>>(14))) & (SINTABLE_SIZE-1)];					}					pOPL->nCurrPos[nSlot] += nCurrAdd[nSlot];					/* Increase sintable offset Slot A*/					pOPL->nCurrPos[nSlot2] += nCurrAdd[nSlot2]; 				/* Increase sintable offset Slot B*/				}			}			/* Calculate one sample from all active Rhythm sounds*/			for( l=0; l<nRhythm; l++ )			{				Value += (*pRhythm[l] * ym3812_StdVolume)<<(SINTABLE_SHIFT);				pRhythm[l] += nAdd[l]>>8;				nAdd[l] = (nAdd[l]&0xff)+nDiffAdd[l];			}			/* Put sample value into sample buffer*/			if( f16Bit )	*pBuffer16++ = ym3812_Sign16(Value >> ( SINTABLE_SHIFT+1 ));			else			*pBuffer++ = ym3812_Sign8(Value >> ( SINTABLE_SHIFT+1+8 ));		}	}}

⌨️ 快捷键说明

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