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

📄 pokey.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				}
            }
			else
			{
				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);
				}
            }
			if (TIMER[chip][TIMER1])
				timer_enable(TIMER[chip][TIMER1], IRQEN[chip] & IRQ_TIMR1);
			if (TIMER[chip][TIMER2])
				timer_enable(TIMER[chip][TIMER2], IRQEN[chip] & IRQ_TIMR2);
			if (TIMER[chip][TIMER4])
				timer_enable(TIMER[chip][TIMER4], IRQEN[chip] & IRQ_TIMR4);
			break;

        case SKREST_C:
			/* reset SKSTAT */
            SKSTAT[chip] &= ~(SK_FRAME|SK_OVERRUN|SK_KBERR);
			break;

		case POTGO_C:
            break;

		case SEROUT_C:
            if (intf->serout_w[chip])
				(*intf->serout_w[chip])(addr, val);
			SKSTAT[chip] |= SK_SEROUT;
			if (IRQEN[chip] & IRQ_SEROR)
			{
				IRQST[chip] |= IRQ_SEROR;
				if (intf->interrupt_cb[chip])
					(*intf->interrupt_cb[chip])(IRQ_SEROR);
			}
			break;

        case IRQEN_C:
            /* check if serout ready is clear */
			if (!(IRQST[chip] & IRQ_SEROR))
			{
				/* write enables serout completed ? */
				if (val & IRQ_SEROC)
				{
					/* SK status serout bit was set ? */
					if (SKSTAT[chip] & SK_SEROUT)
					{
						/* remove SK status serout bit */
						SKSTAT[chip] &= ~SK_SEROUT;
						/* and set the serout complete bit */
						IRQST[chip] |= IRQ_SEROC;
						if (intf->interrupt_cb[chip])
							(*intf->interrupt_cb[chip])(IRQ_SEROC);
					}
				}
            }
			/* acknowledge one or more IRQST bits ? */
            if (IRQST[chip] & ~val)
			{
				/* reset IRQST bits that are masked now */
				IRQST[chip] &= val;
			}
			else
			{
				/* enable/disable timers now to avoid unneeded
				   breaking of the CPU cores for masked timers */
				if (TIMER[chip][TIMER1] && ((IRQEN[chip]^val) & IRQ_TIMR1))
					timer_enable(TIMER[chip][TIMER1], val & IRQ_TIMR1);
				if (TIMER[chip][TIMER2] && ((IRQEN[chip]^val) & IRQ_TIMR2))
					timer_enable(TIMER[chip][TIMER2], val & IRQ_TIMR2);
				if (TIMER[chip][TIMER4] && ((IRQEN[chip]^val) & IRQ_TIMR4))
					timer_enable(TIMER[chip][TIMER4], val & IRQ_TIMR4);
			}
			/* store irq enable */
            IRQEN[chip] = val;
            break;

		case SKCTL_C:
			if (val == SKCTL[chip])
				return;
            SKCTL[chip] = val;
			if (!(val & SK_RESET))
			{
				Update_pokey_sound(IRQEN_C,  0, chip, gain);
                Update_pokey_sound(SKREST_C, 0, chip, gain);
#if 0	/* reset does not seem to change the AUDxx registers!? */
                Update_pokey_sound(AUDCTL_C, 0, chip, gain);
                Update_pokey_sound(AUDC4_C,  0, chip, gain);
                Update_pokey_sound(AUDF4_C,  0, chip, gain);
                Update_pokey_sound(AUDC3_C,  0, chip, gain);
                Update_pokey_sound(AUDF3_C,  0, chip, gain);
                Update_pokey_sound(AUDC2_C,  0, chip, gain);
                Update_pokey_sound(AUDF2_C,  0, chip, gain);
                Update_pokey_sound(AUDC1_C,  0, chip, gain);
                Update_pokey_sound(AUDF1_C,  0, chip, gain);
#endif
            }
			break;
    }

    /************************************************************/
    /* As defined in the manual, the exact Div_n_cnt values are */
    /* different depending on the frequency and resolution:     */
    /*    64 kHz or 15 kHz - AUDF + 1                           */
    /*    1 MHz, 8-bit -     AUDF + 4                           */
    /*    1 MHz, 16-bit -    AUDF[CHAN1]+256*AUDF[CHAN2] + 7    */
    /************************************************************/

    /* only reset the channels that have changed */

    if (chan_mask & (1 << CHAN1))
    {
		/* process channel 1 frequency */
		if (AUDCTL[chip] & CH1_179)
			new_val = AUDF[CHAN1 + chip_offs] + 4;
		else
			new_val = (AUDF[CHAN1 + chip_offs] + 1) * Base_mult[chip];

        /* timer 'div by n' changed ? */
		if (intf->interrupt_cb[chip] && new_val != Div_n_tmr[CHAN1 + chip_offs])
		{
			Div_n_tmr[CHAN1 + chip_offs] = new_val;
			if (TIMER[chip][TIMER1] && new_val > MIN_TIMER)
				timer_reset(TIMER[chip][TIMER1], 1.0 * new_val / intf->baseclock);
		}

        /* sound 'div by n' changed ? */
        if (new_val != Div_n_max[CHAN1 + chip_offs])
		{
			Div_n_max[CHAN1 + chip_offs] = new_val;
			if (Div_n_cnt[CHAN1 + chip_offs] > new_val)
				Div_n_cnt[CHAN1 + chip_offs] = new_val;
		}
    }

    if (chan_mask & (1 << CHAN2))
    {
		/* process channel 2 frequency */
		if (AUDCTL[chip] & CH1_CH2)
		{
			if (AUDCTL[chip] & CH1_179)
				new_val = AUDF[CHAN2 + chip_offs] * 256 +
						  AUDF[CHAN1 + chip_offs] + 7;
			else
				new_val = (AUDF[CHAN2 + chip_offs] * 256 +
						   AUDF[CHAN1 + chip_offs] + 1) * Base_mult[chip];
		}
		else
			new_val = (AUDF[CHAN2 + chip_offs] + 1) * Base_mult[chip];

        /* timer 'div by n' changed ? */
        if (intf->interrupt_cb[chip] && new_val != Div_n_tmr[CHAN2 + chip_offs])
		{
			Div_n_tmr[CHAN2 + chip_offs] = new_val;
			if (TIMER[chip][TIMER2] && new_val > MIN_TIMER)
				timer_reset(TIMER[chip][TIMER2], 1.0 * new_val / intf->baseclock);
        }

        /* sound 'div by n' changed ? */
        if (new_val != Div_n_max[CHAN2 + chip_offs])
		{
			Div_n_max[CHAN2 + chip_offs] = new_val;
			if (Div_n_cnt[CHAN2 + chip_offs] > new_val)
				Div_n_cnt[CHAN2 + chip_offs] = new_val;
        }
    }

    if (chan_mask & (1 << CHAN3))
    {
		/* process channel 3 frequency */
		if (AUDCTL[chip] & CH3_179)
			new_val = AUDF[CHAN3 + chip_offs] + 4;
		else
			new_val= (AUDF[CHAN3 + chip_offs] + 1) * Base_mult[chip];

        /* channel 3 has no timer associated; we don't need Div_n_tmr[CHAN3] */
		if (new_val != Div_n_max[CHAN3 + chip_offs])
		{
			Div_n_max[CHAN3 + chip_offs] = new_val;
			if (Div_n_cnt[CHAN3 + chip_offs] > new_val)
				Div_n_cnt[CHAN3 + chip_offs] = new_val;
        }
    }

    if (chan_mask & (1 << CHAN4))
    {
		/* process channel 4 frequency */
		if (AUDCTL[chip] & CH3_CH4)
		{
			if (AUDCTL[chip] & CH3_179)
				new_val = AUDF[CHAN4 + chip_offs] * 256 +
						  AUDF[CHAN3 + chip_offs] + 7;
			else
				new_val = (AUDF[CHAN4 + chip_offs] * 256 +
						   AUDF[CHAN3 + chip_offs] + 1) * Base_mult[chip];
		}
		else
			new_val = (AUDF[CHAN4 + chip_offs] + 1) * Base_mult[chip];

        /* timer 'div by n' changed ? */
        if (intf->interrupt_cb[chip] && new_val != Div_n_tmr[CHAN4 + chip_offs])
		{
			Div_n_tmr[CHAN4 + chip_offs] = new_val;
			if (TIMER[chip][TIMER4] && new_val > MIN_TIMER)
				timer_reset(TIMER[chip][TIMER4], 1.0 * new_val / intf->baseclock);
        }

        /* sound 'div by n' changed ? */
        if (new_val != Div_n_max[CHAN4 + chip_offs])
		{
			Div_n_max[CHAN4 + chip_offs] = new_val;
			if (Div_n_cnt[CHAN4 + chip_offs] > new_val)
				Div_n_cnt[CHAN4 + chip_offs] = new_val;
        }
    }

	/* if channel is volume only, set current output */
    for (chan = CHAN1; chan <= CHAN4; chan++)
    {
		if (chan_mask & (1 << chan))
		{
			/* I've disabled any frequencies that exceed the sampling
			   frequency.  There isn't much point in processing frequencies
			   that the hardware can't reproduce.  I've also disabled
			   processing if the volume is zero. */

            /* if the channel is volume only */
			/* or the channel is off (volume == 0) */
			/* or the channel freq is greater than the playback freq */
			if ((AUDC[chan + chip_offs] & VOL_ONLY) ||
			   !(AUDC[chan + chip_offs] & VOLUME_MASK)
#if USE_SAMP_N_MAX
				|| (Div_n_max[chan + chip_offs] < (Samp_n_max >> 8)) */
#endif
               )
			{
                /* indicate the channel is 'on' */
				Outbit[chan + chip_offs] = 1;
				/* can only ignore channel if filtering off */
				if ((chan == CHAN3 && !(AUDCTL[chip] & CH1_FILTER)) ||
					(chan == CHAN4 && !(AUDCTL[chip] & CH2_FILTER)) ||
					(chan == CHAN1) ||
					(chan == CHAN2)
#if USE_SAMP_N_MAX
					|| (Div_n_max[chan + chip_offs] < (Samp_n_max >> 8))
#endif
                   )
				{
					/* and set channel freq to max to reduce processing */
					Div_n_max[chan + chip_offs] = 0x7fffffffL;
					Div_n_cnt[chan + chip_offs] = 0x7fffffffL;
				}
            }
        }
    }
}


/*****************************************************************************/
/* Module:  Pokey_process()                                                  */
/* Purpose: To fill the output buffer with the sound output based on the     */
/*			pokey chip parameters.											 */
/*                                                                           */
/* Author:  Ron Fries                                                        */
/* Date:    January 1, 1997                                                  */
/*                                                                           */
/* Inputs:	chip - chip number to process									 */
/*			*buffer - pointer to the buffer where the audio output will 	 */
/*                    be placed                                              */
/*          n - size of the playback buffer                                  */
/*                                                                           */
/* Outputs: the buffer will be filled with n bytes of audio - no return val  */
/*                                                                           */
/*****************************************************************************/

void Pokey_process (int chip, void *buffer, int n)
{
	REGISTER UINT32 event_min;
	REGISTER UINT8 next_event;
	REGISTER UINT16 chip_offs;
	REGISTER UINT8 *buf_ptr;
#ifdef CLIP 					/* if clipping is selected */
    REGISTER INT16 cur_val;     /* then we have to count as 16-bit */
#else
    REGISTER INT8 cur_val;      /* otherwise we'll simplify as 8-bit */
#endif

/* GSL 980313 B'zarre defines to handle optimised non-dword-aligned load/stores on ARM etc processors */
/* HDG 980501 Removed and replaced by cleaner solution without ifdef's,
   as in use with unix port for several versions now */

	if (n < 0 || chip >= Num_pokeys) {
		return;
	}

	chip_offs = chip << 2;

    /* The current output is pre-determined and then adjusted based on each */
    /* output change for increased performance (less over-all math). */
    /* add the output values of all 4 channels */

	cur_val = (Outbit[chip_offs+CHAN1]?AUDV[chip_offs+CHAN1]:-AUDV[chip_offs+CHAN1]) / 2 +
			  (Outbit[chip_offs+CHAN2]?AUDV[chip_offs+CHAN2]:-AUDV[chip_offs+CHAN2]) / 2 +
			  (Outbit[chip_offs+CHAN3]?AUDV[chip_offs+CHAN3]:-AUDV[chip_offs+CHAN3]) / 2 +
			  (Outbit[chip_offs+CHAN4]?AUDV[chip_offs+CHAN4]:-AUDV[chip_offs+CHAN4]) / 2;

	buf_ptr = buffer;

    /* loop until the buffer is filled */
	while (n > 0) {
		/* Normally the routine would simply decrement the 'div by N' */
		/* counters and react when they reach zero.  Since we normally */
		/* won't be processing except once every 80 or so counts, */
		/* I've optimized by finding the smallest count and then */
		/* 'accelerated' time by adjusting all pointers by that amount. */

		/* find next smallest event (either sample or chan 1-4) */
        next_event = SAMPLE;
        event_min = Samp_n_cnt[0];

		if (Div_n_cnt[chip_offs+CHAN1] <= event_min) {
			event_min = Div_n_cnt[chip_offs+CHAN1];
			next_event = chip_offs + CHAN1;
		}
		if (Div_n_cnt[chip_offs+CHAN2] <= event_min) {
			event_min = Div_n_cnt[chip_offs+CHAN2];
			next_event = chip_offs + CHAN2;
        }
		if (Div_n_cnt[chip_offs+CHAN3] <= event_min) {
			event_min = Div_n_cnt[chip_offs+CHAN3];
			next_event = chip_offs + CHAN3;
        }
		if (Div_n_cnt[chip_offs+CHAN4] <= event_min) {
			event_min = Div_n_cnt[chip_offs+CHAN4];
			next_event = chip_offs + CHAN4;
        }

        /* decrement all counters by the smallest count found */

		Div_n_cnt[chip_offs+CHAN1] -= event_min;
		Div_n_cnt[chip_offs+CHAN2] -= event_min;
		Div_n_cnt[chip_offs+CHAN3] -= event_min;
		Div_n_cnt[chip_offs+CHAN4] -= event_min;

        Samp_n_cnt[0] -= event_min;

		/* since the polynomials require a mod (%) function which is
		   division, I don't adjust the polynomials on the SAMPLE events,
		   only the CHAN events.  I have to keep track of the change,
		   though. */
		Poly_adjust += event_min;

		/* if the next event is a channel change */
		if (next_event != SAMPLE)
		{
			REGISTER UINT8 audc;
			REGISTER UINT8 audctl;
			REGISTER UINT8 toggle;

            /* shift the polynomial counters */
			P4	= (P4  + Poly_adjust) % POLY4_SIZE;
			P5	= (P5  + Poly_adjust) % POLY5_SIZE;
			P9	= (P9  + Poly_adjust) % POLY9_SIZE;
			P17 = (P17 + Poly_adjust) % POLY17_SIZE;

			/* reset the polynomial adjust counter to zero */
			Poly_adjust = 0;

			/* adjust channel counter */
			Div_n_cnt[next_event] += Div_n_max[next_event];

			/* get the current AUDC into a register (for optimization) */
			audc = AUDC[next_event];

			/* get the current chips AUDCTL */
			audctl = AUDCTL[next_event>>2];

			/* assume no changes to the output */
			toggle = 0;

			/* From here, a good understanding of the hardware is required */
			/* to understand what is happening.  I won't be able to provide */
			/* much description to explain it here. */

            /* if the output is pure or the output is poly5 */
			/* and the poly5 bit is set */
			if ((audc & NOTPOLY5) || poly5[P5]) {
				/* if the PURE bit is set */
				if (audc & PURE) {
					/* simply toggle the output */
					toggle = 1;
				} else if (audc & POLY4) {
					/* otherwise if POLY4 is selected */

⌨️ 快捷键说明

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