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

📄 adpcm.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *   Stop playback on an ADPCM data channel
 */

void ADPCM_stop (int num)
{
	struct ADPCMVoice *voice = adpcm + num;

	/* bail if we're not playing anything */
	if (Machine->sample_rate == 0)
		return;

	/* range check the numbers */
	if (num >= adpcm_intf->num)
	{
		return;
	}

	/* update the ADPCM voice */
	ADPCM_update (voice, cpu_scalebyfcount (buffer_len));

	/* stop playback */
	voice->playing = 0;
}

/*
 *   Change volume on an ADPCM data channel
 */

void ADPCM_setvol (int num, int vol)
{
	struct ADPCMVoice *voice = adpcm + num;

	/* bail if we're not playing anything */
	if (Machine->sample_rate == 0)
		return;

	/* range check the numbers */
	if (num >= adpcm_intf->num)
	{
		return;
	}

	voice->volume = vol;

	/* update the ADPCM voice */
	ADPCM_update(voice, cpu_scalebyfcount (buffer_len));
}


/*
 *   Stop playback on an ADPCM data channel
 */

int ADPCM_playing (int num)
{
	struct ADPCMVoice *voice = adpcm + num;

	/* bail if we're not playing anything */
	if (Machine->sample_rate == 0)
		return 0;

	/* range check the numbers */
	if (num >= adpcm_intf->num)
	{
		return 0;
	}

	/* update the ADPCM voice */
	ADPCM_update (voice, cpu_scalebyfcount (buffer_len));

	/* return true if we're playing */
	return voice->playing;
}



/*
 *
 *	OKIM 6295 ADPCM chip:
 *
 *	Command bytes are sent:
 *
 *		1xxx xxxx = start of 2-byte command sequence, xxxxxxx is the sample number to trigger
 *		abcd ???? = second half of command; one of the abcd bits is set to indicate which voice
 *		            the ???? bits may be a volume or an extension of the xxxxxxx bits above
 *
 *		0abc d000 = stop playing; one or more of the abcd bits is set to indicate which voice(s)
 *
 *	Status is read:
 *
 *		???? abcd = one bit per voice, set to 0 if nothing is playing, or 1 if it is active
 *
 */


static struct OKIM6295interface *okim6295_interface;
static int okim6295_command[MAX_OKIM6295];



/*
 *    Start emulation of an OKIM6295-compatible chip
 */

int OKIM6295_sh_start (struct OKIM6295interface *intf)
{
	static struct ADPCMinterface generic_interface;
	int i;

	/* save a global pointer to our interface */
	okim6295_interface = intf;

	/* create an interface for the generic system here */
	generic_interface.num = 4 * intf->num;
	generic_interface.frequency = intf->frequency;
	generic_interface.region = intf->region;
	generic_interface.init = 0;
	for (i = 0; i < intf->num; i++)
		generic_interface.volume[i*4+0] =
		generic_interface.volume[i*4+1] =
		generic_interface.volume[i*4+2] =
		generic_interface.volume[i*4+3] = intf->volume[i];

	/* reset the parameters */
	for (i = 0; i < intf->num; i++)
		okim6295_command[i] = -1;

	/* initialize it in the standard fashion */
	return ADPCM_sh_start (&generic_interface);
}



/*
 *    Stop emulation of an OKIM6295-compatible chip
 */

void OKIM6295_sh_stop (void)
{
	/* standard stop */
	ADPCM_sh_stop ();
}



/*
 *    Update emulation of an OKIM6295-compatible chip
 */

void OKIM6295_sh_update (void)
{
	/* standard update */
	ADPCM_sh_update ();
}



/*
 *    Read the status port of an OKIM6295-compatible chip
 */

int OKIM6295_status_r (int num)
{
	int i, result, buffer_end;

	/* range check the numbers */
	if (num >= okim6295_interface->num)
	{
		return 0x0f;
	}

	/* precompute the end of buffer */
	buffer_end = cpu_scalebyfcount (buffer_len);

	/* set the bit to 1 if something is playing on a given channel */
	result = 0;
	for (i = 0; i < 4; i++)
	{
		struct ADPCMVoice *voice = adpcm + num * 4 + i;

		/* update the ADPCM voice */
		ADPCM_update (voice, buffer_end);

		/* set the bit if it's playing */
		if (voice->playing)
			result |= 1 << i;
	}

	return result;
}



/*
 *    Write to the data port of an OKIM6295-compatible chip
 */

void OKIM6295_data_w (int num, int data)
{
	/* range check the numbers */
	if (num >= okim6295_interface->num)
	{
		return;
	}

	/* if a command is pending, process the second half */
	if (okim6295_command[num] != -1)
	{
		int temp = data >> 4, i, start, stop, buffer_end;
		unsigned char *base;

		/* determine the start/stop positions */
		base = &Machine->memory_region[okim6295_interface->region][okim6295_command[num] * 8];
		start = (base[0] << 16) + (base[1] << 8) + base[2];
		stop = (base[3] << 16) + (base[4] << 8) + base[5];

		/* precompute the end of buffer */
		buffer_end = cpu_scalebyfcount (buffer_len);

		/* determine which voice(s) (voice is set by a 1 bit in the upper 4 bits of the second byte */
		for (i = 0; i < 4; i++)
		{
			if (temp & 1)
			{
				struct ADPCMVoice *voice = adpcm + num * 4 + i;

				/* update the ADPCM voice */
				ADPCM_update (voice, buffer_end);

				/* set up the voice to play this sample */
				voice->playing = 1;
				voice->base = &Machine->memory_region[okim6295_interface->region][start];
				voice->sample = 0;
				voice->count = 2 * (stop - start + 1);

				/* also reset the ADPCM parameters */
				voice->signal = -2;
				voice->step = 0;
			}
			temp >>= 1;
		}

		/* reset the command (there may be additional information in the low 4 bits (volume?) */
		okim6295_command[num] = -1;
	}

	/* if this is the start of a command, remember the sample number for next time */
	else if (data & 0x80)
	{
		okim6295_command[num] = data & 0x7f;
	}

	/* otherwise, see if this is a silence command */
	else
	{
		int temp = data >> 3, i, buffer_end;

		/* precompute the end of buffer */
		buffer_end = cpu_scalebyfcount (buffer_len);

		/* determine which voice(s) (voice is set by a 1 bit in bits 3-6 of the command */
		for (i = 0; i < 4; i++)
		{
			if (temp & 1)
			{
				struct ADPCMVoice *voice = adpcm + num * 4 + i;

				/* update the ADPCM voice */
				ADPCM_update (voice, buffer_end);

				/* stop this guy from playing */
				voice->playing = 0;
			}
			temp >>= 1;
		}
	}
}




/*
 *
 *	MSM 5205 ADPCM chip:
 *
 *	Data is streamed from a CPU by means of a clock generated on the chip.
 *
 *	A reset signal is set high or low to determine whether playback (and interrupts) are occuring
 *
 */


static struct MSM5205interface *msm5205_interface;



/*
 *    Start emulation of an MSM5205-compatible chip
 */

int MSM5205_sh_start (struct MSM5205interface *intf)
{
	static struct ADPCMinterface generic_interface;
	int i, stream_size, result;

	/* save a global pointer to our interface */
	msm5205_interface = intf;

	/* if there's an interrupt function to be called, set it up */
	if (msm5205_interface->interrupt)
		timer_pulse (TIME_IN_HZ (msm5205_interface->frequency), 0, msm5205_interface->interrupt);

	/* create an interface for the generic system here */
	generic_interface.num = intf->num;
	generic_interface.frequency = intf->frequency;
	generic_interface.region = 0;
	generic_interface.init = 0;
	for (i = 0; i < intf->num; i++)
		generic_interface.volume[i] = intf->volume[i];

	/* initialize it in the standard fashion */
	result = ADPCM_sh_start (&generic_interface);

	/* if we succeeded, create streams for everyone */
	if (!result)
	{
		/* stream size is the number of samples per second rounded to the next power of 2 */
		stream_size = 1;
		while (stream_size < msm5205_interface->frequency)
			stream_size <<= 1;

		/* allocate streams for everyone */
		for (i = 0; i < intf->num; i++)
		{
			struct ADPCMVoice *voice = adpcm + i;

			/* create the stream memory */
			voice->stream = malloc (stream_size);
			if (!voice->stream)
				return 1;

			/* set the mask value */
			voice->mask = stream_size - 1;
		}
	}

	/* return the result */
	return result;
}



/*
 *    Stop emulation of an MSM5205-compatible chip
 */

void MSM5205_sh_stop (void)
{
	/* standard stop */
	ADPCM_sh_stop ();
}



/*
 *    Update emulation of an MSM5205-compatible chip
 */

void MSM5205_sh_update (void)
{
	/* standard update */
	ADPCM_sh_update ();
}



/*
 *    Handle an update of the reset status of a chip (1 is reset ON, 0 is reset OFF)
 */

void MSM5205_reset_w (int num, int reset)
{
	struct ADPCMVoice *voice = adpcm + num;

	/* range check the numbers */
	if (num >= msm5205_interface->num)
	{
		return;
	}

	/* see if this is turning on playback */
	if (!voice->playing && !reset)
	{
		/* update the ADPCM voice */
		ADPCM_update (voice, cpu_scalebyfcount (buffer_len));

		/* mark this voice as playing */
		voice->playing = 1;
		voice->base = voice->stream;
		voice->sample = 0;
		voice->count = 0;

		/* also reset the ADPCM parameters */
		voice->signal = -2;
		voice->step = 0;
	}

	/* see if this is turning off playback */
	else if (voice->playing && reset)
	{
		/* update the ADPCM voice */
		ADPCM_update (voice, cpu_scalebyfcount (buffer_len));

		/* mark this voice as not playing */
		voice->playing = 0;
	}
}



/*
 *    Handle an update of the data to the chip
 */

void MSM5205_data_w (int num, int data)
{
	struct ADPCMVoice *voice = adpcm + num;

	/* only do this if we're playing */
	if (voice->playing)
	{
		int count = voice->count;

		/* set the upper or lower half */
		if (!(count & 1))
			voice->stream[(count / 2) & voice->mask] = data << 4;
		else
			voice->stream[(count / 2) & voice->mask] |= data & 0x0f;

		/* update the count */
		voice->count = count + 1;
	}
}

⌨️ 快捷键说明

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