/*	
 *	framhes.h
 *
 *	P/ECE HES Driver
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2004 Naoyuki Sawa
 *
 *	* Mon Feb 23 04:28:00 JST 2004 Naoyuki Sawa
 *	- 作成開始。
 */
#include "clip.h"

/****************************************************************************
 *	HUC6280エミュレーション用外部関数
 ****************************************************************************/

void
hes_huc6280_write(HUC6280* huc6280, unsigned short addr, unsigned char data)
{
	HESDRIVER* hes = (HESDRIVER*)huc6280;

	/* MPR0=$FFと仮定。
	 *   論理アドレス   0x0000〜  0x1fff
	 * = 物理アドレス 0x1fe000〜0x1fffff
	 * = I/O area
	 */
	if(addr <= 0x1fff) {
		hes_huc6280_out(huc6280, addr, data);
		return;
	}

	hes->mem[addr] = data;
}

/****************************************************************************
 *	HESドライバ内部関数
 ****************************************************************************/

int
hes_mix(HESDRIVER* hes, short wbuff[/*HESBUFLEN*/])
{
	HUC6280* huc6280 = &hes->huc6280;
	unsigned char* mem = hes->mem;
	//
	int cnt1 = HESBUFLEN;	/* 残りサンプル数 */
	int cnt2;

	ASSERT(HES_CPU_CLOCK >= SPEAKER_FREQUENCY);
	do {
		/* 次回割り込み発生までの残りサイクル数で、何サンプルミキシングできるか? */
		if(hes->timer_start && !(mem[0x1402] & 4)) {
			if(hes->vblank_enable && !(mem[0x1402] & 2)) {
				/* TIMER,VBLANKとも有効 */
				if(hes->timer_progress <= hes->vblank_progress) {
					cnt2 = (hes->timer_progress * SPEAKER_FREQUENCY + HES_CPU_CLOCK - 1) / HES_CPU_CLOCK;
				} else {
					cnt2 = (hes->vblank_progress * SPEAKER_FREQUENCY + HES_CPU_CLOCK - 1) / HES_CPU_CLOCK;
				}
			} else {
				/* TIMERのみ有効 */
				cnt2 = (hes->timer_progress * SPEAKER_FREQUENCY + HES_CPU_CLOCK - 1) / HES_CPU_CLOCK;
			}
		} else {
			if(hes->vblank_enable && !(mem[0x1402] & 2)) {
				/* VBLANKのみ有効 */
				cnt2 = (hes->vblank_progress * SPEAKER_FREQUENCY + HES_CPU_CLOCK - 1) / HES_CPU_CLOCK;
			} else {
				/* TIMER,VBLANKとも無効 */
				cnt2 = cnt1;
			}
		}
		if(cnt2 > cnt1) cnt2 = cnt1;

		/* ミキシング。 */
		huc6280psg_mix(&hes->psg, wbuff, cnt2);
		wbuff += cnt2;
		cnt1 -= cnt2;

		/* 次回割り込み発生までの残りサイクル数を減らして、0になったら割り込み処理。 */
		if(hes->timer_start && !(mem[0x1402] & 4)) {
			hes->timer_progress -= cnt2 * HES_CPU_CLOCK / SPEAKER_FREQUENCY;
			while(hes->timer_progress <= 0) {
				hes->timer_progress += hes->timer_period;
				mem[0x1403] = 4; /* TIMER割り込み発生を示す */
				huc6280_timer(huc6280);
				huc6280_run(huc6280, HES_CPU_CLOCK/*最悪でも1秒以内には完了すると仮定*/);
			}
		}
		if(hes->vblank_enable && !(mem[0x1402] & 2)) {
			hes->vblank_progress -= cnt2 * HES_CPU_CLOCK / SPEAKER_FREQUENCY;
			while(hes->vblank_progress <= 0) {
				hes->vblank_progress += HES_VBLANK_PERIOD;
				mem[0x1403] = 2; /* IRQ1割り込み発生を示す */
				huc6280_irq1(huc6280);
				huc6280_run(huc6280, HES_CPU_CLOCK/*最悪でも1秒以内には完了すると仮定*/);
			}
		}
	} while(cnt1);

	return 0;
}

