/*	
 *	clipspc.h
 *
 *	P/ECE SPC Driver
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2017 Naoyuki Sawa
 *
 *	* Sun Jan 06 06:00:00 JST 2004 Naoyuki Sawa
 *	- 作成開始。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 *	* Wed Aug 16 22:59:27 JST 2017 Naoyuki Sawa
 *	- 64ビット対応のために、STREAMCALLBACKのparamの型を、int⇒intptr_tに変更しました。
 */
#ifndef __CLIP_SPC_H__
#define __CLIP_SPC_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

/* 要注意!! 高速化のために『S-SMP入力クロック = S-DSP入力クロック = 2.048MHz』決め打ちで実装します。 */

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

/* * ID666/SPCHEADER構造体どちらも、リトルエンディアンです。
 *
 * * ID666/SPCHEADER構造体どちらも、フィールドアライメントなしでパックされています。
 *   そのためshortやintが使えないので、2バイト以上のフィールドはchar[]として定義しました。
 *
 * * SPCファイルに含まれているID666 Tagが text format / binary format どちらかを見分ける方法が不明です。
 *   とりあえず両方に共通の song_title,game_title,dumper,comments フィールドだけを使うのが安全そうです。
 */

/* ID666 Tag (text format) */
typedef struct _ID666TEXT {
	         char song_title[32];		/* +0002eh, 32: Song title */
	         char game_title[32];		/* +0004eh, 32: Game title */
	         char dumper[16];		/* +0006eh, 16: Name of dumper */
	         char comments[32];		/* +0007eh, 32: Comments */
	         char date[11];			/* +0009eh, 11: Date SPC was dumped (MM/DD/YYYY) */
	         char play_time[3];		/* +000a9h,  3: Number of seconds to play song before fading out */
	         char fade_time[5];		/* +000ach,  5: Length of face in milliseconds */
	         char artist[32];		/* +000b1h, 32: Artist of song */
	unsigned char channel_disable;		/* +000d1h,  1: Default channel disables (0:enable/1:disable) */
	unsigned char emulator;			/* +000d2h,  1: Emulator used to dump SPC (0:unknown/1:ZSNES/2:Snes9x) */
	unsigned char resv000d3[45];		/* +000d3h, 45: (予約) */
} ID666TEXT;					/* =00100h,210 */

/* ID666 Tag (binary format) */
typedef struct _ID666BINARY {
	         char song_title[32];		/* +0002eh, 32: Song title */
	         char game_title[32];		/* +0004eh, 32: Game title */
	         char dumper[16];		/* +0006eh, 16: Name of dumper */
	         char comments[32];		/* +0007eh, 32: Comments */
	unsigned char date[4];			/* +0009eh,  4: Date SPC was dumped (YYYYMMDD) */
	unsigned char resv000a2[7];		/* +000a2h,  7: (予約) */
	unsigned char play_time[3];		/* +000a9h,  3: Number of seconds to play song before fading out */
	unsigned char fade_time[4];		/* +000ach,  4: Length of face in milliseconds */
	         char artist[32];		/* +000b0h, 32: Artist of song */
	unsigned char channel_disable;		/* +000d0h,  1: Default channel disables (0:enable/1:disable) */
	unsigned char emulator;			/* +000d1h,  1: Emulator used to dump SPC (0:unknown/1:ZSNES/2:Snes9x) */
	unsigned char resv000d3[46];		/* +000d2h, 46: (予約) */
} ID666BINARY;					/* =00100h,210 */

/* ID666 Tag */
typedef union _ID666 {
	ID666TEXT text;				/* text format */
	ID666BINARY binary;			/* binary format */
} ID666;

typedef struct _SPCHEADER {
	         char signature[33];		/* +00000h, 33: "SNES-SPC700 Sound File Data v0.30" 固定 */
	unsigned char resv00021[2];		/* +00021h,  2: {26,26} 固定 */
	unsigned char has_id666;		/* +00023h,  1: ID666 Tag有効/無効 (26:有効/27:無効) */
	unsigned char minor_ver;		/* +00024h,  1: マイナーバージョン (30固定?) */
	/*===== SPC700 Registers =====*/
	unsigned char pc[2];			/* +00025h,  1: PC */
	unsigned char a;			/* +00027h,  1: A */
	unsigned char x;			/* +00028h,  1: X */
	unsigned char y;			/* +00029h,  1: Y */
	unsigned char psw;			/* +0002ah,  1: PSW */
	unsigned char sp;			/* +0002bh,  1: SP */
	unsigned char resv0002c[2];		/* +0002ch,  2: (予約) ※「SPC File Format v0.30」(spc_file_format.txt)には3バイトと書いてあります。誤植? */
	/*===== ID666 Tag =====*/
	        ID666 id666;			/* +0002eh,210: ID666 Tag (text or binary format) */
	/*===== Memory Image =====*/
	unsigned char main_ram[0x10000];	/* +00100h,64K: メインRAM */
	unsigned char dsp_regs[128];		/* +10100h,128: DSPレジスタ */
	unsigned char resv10180[64];		/* +10180h, 64: (予約) */
	unsigned char extra_ram[64];		/* +101c0h, 64: Extra RAM (IPL ROMの裏RAM?) */
} SPCHEADER;					/* =10200h */
						/* この後にExtended ID666 Itemsが続く場合があります。(未対応) */

/****************************************************************************
 *	SPCドライバ
 ****************************************************************************/

#define SPCBUFLEN	320		/* = 16000/50 … 1[tick](=1/50[sec])当たりのサンプル数 */

#define SPC_CLOCK	SDSP_CLOCK	/* CPU＆DSPクロック[Hz] (共通です) */

/*
 *	SPCタイマ (本当はS-SMPオンチップ)
 */
typedef struct _SPCTIMER {
	int start;		/* 0:STOP/1:START ($00f1[2:0]に相当) */
	unsigned period;	/* $00fa〜$00fcに書き込まれた値を分周倍して保持 */
	//
	int cycle;		/* 経過サイクルカウント用のCPUサイクル値保存 */
	unsigned progress;	/* 経過サイクル数 */
} SPCTIMER;

/*
 *	SPCドライバ
 */
typedef struct _SPCDRIVER {
	/*===== SNESハードウェアに関するもの =====*/
	/*{{SSMPコアのREAD外部関数を使うため、レイアウト固定*/
	SSMP ssmp;			/* SSMP Core */
	unsigned char mem[0x10000];	/* Main Memory */
	/*}}SSMPコアのREAD外部関数を使うため、レイアウト固定*/
	SDSP sdsp;			/* SDSP Core */
	SPCTIMER timer[3];		/* Timer (8K/8K/64K[Hz]) */

	/*===== SPCファイルソフトウェアに関するもの =====*/
	/* ※TODO: */
} SPCDRIVER;

/*
 *	SSMPエミュレーション用外部関数
 */
unsigned char spc_ssmp_read(SSMP* ssmp, unsigned short addr);
void spc_ssmp_write(SSMP* ssmp, unsigned short addr, unsigned char data);
unsigned char spc_ssmp_in(SSMP* ssmp, unsigned short addr);
void spc_ssmp_out(SSMP* ssmp, unsigned short addr, unsigned char data);

/*
 *	SPCドライバ内部関数
 */
int spc_init(SPCDRIVER* spc, const void* data);
int spc_mix(SPCDRIVER* spc, short wbuff[/*SPCBUFLEN*/]);
//{{2017/08/16変更:64ビット対応のために、STREAMCALLBACKのparamの型を、int⇒intptr_tに変更しました。
//int spc_stream_callback(short* wbuff, int param);
//↓2017/08/16変更:64ビット対応のために、STREAMCALLBACKのparamの型を、int⇒intptr_tに変更しました。
int spc_stream_callback(short* wbuff, intptr_t param);
//}}2017/08/16変更:64ビット対応のために、STREAMCALLBACKのparamの型を、int⇒intptr_tに変更しました。

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

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

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

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif /*__CLIP_SPC_H__*/
