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

📄 ymz280b.c

📁 十七种模拟器源代码 非常有用的作课程设计不可缺少的
💻 C
📖 第 1 页 / 共 2 页
字号:
		UINT32 new_samples, samples_left;		UINT32 final_pos;		int remaining = length;		int lvol = voice->output_left;		int rvol = voice->output_right;		/* quick out if we're not playing and we're at 0 */		if (!voice->playing && curr == 0)			continue;		/* finish off the current sample */		if (voice->output_pos > 0)		{			/* interpolate */			while (remaining > 0 && voice->output_pos < FRAC_ONE)			{				int interp_sample = (((INT32)prev * (FRAC_ONE - voice->output_pos)) + ((INT32)curr * voice->output_pos)) >> FRAC_BITS;				*ldest++ += interp_sample * lvol;				*rdest++ += interp_sample * rvol;				voice->output_pos += voice->output_step;				remaining--;			}			/* if we're over, continue; otherwise, we're done */			if (voice->output_pos >= FRAC_ONE)				voice->output_pos -= FRAC_ONE;			else				continue;		}		/* compute how many new samples we need */		final_pos = voice->output_pos + remaining * voice->output_step;		new_samples = (final_pos + FRAC_ONE - 1) >> FRAC_BITS;		if (new_samples > MAX_SAMPLE_CHUNK)			new_samples = MAX_SAMPLE_CHUNK;		samples_left = new_samples;		/* generate them into our buffer */		if (voice->playing)		{			switch (voice->mode)			{				case 1:	samples_left = generate_adpcm(voice, chip->region_base, scratch, new_samples);	break;				case 2:	samples_left = generate_pcm8(voice, chip->region_base, scratch, new_samples);	break;				case 3:	samples_left = generate_pcm16(voice, chip->region_base, scratch, new_samples);	break;				default:				case 0:	samples_left = 0; memset(scratch, 0, new_samples * sizeof(scratch[0]));			break;			}		}		/* if there are leftovers, ramp back to 0 */		if (samples_left)		{			int base = new_samples - samples_left;			int i, t = (base == 0) ? curr : scratch[base - 1];			for (i = 0; (UINT32)i < samples_left; i++)			{				if (t < 0) t = -((-t * 15) >> 4);				else if (t > 0) t = (t * 15) >> 4;				scratch[base + i] = t;			}			/* if we hit the end and IRQs are enabled, signal it */			if (base != 0)			{				voice->playing = 0;				chip->status_register |= 1 << v;				update_irq_state(chip);			}		}		/* advance forward one sample */		prev = curr;		curr = *curr_data++;		/* then sample-rate convert with linear interpolation */		while (remaining > 0)		{			/* interpolate */			while (remaining > 0 && voice->output_pos < FRAC_ONE)			{				int interp_sample = (((INT32)prev * (FRAC_ONE - voice->output_pos)) + ((INT32)curr * voice->output_pos)) >> FRAC_BITS;				*ldest++ += interp_sample * lvol;				*rdest++ += interp_sample * rvol;				voice->output_pos += voice->output_step;				remaining--;			}			/* if we're over, grab the next samples */			if (voice->output_pos >= FRAC_ONE)			{				voice->output_pos -= FRAC_ONE;				prev = curr;				curr = *curr_data++;			}		}		/* remember the last samples */		voice->last_sample = prev;		voice->curr_sample = curr;	}	/* mix and clip the result */	for (v = 0; v < length; v++)	{		int lsamp = lacc[v] / 256;		int rsamp = racc[v] / 256;		if (lsamp < -32768) lsamp = -32768;		else if (lsamp > 32767) lsamp = 32767;		if (rsamp < -32768) rsamp = -32768;		else if (rsamp > 32767) rsamp = 32767;		buffer[0][v] = lsamp;		buffer[1][v] = rsamp;	}}void Addymz280b_savedata() {  AddSaveData(SAVE_USER_0,(UINT8*)&ymz280b[0].voice,sizeof(struct YMZ280BVoice)*8);  AddSaveData(SAVE_USER_1,(UINT8*)&ymz280b[1].voice,sizeof(struct YMZ280BVoice)*8);}/**********************************************************************************************     YMZ280B_sh_start -- start emulation of the YMZ280B***********************************************************************************************/int YMZ280B_sh_start(const struct YMZ280Binterface *intf){	char stream_name[2][40];	const char *stream_name_ptrs[2];	int vol[2];	int i;	/* compute ADPCM tables */	compute_tables();	/* initialize the voices */	memset(&ymz280b, 0, sizeof(ymz280b));	for (i = 0; i < intf->num; i++)	{		/* generate the name and create the stream */		sprintf(stream_name[0], "%s #%d Ch1", "YMZ280B", i);		sprintf(stream_name[1], "%s #%d Ch2", "YMZ280B", i);		stream_name_ptrs[0] = stream_name[0];		stream_name_ptrs[1] = stream_name[1];		/* set the volumes */		vol[0] = intf->mixing_level[i] & 0xffff;		vol[1] = intf->mixing_level[i] >> 16;		/* create the stream */		ymz280b[i].stream = stream_init_multim(2, stream_name_ptrs, vol, audio_sample_rate, i, ymz280b_update);		if (ymz280b[i].stream == -1)			return 1;		/* initialize the rest of the structure */		ymz280b[i].master_clock = (double)intf->baseclock[i] / 384.0;		ymz280b[i].region_base = load_region[intf->region[i]];		ymz280b[i].irq_callback = intf->irq_callback[i];	}	/* allocate memory */	accumulator = malloc(sizeof(accumulator[0]) * 2 * MAX_SAMPLE_CHUNK);	scratch = malloc(sizeof(scratch[0]) * MAX_SAMPLE_CHUNK);	if (!accumulator || !scratch)		return 1;	Addymz280b_savedata();	/* success */	return 0;}/**********************************************************************************************     YMZ280B_sh_stop -- stop emulation of the YMZ280B***********************************************************************************************/void YMZ280B_sh_stop(void){	/* free memory */	if (accumulator)		free(accumulator);	accumulator = NULL;	if (scratch)		free(scratch);	scratch = NULL;}/**********************************************************************************************     write_to_register -- handle a write to the current register***********************************************************************************************/static void write_to_register(struct YMZ280BChip *chip, int data){	struct YMZ280BVoice *voice;	int i;	/* force an update */	stream_update(chip->stream, 0);	/* lower registers follow a pattern */	if (chip->current_register < 0x80)	{		voice = &chip->voice[(chip->current_register >> 2) & 7];		switch (chip->current_register & 0xe3)		{			case 0x00:		/* pitch low 8 bits */				voice->fnum = (voice->fnum & 0x100) | (data & 0xff);				update_step(chip, voice);				break;			case 0x01:		/* pitch upper 1 bit, loop, key on, mode */				voice->fnum = (voice->fnum & 0xff) | ((data & 0x01) << 8);				voice->looping = (data & 0x10) >> 4;				voice->mode = (data & 0x60) >> 5;				if (!voice->keyon && (data & 0x80) && chip->keyon_enable)				{					voice->playing = 1;					voice->position = voice->start;					voice->signal = voice->loop_signal = 0;					voice->step = voice->loop_step = 0x7f;					voice->loop_count = 0;				}				if (voice->keyon && !(data & 0x80) && !voice->looping){//ks start				  voice->playing = 0;				  chip->status_register &= ~(1 << ((chip->current_register >> 2) & 7));				}//ks end								voice->keyon = (data & 0x80) >> 7;				update_step(chip, voice);				break;			case 0x02:		/* total level */				voice->level = data;				update_volumes(voice);				break;			case 0x03:		/* pan */				voice->pan = data & 0x0f;				update_volumes(voice);				break;			case 0x20:		/* start address high */				voice->start = (voice->start & (0x00ffff << 1)) | (data << 17);				break;			case 0x21:		/* loop start address high */				voice->loop_start = (voice->loop_start & (0x00ffff << 1)) | (data << 17);				break;			case 0x22:		/* loop end address high */				voice->loop_end = (voice->loop_end & (0x00ffff << 1)) | (data << 17);				break;			case 0x23:		/* stop address high */				voice->stop = (voice->stop & (0x00ffff << 1)) | (data << 17);				break;			case 0x40:		/* start address middle */				voice->start = (voice->start & (0xff00ff << 1)) | (data << 9);				break;			case 0x41:		/* loop start address middle */				voice->loop_start = (voice->loop_start & (0xff00ff << 1)) | (data << 9);				break;			case 0x42:		/* loop end address middle */				voice->loop_end = (voice->loop_end & (0xff00ff << 1)) | (data << 9);				break;			case 0x43:		/* stop address middle */				voice->stop = (voice->stop & (0xff00ff << 1)) | (data << 9);				break;			case 0x60:		/* start address low */				voice->start = (voice->start & (0xffff00 << 1)) | (data << 1);				break;			case 0x61:		/* loop start address low */				voice->loop_start = (voice->loop_start & (0xffff00 << 1)) | (data << 1);				break;			case 0x62:		/* loop end address low */				voice->loop_end = (voice->loop_end & (0xffff00 << 1)) | (data << 1);				break;			case 0x63:		/* stop address low */				voice->stop = (voice->stop & (0xffff00 << 1)) | (data << 1);				break;			default:#ifdef RAINE_DEBUG			  print_debug("YMZ280B: unknown register write %02X = %02X\n", chip->current_register, data);#endif				break;		}	}	/* upper registers are special */	else	{		switch (chip->current_register)		{			case 0xfe:		/* IRQ mask */				chip->irq_mask = data;				update_irq_state(chip);				break;			case 0xff:		/* IRQ enable, test, etc */				chip->irq_enable = (data & 0x10) >> 4;				update_irq_state(chip);// ks start				if (chip->keyon_enable && !(data & 0x80))				  for (i = 0; i < 8; i++)				    chip->voice[i].playing = 0;				if (!chip->keyon_enable && (data & 0x80))				  for (i = 0; i < 8; i++)				    if (chip->voice[i].keyon && chip->voice[i].looping)				      chip->voice[i].playing = 1;				chip->keyon_enable = (data & 0x80) >> 7;// ks end								break;			default:#ifdef RAINE_DEBUG			  print_debug("YMZ280B: unknown register write %02X = %02X\n", chip->current_register, data);#endif			  				break;		}	}}/**********************************************************************************************     compute_status -- determine the status bits***********************************************************************************************/static int compute_status(struct YMZ280BChip *chip){	UINT8 result = chip->status_register;	/* force an update */	stream_update(chip->stream, 0);	/* clear the IRQ state */	chip->status_register = 0;	update_irq_state(chip);	return result;}/**********************************************************************************************     YMZ280B_status_0_r/YMZ280B_status_1_r -- handle a read from the status register***********************************************************************************************/READ_HANDLER( YMZ280B_status_0_r ){	return compute_status(&ymz280b[0]);}READ_HANDLER( YMZ280B_status_1_r ){	return compute_status(&ymz280b[1]);}/**********************************************************************************************     YMZ280B_register_0_w/YMZ280B_register_1_w -- handle a write to the register select***********************************************************************************************/WRITE_HANDLER( YMZ280B_register_0_w ){	ymz280b[0].current_register = data;}WRITE_HANDLER( YMZ280B_register_1_w ){	ymz280b[1].current_register = data;}/**********************************************************************************************     YMZ280B_data_0_w/YMZ280B_data_1_w -- handle a write to the current register***********************************************************************************************/WRITE_HANDLER( YMZ280B_data_0_w ){	write_to_register(&ymz280b[0], data);}WRITE_HANDLER( YMZ280B_data_1_w ){	write_to_register(&ymz280b[1], data);}

⌨️ 快捷键说明

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