/*	
 *	frampsid.c
 *
 *	P/ECE PSID Driver
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2003 Naoyuki Sawa
 *
 *	* Sat Dec 28 21:38:00 JST 2003 Naoyuki Sawa
 *	- 作成開始。
 */
#include "clip.h"

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

void
psid_m6502_write(M6502* m6502, unsigned short addr, unsigned char data)
{
	PSIDDRIVER* psid = (PSIDDRIVER*)m6502;
	unsigned char* mem = psid->mem;

	/* * mem[0x0001](bit2〜0)のバンク切り換えレジスタについて:
	 *   I/O領域($d000-dfff)のバンク切り換え条件がちょっと特殊です。
	 *
	 *	mem[1](2-0)	$a000-$bfff	$d000-dfff	$e000-$ffff
	 *	       000	RAM		RAM		RAM
	 *	       001	RAM		Character ROM	RAM
	 *	       010	RAM		Character ROM	Kernel ROM
	 *	       011	BASIC ROM	Character ROM	Kernel ROM
	 *	       100	RAM		I/O		RAM
	 *	       101	RAM		I/O		RAM
	 *	       110	RAM		I/O		Kernel ROM
	 *	       111	BASIC ROM	I/O		Kernel ROM
	 */
	if((addr >= 0xd000 && addr <= 0xdfff) &&	/* I/O Area access */
	   (mem[0x0001] & 4)) {				/* I/O Switched in */
		psid_m6502_out(m6502, addr, data);
		return;
	}

	/* Main Memory */
	mem[addr] = data;
}

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

int
psid_mix(PSIDDRIVER* psid, short* wbuff)
{
	M6502* m6502 = &psid->m6502;
	SID* sid = &psid->sid;
	int i_sample;
	int value;
	int step;

	for(i_sample = 0; i_sample < SIDBUFLEN; i_sample++) {
		/* 1サンプル処理し、経過クロック数を取得。 */
		value  = sid_mix1(sid, &step);		/* Real SID    : 符号付き17.5bit */
		value += psid_xsid_process(psid, step);	/* Extended SID: 符号付き17.5bit */

		/* スケーリング・クリッピングして格納。 */
		value >>= 1; /* 調整可 */
		if(value < -0x7fff) value = -0x7fff;
		if(value >  0x7fff) value =  0x7fff;
		*wbuff++ = value;

		/* IRQ発生チェック。
		 * PSIDドライバ初期化直後はcia_count=0なので、初回ループで必ずIRQ発生します。
		 */
		psid->cia_count -= step;
		//while(psid->cia_count <= 0) {
		//↓cia_timerは上下バイト別々に書き込むため、もしかしたら変更途中の値の可能\性があります。
		//  タイミング悪くcia_timer=0になっていると無限ループの恐れがあるので、while()はやめます。
		if(psid->cia_count <= 0) {
			psid->cia_count += psid->cia_timer;
			/* 演奏処理呼び出しセットアップ。 */
			psid_m6502_setup(psid, 0, psid->play_addr);
		}

		/* 経過クロック数の分、CPU処理を行います。 */
		m6502_run(m6502, m6502->cycle + step);
	}
	/* play_addr自体が割り込み処理なので、m6502_int()は不要です。 */

	return 0;
}

