/*	
 *	clipay.h
 *
 *	P/ECE AY Driver
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2003 Naoyuki Sawa
 *
 *	* Sat Nov 22 06:00:00 JST 2003 Naoyuki Sawa
 *	- 作成開始。
 *	* Sun Nov 30 20:03:00 JST 2003 Naoyuki Sawa
 *	- Z80コア内蔵のREAD/WRITE外部関数を使うため、AYDRIVER構造体のレイアウトを変更しました。
 *	* Sat Feb 07 22:29:00 JST 2004 Naoyuki Sawa
 *	- PSG(AY-3-8910)エミュレーションを、clippsg.*からclipay3.*に変更しました。
 */
#ifndef __CLIP_AY_H__
#define __CLIP_AY_H__

/****************************************************************************
 *	AYファイル仕様
 ****************************************************************************/

/* ハーフワード値読み込み (BigEndianで、しかもHWアライメントされていません!!) */
#define AYHALF(h)	(((unsigned char*)&h)[0] << 8 | ((unsigned char*)&h)[1])

/* オフセット→ポインタ変換 (オフセット変数自身のアドレスに相対です) */
#define AYPTR(o)	((unsigned char*)&(o) + (short)AYHALF(o))

/*
 *	AYファイルヘッダ
 */
typedef struct _AYHEADER {
	char FileID[4];			/* + 0, 4: "ZYAY"固定 */
	char TypeID[4];			/* + 4, 4: "EMUL"固定 */
	unsigned char FileVersion;	/* + 8, 1: (使いません)バージョン情報 */
	unsigned char PlayerVersion;	/* + 9, 1: (使いません)バージョン情報 */
	short PSpecialPlayer;		/* +10, 2: (使いません)特殊なプレイヤー用 */
	short PAuthor;			/* +12, 2: 製作者名文字列へのオフセット */
	short PMisc;			/* +14, 2: その他文字列へのオフセット */
	unsigned char NumOfSongs;	/* +16, 1: 曲数-1(←要注意!!) */
	unsigned char FirstSong;	/* +17, 1: 最初に演奏する曲の番号 */
	short PSongsStructure;		/* +18, 2: 曲情報配列へのオフセット */
} AYHEADER;				/* =20 */

/*
 *	曲情報
 */
typedef struct _AYSONGSTRUCTURE {
	short PSongName;		/* + 0, 2: 曲名文字列へのオフセット */
	short PSongData;		/* + 2, 2: 曲データへのオフセット */
} AYSONGSTRUCTURE;			/* = 4 */

/*
 *	曲データ
 */
typedef struct _AYSONGDATA {
	unsigned char AChan;		/* + 0, 1: (使いません)AMIGA用チャネル割り当て */
	unsigned char BChan;		/* + 1, 1: (使いません)AMIGA用チャネル割り当て */
	unsigned char CChan;		/* + 2, 1: (使いません)AMIGA用チャネル割り当て */
	unsigned char Noise;		/* + 3, 1: (使いません)AMIGA用チャネル割り当て */
	unsigned short SongLength;	/* + 4, 2: (使いません)演奏時間 */
	unsigned short FadeLength;	/* + 6, 2: (使いません)フェード時間 */
	unsigned char HiReg;		/* + 8, 1: 上位レジスタ初期値 */
	unsigned char LoReg;		/* + 9, 1: 下位レジスタ初期値 */
	short PPoints;			/* +10, 2: ポイントデータへのオフセット */
	short PAddresses;		/* +12, 2: ブロックデータ配列へのオフセット */
} AYSONGDATA;				/* =14 */

/*
 *	ポイントデータ
 */
typedef struct _AYPOINTDATA {
	unsigned short Stack;		/* + 0, 2: スタックポインタ初期値  (BigEndian←要注意!!) */
	unsigned short Init;		/* + 2, 2: 初期化ルーチンアドレス  (BigEndian←要注意!!) */
	unsigned short Inter;		/* + 4, 2: 割り込みルーチンアドレス(BigEndian←要注意!!) */
} AYPOINTDATA;				/* = 6 */

/*
 *	ブロックデータ
 */
typedef struct _AYBLOCKDATA {
	unsigned short Address;		/* + 0, 2: 転送先アドレス(0:終端) */
	unsigned short Length;		/* + 2, 4: 転送サイズ */
	short Offset;			/* + 4, 2: 転送元データへのオフセット */
} AYBLOCKDATA;				/* = 6 */

/****************************************************************************
 *	AYドライバ
 ****************************************************************************/

#define AYBUFLEN		AY38910BUFLEN	/* 1[tick](=1/50[sec])当たりのサンプル数 */

#define AY_ZX_Z80_CLOCK		3546900		/* ZX-SpectrumのZ80A     動作クロック[Hz] */
#define AY_ZX_AY38910_CLOCK	1773400		/* ZX-SpectrumのAY-3-8910入力クロック[Hz] */

/*
 *	AYドライバ
 */
typedef struct _AYDRIVER {
	/*===== Z80 =====*/
	/* Z80コア内蔵のREAD/WRITE外部関数を利用するために、このバイナリレイアウト必須です。 */
	Z80 z80;			/* +    0,   64: Z80A */
	unsigned char mem[0x10000];	/* +   64,65536: Z80Aメインメモリ */
	/*===== AY-3-8910 =====*/
	AY38910 ay38910;		/* +65600,   64: AY-3-8910 */
} AYDRIVER;

/*
 *	Z80エミュレーション用外部関数
 */
unsigned char ay_z80_in(struct _Z80* z80, unsigned short addr);
void ay_z80_out(struct _Z80* z80, unsigned short addr, unsigned char data);

/*
 *	AYドライバ内部関数
 */
int ay_init(AYDRIVER* ay, const void* data, int i_song);
int ay_stream_callback(short* wbuff, int param);

/****************************************************************************
 *	アプリケーション用関数
 ****************************************************************************/

/* AYファイルの再生を開始します。
 * [in]
 *	data		AYデータの先頭アドレス。
 *	i_song		トラック番号。(0〜NumOfSongs)
 * [out]
 *	戻り値		再生開始に成功したら、 0を返します。
 *			再生開始できなければ、-1を返します。
 * [note]
 *	* この関数は内部でstream_play()を呼び出しています。
 *	* stream_play()を呼ぶと、サウンド割り込みベクタがフックされます。
 *	  プログラム終了前に必ずay_stop()を呼んで、ベクタを復元してください。
 */
int ay_play(const void* data, int i_song);

/* AYファイルの再生を停止します。
 * [note]
 *	* 再生中でなければ、この関数は何もしません。
 */
void ay_stop();

/* AYファイルの内容を、標準エラー出力にダンプします。
 * [in]
 *	data		AYデータの先頭アドレス。
 */
void ay_dump(const void* data);

#endif /*__CLIP_AY_H__*/
