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

📄 pokey.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        /* calculate next bit */
		x = ((x << a) + (x >> b) + c) & size;
	}
}

static void Rand_init(UINT8 *p, int size, int a, int b, int c)
{
UINT32 i, x = 0;
    for (i = 0; i < size; i++)
	{
	UINT8 rnd = x >> 3;
        /* store the 8 bits of the new value */
		*p++ = rnd;
		/* calculate next bit */
		x = ((x << a) + (x >> b) + c) & size;
	}
}

/*****************************************************************************/
/* Module:  Pokey_sound_init()                                               */
/* Purpose: to handle the power-up initialization functions                  */
/*          these functions should only be executed on a cold-restart        */
/*                                                                           */
/* Author:  Ron Fries                                                        */
/* Date:    January 1, 1997                                                  */
/*                                                                           */
/* Inputs:  freq17 - the value for the '1.79MHz' Pokey audio clock           */
/*          playback_freq - the playback frequency in samples per second     */
/*          num_pokeys - specifies the number of pokey chips to be emulated  */
/*                                                                           */
/* Outputs: Adjusts local globals - no return value                          */
/*                                                                           */
/*****************************************************************************/

/* ASG 980126 - added a return parameter to indicate failure */
int Pokey_sound_init (int freq17, int playback_freq, int volume, int num_pokeys, int use_clip)
{
	int chip, chan;

	/* ASG 980126 - dynamically allocate this array */
	poly17 = malloc (POLY17_SIZE+1);
	if (!poly17) return 1;

    /* HJB 980706 - random numbers are the upper 8 bits of poly 17 */
	rand17 = malloc (POLY17_SIZE+1);
	if (!rand17) return 1;

	/* Initialize the poly counters */
	Poly_init(poly4,  POLY4_SIZE,  POLY4_SHL,  POLY4_SHR,  POLY4_ADD);
	Poly_init(poly5,  POLY5_SIZE,  POLY5_SHL,  POLY5_SHR,  POLY5_ADD);
	Poly_init(poly9,  POLY9_SIZE,  POLY9_SHL,  POLY9_SHR,  POLY9_ADD);
	Poly_init(poly17, POLY17_SIZE, POLY17_SHL, POLY17_SHR, POLY17_ADD);
	Rand_init(rand17, POLY17_SIZE, POLY17_SHL, POLY17_SHR, POLY17_ADD);

	/* start all of the polynomial counters at zero */
	Poly_adjust = 0;
	P4 = 0;
	P5 = 0;
	P9 = 0;
	P17 = 0;

	/* calculate the sample 'divide by N' value based on the playback freq. */
	if (playback_freq)
		Samp_n_max = ((UINT32)freq17 << 8) / playback_freq;
    else
		Samp_n_max = 1;

	Samp_n_cnt[0] = 0;	/* initialize all bits of the sample */
	Samp_n_cnt[1] = 0;	/* 'divide by N' counter */

	for (chip = 0; chip < MAXPOKEYS; chip++) {
        AUDCTL[chip] = 0;
        Base_mult[chip] = DIV_64;
        TIMER[chip][TIMER1] = 0;
        TIMER[chip][TIMER2] = 0;
        TIMER[chip][TIMER4] = 0;
        KBCODE[chip] = 0x09;                /* Atari 800 'no key' */
        SEROUT[chip] = 0;
        SERIN[chip] = 0;
        IRQST[chip] = 0;
        IRQEN[chip] = 0;
        SKSTAT[chip] = 0;
        SKCTL[chip] = SK_RESET;             /* let the RNG run after reset */
    }

	for (chan = 0; chan < (MAXPOKEYS * 4); chan++) {
        Outbit[chan] = 0;
		Div_n_cnt[chan] = 0;
		Div_n_max[chan] = 0x7fffffffL;
		Div_n_tmr[chan] = 0;
		AUDC[chan] = 0;
		AUDF[chan] = 0;
		AUDV[chan] = 0;
    }

	for (chip = 0; chip < num_pokeys; chip++) {
		char name[40];

        sprintf(name, "Pokey #%d", chip);
        channel[chip] = stream_init(name, playback_freq, 8, chip, Pokey_process);
		stream_set_volume(channel[chip],volume);

        if (channel[chip] == -1)
            return 1;
    }

    /* set the number of pokey chips currently emulated */
	Num_pokeys = num_pokeys;
	clip = use_clip; /* LBO 101297 */

	/* ASG 980126 - return success */
	return 0;
}

/*****************************************************************************/
/* Module:  Pokey_Timer(int param)                                           */
/* Purpose: Is called when a pokey timer expires.                            */
/*                                                                           */
/* Author:  Juergen Buchmueller                                              */
/* Date:    June, 27 1998                                                    */
/*                                                                           */
/* Inputs:  param - chip * 8 + bitmask for timers (1,2,4)                    */
/*                                                                           */
/* Outputs: modifies the IRQ status and calls a user supplied function       */
/*                                                                           */
/*****************************************************************************/

void Pokey_Timer(int param)
{
int chip;
    /* split param into chip number and timer mask */
    chip = param >> CHIP_SHIFT;
	param &= TIMER_MASK;
    /* check if some of the requested timer interrupts are enabled */
	param &= IRQEN[chip];
    if (param)
    {
        /* set the enabled timer irq status bits */
        IRQST[chip] |= param;
        /* call back an application supplied function to handle the interrupt */
        if (intf->interrupt_cb[chip])
            (*intf->interrupt_cb[chip])(param);
    }
}

#if VERBOSE_SOUND
static char *audc2str(int val)
{
	static char buff[80];
	if (val & NOTPOLY5) {
		if (val & PURE) {
			strcpy(buff,"pure");
		} else if (val & POLY4) {
			strcpy(buff,"poly4");
        } else {
			strcpy(buff,"poly9/17");
		}
	} else {
		if (val & PURE) {
			strcpy(buff,"poly5");
		} else if (val & POLY4) {
			strcpy(buff,"poly4+poly5");
        } else {
			strcpy(buff,"poly9/17+poly5");
        }
    }
	return buff;
}

static char *audctl2str(int val)
{
	static char buff[80];
	if (val & POLY9) {
		strcpy(buff,"poly9");
	} else {
		strcpy(buff,"poly17");
    }
	if (val & CH1_179) {
		strcpy(buff,"+ch1hi");
    }
	if (val & CH3_179) {
		strcpy(buff,"+ch3hi");
    }
	if (val & CH1_CH2) {
		strcpy(buff,"+ch1/2");
    }
	if (val & CH3_CH4) {
		strcpy(buff,"+ch3/4");
    }
	if (val & CH1_FILTER) {
		strcpy(buff,"+ch1filter");
    }
	if (val & CH2_FILTER) {
		strcpy(buff,"+ch2filter");
    }
	if (val & CLOCK_15) {
		strcpy(buff,"+clk15");
    }
    return buff;
}
#endif

/*****************************************************************************/
/* Module:	Pokey_SerinReady(int param) 									 */
/* Purpose: Is called when another data byte is ready at the SERIN register. */
/*                                                                           */
/* Author:  Juergen Buchmueller                                              */
/* Date:	June, 28 1998													 */
/*                                                                           */
/* Inputs:	chip - chip number												 */
/*                                                                           */
/* Outputs: modifies the IRQ status and calls a user supplied function       */
/*                                                                           */
/*****************************************************************************/

void Pokey_SerinReady(int chip)
{
	if (IRQEN[chip] & IRQ_SERIN)
	{
		/* set the enabled timer irq status bits */
		IRQST[chip] |= IRQ_SERIN;
		/* call back an application supplied function to handle the interrupt */
		if (intf->interrupt_cb[chip])
			(*intf->interrupt_cb[chip])(IRQ_SERIN);
	}
}


/*****************************************************************************/
/* Module:  Update_pokey_sound()                                             */
/* Purpose: To process the latest control values stored in the AUDF, AUDC,   */
/*          and AUDCTL registers.  It pre-calculates as much information as  */
/*          possible for better performance.  This routine has not been      */
/*          optimized.                                                       */
/*                                                                           */
/* Author:  Ron Fries                                                        */
/* Date:    January 1, 1997                                                  */
/*                                                                           */
/* Inputs:  addr - the address of the parameter to be changed                */
/*          val - the new value to be placed in the specified address        */
/*          gain - specified as an 8-bit fixed point number - use 1 for no   */
/*                 amplification (output is multiplied by gain)              */
/*                                                                           */
/* Outputs: Adjusts local globals - no return value                          */
/*                                                                           */
/*****************************************************************************/

void Update_pokey_sound (int addr, int val, int chip, int gain)
{
	UINT32 new_val = 0;
	UINT8 chan;
	UINT8 chan_mask = 0;
	UINT8 chip_offs;

    /* calculate the chip_offs for the channel arrays */
    chip_offs = chip << 2;

    /* determine which address was changed */
    switch (addr & 0x0f)
    {
		case AUDF1_C:
			if (val == AUDF[CHAN1 + chip_offs])
				return;
            AUDF[CHAN1 + chip_offs] = val;
			chan_mask = 1 << CHAN1;

			if (AUDCTL[chip] & CH1_CH2)    /* if ch 1&2 tied together */
				chan_mask |= 1 << CHAN2;   /* then also change on ch2 */
			break;

		case AUDC1_C:
			if (val == AUDC[CHAN1 + chip_offs])
				return;
            AUDC[CHAN1 + chip_offs] = val;
			AUDV[CHAN1 + chip_offs] = (val & VOLUME_MASK) * gain;
			chan_mask = 1 << CHAN1;
			break;

		case AUDF2_C:
			if (val == AUDF[CHAN2 + chip_offs])
				return;
            AUDF[CHAN2 + chip_offs] = val;
			chan_mask = 1 << CHAN2;
			break;

		case AUDC2_C:
			if (val == AUDC[CHAN2 + chip_offs])
				return;
            AUDC[CHAN2 + chip_offs] = val;
			AUDV[CHAN2 + chip_offs] = (val & VOLUME_MASK) * gain;
			chan_mask = 1 << CHAN2;
            break;

		case AUDF3_C:
			if (val == AUDF[CHAN3 + chip_offs])
				return;
            AUDF[CHAN3 + chip_offs] = val;
			chan_mask = 1 << CHAN3;

			if (AUDCTL[chip] & CH3_CH4)   /* if ch 3&4 tied together */
				chan_mask |= 1 << CHAN4;  /* then also change on ch4 */
			break;

		case AUDC3_C:
			if (val == AUDC[CHAN3 + chip_offs])
				return;
            AUDC[CHAN3 + chip_offs] = val;
			AUDV[CHAN3 + chip_offs] = (val & VOLUME_MASK) * gain;
			chan_mask = 1 << CHAN3;
			break;

		case AUDF4_C:
			if (val == AUDF[CHAN4 + chip_offs])
				return;
            AUDF[CHAN4 + chip_offs] = val;
			chan_mask = 1 << CHAN4;
			break;

		case AUDC4_C:
			if (val == AUDC[CHAN4 + chip_offs])
				return;
            AUDC[CHAN4 + chip_offs] = val;
			AUDV[CHAN4 + chip_offs] = (val & VOLUME_MASK) * gain;
			chan_mask = 1 << CHAN4;
            break;

		case AUDCTL_C:
			if (val == AUDCTL[chip])
				return;
            AUDCTL[chip] = val;
			chan_mask = 15; 	  /* all channels */
			/* determine the base multiplier for the 'div by n' calculations */
			Base_mult[chip] = (AUDCTL[chip] & CLOCK_15) ? DIV_15 : DIV_64;
			break;

		case STIMER_C:
			/* first remove any existing timers */
            if (TIMER[chip][TIMER1])
				timer_remove(TIMER[chip][TIMER1]);
			if (TIMER[chip][TIMER2])
				timer_remove(TIMER[chip][TIMER2]);
			if (TIMER[chip][TIMER4])
				timer_remove(TIMER[chip][TIMER4]);
            TIMER[chip][TIMER1] = 0;
			TIMER[chip][TIMER2] = 0;
			TIMER[chip][TIMER4] = 0;

			/* reset all counters to zero (side effect) */
			Div_n_cnt[CHAN1 + chip_offs] = 0;
			Div_n_cnt[CHAN2 + chip_offs] = 0;
			Div_n_cnt[CHAN3 + chip_offs] = 0;
			Div_n_cnt[CHAN4 + chip_offs] = 0;

            /* joined chan#1 and chan#2 ? */
			if (AUDCTL[chip] & CH1_CH2)
			{
				if (Div_n_tmr[CHAN2 + chip_offs] > MIN_TIMER)
                {
                    /* set timer #1 _and_ #2 event after Div_n_tmr clocks of joined CHAN1+CHAN2 */
					TIMER[chip][TIMER2] =
						timer_pulse(1.0 * Div_n_tmr[CHAN2 + chip_offs] / intf->baseclock,
							(chip << CHIP_SHIFT) | IRQ_TIMR2 | IRQ_TIMR1, Pokey_Timer);
				}
            }
			else
			{
				if (Div_n_tmr[CHAN1 + chip_offs] > MIN_TIMER)
                {
                    /* set timer #1 event after Div_n_tmr clocks of CHAN1 */
					TIMER[chip][TIMER1] =
						timer_pulse(1.0 * Div_n_tmr[CHAN1 + chip_offs] / intf->baseclock,
							(chip << CHIP_SHIFT) | IRQ_TIMR1, Pokey_Timer);
				}
				if (Div_n_tmr[CHAN1 + chip_offs] > MIN_TIMER)
                {
                    /* set timer #2 event after Div_n_tmr clocks of CHAN2 */
					TIMER[chip][TIMER2] =
						timer_pulse(1.0 * Div_n_tmr[CHAN2 + chip_offs] / intf->baseclock,
							(chip << CHIP_SHIFT) | IRQ_TIMR2, Pokey_Timer);
				}
            }

            /* NB: POKEY has no timer #3 :) */

            if (AUDCTL[chip] & CH3_CH4)
			{
				/* not sure about this: if audc4 == 0000xxxx don't start timer 4 ? */
				if (AUDC[CHAN4 + chip_offs] & 0xf0)
				{
					if (Div_n_tmr[CHAN4 + chip_offs] > MIN_TIMER)
					{
                        /* set timer #4 event after Div_n_tmr clocks of CHAN4 */
						TIMER[chip][TIMER4] =
							timer_pulse(1.0 * Div_n_tmr[CHAN4 + chip_offs] / intf->baseclock,
								(chip << CHIP_SHIFT) | IRQ_TIMR4, Pokey_Timer);
					}

⌨️ 快捷键说明

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