#include <clip.h>

/***************************************************************************/
/* DO change */

//#define FILENAME "c:/home/share/quarth.gbs"
#define FILENAME "c:/home/share/PokemonB.gbs"
//#define FILENAME "c:/home/share/ZeldaOoA.gbs"	/*ダメ*/

#define BUFLEN		GBSBUFLEN
#define INIT()		gbs_init(&driver, g_data, g_size, 5/*i_song*/)
#define stream_callback	gbs_stream_callback

/***************************************************************************/
/* do NOT change */

#define NWHDR		8	/* これ以上増やすとwaveOutWriteでエラーになるみたい */
HWAVEOUT g_wout;
WAVEFORMATEX g_fmt;
WAVEHDR g_whdr[NWHDR];
short g_wbuff[NWHDR][BUFLEN];
unsigned char g_data[16 * 1024 * 1024];
int g_size;
GBSDRIVER driver;

/***************************************************************************/

void CALLBACK
waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
	static int I;
	int retval;

	if(uMsg != WOM_DONE) return;

	retval = stream_callback(g_wbuff[I], (int)&driver);
	if(retval != 0) {
		memset(g_wbuff[I], 0, sizeof(short) * GBSBUFLEN);
	}
	retval = waveOutWrite(hwo, &g_whdr[I], sizeof g_whdr[I]);
	assert(retval == 0);

	I = (I + 1) % NWHDR;
}

int
main(int argc, char* argv[])
{
	int retval;
	int i;
	const char* fname;
	FILE* fp;

	if(argc >= 1 + 1) {
		fname = argv[1];
	} else {
		fname = FILENAME;
	}

	/* init driver */
	fp = fopen(fname, "rb");
	if(!fp) {
		fprintf(stderr, "fopen(%s) failed\n", fname);
		exit(1);
	}
	g_size = fread(g_data, 1, sizeof g_data, fp);
	fclose(fp);
	retval = INIT();
	if(retval != 0) {
		fprintf(stderr, "init failed (%d)\n", retval);
		exit(1);
	}

	/* init stream */
	memset(&g_fmt, 0, sizeof g_fmt);
	g_fmt.wFormatTag = WAVE_FORMAT_PCM;
	g_fmt.nChannels = 1;
	g_fmt.nSamplesPerSec = 16000;
	g_fmt.nAvgBytesPerSec = 16000 * 2;
	g_fmt.nBlockAlign = 2;
	g_fmt.wBitsPerSample = 16;
	retval = waveOutOpen(&g_wout, WAVE_MAPPER, &g_fmt, (DWORD)waveOutProc, 0, CALLBACK_FUNCTION);
	assert(retval == 0);
	for(i = 0; i < NWHDR; i++) {
		memset(&g_whdr[i], 0, sizeof g_whdr[i]);
		g_whdr[i].lpData = (char*)g_wbuff[i];
		g_whdr[i].dwBufferLength = sizeof g_wbuff[i];
		retval = waveOutPrepareHeader(g_wout, &g_whdr[i], sizeof g_whdr[i]);
		assert(retval == 0);
	}

	/* start playing */
	for(i = 0; i < NWHDR; i++) {
		retval = waveOutWrite(g_wout, &g_whdr[i], sizeof g_whdr[i]);
		assert(retval == 0);
	}
	Sleep(INFINITE);

	return 0;
}

