/*	
 *	framvgm.c
 *
 *	P/ECE VGM Driver
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2004 Naoyuki Sawa
 *
 *	* Mon Jan 12 18:00:00 JST 2004 Naoyuki Sawa
 *	- 作成開始。
 */
#include "clip.h"

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

int
vgm_mix(VGMDRIVER* vgm, short wbuff[/*VGMBUFLEN*/])
{
	gzFile file = vgm->file;
	VGMHEADER* header = &vgm->header;
	SN76489* sn76489 = &vgm->sn76489;
	int progress = vgm->progress; /* 高速化のため取り出しておく */
	//
	int cnt1 = VGMBUFLEN;	/* 残りバッファ数(カウントダウン) */
	int cnt2 = 0;		/* 出力サンプル数(カウントアップ) */
	//
	int cmd, aa, dd, nn, nn1, nn2;

	if(vgm->stop) return -1; /* 演奏終了? */

	while(cnt1) {
		if(progress < 0) {
			cmd = gzgetc(file);
			switch(cmd) {
			case VGM_GGPSG_dd:
				/* Game Gear PSG (※未対応) */
				dd = gzgetc(file); if(dd == -1) goto L_STOP;
				break;
			case VGM_SN76489_dd:
				dd = gzgetc(file); if(dd == -1) goto L_STOP;
				sn76489_write(sn76489, dd);
				break;
			case VGM_WAIT_nn_nn:
				nn1 = gzgetc(file); if(nn1 == -1) goto L_STOP;
				nn2 = gzgetc(file); if(nn2 == -1) goto L_STOP;
				nn = nn1 | nn2 << 8;
				progress += SPEAKER_FREQUENCY * nn;
				break;
			case VGM_WAIT_735:
				progress += SPEAKER_FREQUENCY * 735;
				break;
			case VGM_WAIT_882:
				progress += SPEAKER_FREQUENCY * 882;
				break;
			case VGM_END:
				if(!header->loop_offset) goto L_STOP; /* ループ無し */
				/* ループ開始位置へ巻き戻し。(+0x1c忘れずに!!) */
				gzseek(file, header->loop_offset + 0x1c, SEEK_SET);
				break;
			default:
				if((cmd & 0xf0) == 0x50) {
					/* cmd aa dd 形式 (※未対応) */
					aa = gzgetc(file); if(aa == -1) goto L_STOP;
					dd = gzgetc(file); if(dd == -1) goto L_STOP;
					break;
				} else {
					/* Unknown Command !? */
					goto L_STOP;
				}
				break;
			}
		}
		while(progress >= 0) {
			progress -= VGMSAMPLERATE;
			cnt2++;	/* 出力サンプル数カウントアップ */
			cnt1--;	/* 残りバッファ数カウントダウン */
			if(!cnt1) break;
		}
		if(cnt2) {
			sn76489_mix(sn76489, wbuff, cnt2);
			wbuff += cnt2;
			cnt2 = 0;
		}
	}

	vgm->progress = progress; /* 書き戻し忘れずに! */
	return 0;
L_STOP:
	vgm->stop = 1; /* 演奏終了 */
	return -1;
}

