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

📄 ym2151.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	for (i=0; i<256; i++){
		/* ASG 980324: changed to compute both TimerB and TimerBTime */
		pom= ( 1024.0 * (256.0-i)  / chip->clock ) ;
		#ifdef USE_MAME_TIMERS
			chip->TimerBTime[i] = pom;
		#else
			chip->TimerB[i] = pom * chip->sampfreq * mult;  /*number of samples that timer period takes (fixed point) */
		#endif
	}

}





INLINE void envelope_KONKOFF(OscilRec * op, int v)
{
	/*OPL3 on SoundBlaster doesn't change envelope volume when KeyOn'ed */
	/*However credit sound in Paper Boy and music tune in Toobin, both  */
	/*proove that YM2151 always zeroes volume after KEYON */
if (v&8)
{
	if (!op->key){
		op->key = 1; /*KEYON'ed*/
		/*op->attack_volume = op->volume;*/      /*don't reset volume*/
		op->attack_volume = op->volume = VOLUME_OFF;   /*reset volume*/
		op->OscilFB = op->phase = 0;      /*clear feedback and phase */
		op->state = EG_ATT;               /*KEY ON = attack*/
	}
}
else
{
	if (op->key){
		op->key = 0; /*KEYOFF'ed*/
		op->state=EG_REL; /*release*/
	}
}

op+=8;

if (v&0x20)
{
	if (!op->key){
		op->key = 1; /*KEYON'ed*/
		/*op->attack_volume = op->volume;*/      /*don't reset volume*/
		op->attack_volume = op->volume = VOLUME_OFF;   /*reset volume*/
		op->OscilFB = op->phase = 0;      /*clear feedback and phase */
		op->state = EG_ATT;               /*KEY ON = attack*/
	}
}
else
{
	if (op->key){
		op->key = 0; /*KEYOFF'ed*/
		op->state=EG_REL; /*release*/
	}
}

op+=8;

if (v&0x10)
{
	if (!op->key){
		op->key = 1; /*KEYON'ed*/
		/*op->attack_volume = op->volume;*/      /*don't reset volume*/
		op->attack_volume = op->volume = VOLUME_OFF;   /*reset volume*/
		op->OscilFB = op->phase = 0;      /*clear feedback and phase */
		op->state = EG_ATT;               /*KEY ON = attack*/
	}
}
else
{
	if (op->key){
		op->key = 0; /*KEYOFF'ed*/
		op->state=EG_REL; /*release*/
	}
}

op+=8;

if (v&0x40)
{
	if (!op->key){
		op->key = 1; /*KEYON'ed*/
		/*op->attack_volume = op->volume;*/      /*don't reset volume*/
		op->attack_volume = op->volume = VOLUME_OFF;   /*reset volume*/
		op->OscilFB = op->phase = 0;      /*clear feedback and phase */
		op->state = EG_ATT;               /*KEY ON = attack*/
	}
}
else
{
	if (op->key){
		op->key = 0; /*KEYOFF'ed*/
		op->state=EG_REL; /*release*/
	}
}

}


#ifdef USE_MAME_TIMERS
static void timer_callback_a (int n)
{
    YM2151 *chip = &YMPSG[n];
	chip->TimATimer=0;
	if ( chip->IRQenable & 0x04 ){
		chip->status |= 1;
		if (chip->handler) (*chip->handler)();
	}
}
static void timer_callback_b (int n)
{
    YM2151 *chip = &YMPSG[n];
	chip->TimBTimer=0;
	if ( chip->IRQenable & 0x08 ){
		chip->status |= 2;
		if (chip->handler) (*chip->handler)();
	}
}
#endif



static void set_connect_feedback_pan( OscilRec *om1, int v )
{
	OscilRec *om2 = om1+8;
	OscilRec *oc1 = om1+16;
	OscilRec *oc2 = om1+24;

	om1->PAN = v;

	om1->FeedBack = (v>>3)&7 ? 8 - ((v>>3)&7) : 0;
	/*for values 0,1,2,3,4,5,6,7 this formula gives: 0,7,6,5,4,3,2,1*/

	/* set connect algorithm */
	switch( v & 7 ){
	case 0:
		/*  PG---M1---C1---M2---C2---OUT */
		om1->connect = &c1;
		oc1->connect = &m2;
		om2->connect = &c2;
		break;
	case 1:
		/*  PG---M1-+-M2---C2---OUT */
		/*  PG---C1-+               */
		om1->connect = &m2;
		oc1->connect = &m2;
		om2->connect = &c2;
		break;
	case 2:
		/* PG---M1------+-C2---OUT */
		/* PG---C1---M2-+          */
		om1->connect = &c2;
		oc1->connect = &m2;
		om2->connect = &c2;
		break;
	case 3:
		/* PG---M1---C1-+-C2---OUT */
		/* PG---M2------+          */
		om1->connect = &c1;
		oc1->connect = &c2;
		om2->connect = &c2;
		break;
	case 4:
		/* PG---M1---C1-+--OUT */
		/* PG---M2---C2-+      */
		om1->connect = &c1;
		oc1->connect = &chanout;
		om2->connect = &c2;
		break;
	case 5:
		/*         +-C1-+     */
		/* PG---M1-+-M2-+-OUT */
		/*         +-C2-+     */
		om1->connect = 0;	/* special mark */
		oc1->connect = &chanout;
		om2->connect = &chanout;
		break;
	case 6:
		/* PG---M1---C1-+     */
		/* PG--------M2-+-OUT */
		/* PG--------C2-+     */
		om1->connect = &c1;
		oc1->connect = &chanout;
		om2->connect = &chanout;
		break;
	case 7:
		/* PG---M1-+     */
		/* PG---C1-+-OUT */
		/* PG---M2-+     */
		/* PG---C2-+     */
		om1->connect = &chanout;
		oc1->connect = &chanout;
		om2->connect = &chanout;
		break;
	}
	oc2->connect = &chanout;
}




/* write a register on YM2151 chip number 'n' */
void YM2151WriteReg(int n, int r, int v)
{
    YM2151 *chip = &(YMPSG[n]);
    OscilRec * osc= &chip->Oscils[ r&0x1f ];

	if ( (r>=0x80) || (r>=0x28 && r<0x38) || (r>=0x40 && r<0x60) )
		chip->need_refresh = 1;

	switch(r & 0xe0){
	case 0x00:
		switch(r){
		case 0x01: /*LFO Reset(bit 1), Test Register (other bits)*/
			if (v&2) chip->LFOphase=0;
			break;
		case 0x08:
			envelope_KONKOFF(&chip->Oscils[ (v&7) ], v );
			break;
		case 0x0f: /*Noise mode select, noise freq*/
			chip->noise = v;
			break;
		case 0x10: /*Timer A  hi*/
			chip->TimAIndex = (chip->TimAIndex & 0x03 ) | (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*/
			if (v&0x20) chip->status &= 0xfd;  /*FRESET B*/
			if (v&0x10) chip->status &= 0xfe;  /*FRESET A*/
			if (v&0x02){                       /*LOAD & START B*/
				#ifdef USE_MAME_TIMERS
				/* ASG 980324: added a real timer */
					if (chip->TimBTimer) timer_remove(chip->TimBTimer);
					chip->TimBTimer = timer_set (chip->TimerBTime[ chip->TimBIndex ], n, timer_callback_b);
				#else
					chip->TimB = 1;
					chip->TimBVal = chip->TimerB[ chip->TimBIndex ];
				#endif
			}else{                             /*STOP B*/
				#ifdef USE_MAME_TIMERS
				/* ASG 980324: added a real timer if we have a handler */
					if (chip->TimBTimer) timer_remove (chip->TimBTimer);
					chip->TimBTimer = 0;
				#else
					chip->TimB = 0;
				#endif
			}
			if (v&0x01){                       /*LOAD & START A*/
				#ifdef USE_MAME_TIMERS
				/* ASG 980324: added a real timer */
					if (chip->TimATimer) timer_remove(chip->TimATimer);
					chip->TimATimer = timer_set (chip->TimerATime[ chip->TimAIndex ], n, timer_callback_a);
				#else
					chip->TimA = 1;
					chip->TimAVal = chip->TimerA[ chip->TimAIndex ];
				#endif
			}else{                             /*STOP 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 FREQ*/
			chip->LFOfrq = chip->LFOfreq[ v ];
			break;
		case 0x19: /*PMD (bit 7=1) or AMD (bit 7=0) */
			if (v&0x80)
				chip->PMD = (v & 0x7f); /*7bits + sign bit*/
			else
				chip->AMD = ((v & 0x7f)<<1) | 1; /*7bits->8bits*/
			break;
		case 0x1b: /*CT2, CT1, LFO Waveform*/
			chip->CT = v;
			chip->LFOwave = v & 3;
			if (chip->porthandler) (*chip->porthandler)(0 , (chip->CT)>>6 );
			break;
		default:
			break;
		}
		break;

	case 0x20:
		switch(r & 0x18){

		case 0x00: /*RL enable, Feedback, Connection */
			set_connect_feedback_pan(&chip->Oscils[r&7], v );
			break;

		case 0x08: /*Key Code*/
		        chip->Oscils[ r&7 ].KC = v & 0x7f;
			break;

		case 0x10: /*Key Fraction*/
			chip->Oscils[ r&7 ].KF = v >> 2 ;
			break;

		case 0x18: /*PMS,AMS*/
			chip->Oscils[ r&7 ].PMS = (v>>4) & 7;
			chip->Oscils[ r&7 ].AMS = v & 3;
			break;
		}
		break;

	case 0x40: /*DT1, MUL*/
		osc->DT1 = (v<<1) & 0xe0;
		osc->mul = MULTab [v & 0x0f];
		break;

	case 0x60: /*TL*/
		osc->TL = (v&0x7f)<<(ENV_BITS-7); /*7bit TL*/
		break;

	case 0x80: /*KS, AR*/
		osc->KS = 3-(v>>6);
		osc->AR = (v&0x1f) << 1;
		break;

	case 0xa0: /*AMS-EN, D1R*/
		osc->AMSmask = (v & 0x80) ? 0xffffffff : 0;
		osc->D1R = (v&0x1f) << 1;
		break;

	case 0xc0: /*DT2, D2R*/
		osc->DT2 = DT2Tab[(v>>6) & 3];
		osc->D2R = (v&0x1f) << 1;
		break;

	case 0xe0: /*D1L, RR*/
		osc->D1L = D1LTab[ (v>>4) & 0x0f ];
		osc->RR = ((v&0x0f)<<2) | 2;
		break;
	}

}

int 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
** 'sample_bits' is 8/16 bit selector
*/
int YM2151Init(int num, int clock, int rate,int sample_bits )
{
    int i;

    if (YMPSG) return (-1);	/* duplicate init. */

    YMNumChips = num;
    if (sample_bits==16)
	sample_16bit=1;
    else
	sample_16bit=0;

    YMPSG = (YM2151 *)malloc(sizeof(YM2151) * YMNumChips);
    if (YMPSG == NULL) return (1);

    TL_TAB = (signed int *)malloc(sizeof(signed int) * TL_TAB_LEN );
    if (TL_TAB == NULL) { free(YMPSG); YMPSG=NULL; return (1); }

    init_tables();
    for ( i = 0 ; i < YMNumChips; i++ )
    {
	YMPSG[i].clock = clock;
	YMPSG[i].sampfreq = rate ? rate : 10000;	/* avoid division by 0 in init_chip_tables() */
	YMPSG[i].handler = NULL;     /*interrupt handler */
	YMPSG[i].porthandler = NULL; /*port write handler*/
	init_chip_tables(&YMPSG[i]);
        YM2151ResetChip(i);
    }
    return(0);
}

void YM2151Shutdown()
{
    if (!YMPSG) return;

    free(YMPSG);
    YMPSG = NULL;

    if (TL_TAB){
	free(TL_TAB);
	TL_TAB=NULL;
    }
}


/*
** reset all chip registers.
*/
void YM2151ResetChip(int num)
{
    int i;
    YM2151 *chip = &YMPSG[num];

⌨️ 快捷键说明

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