/*	
 *	clipsv.h
 *
 *	P/ECE SUPERVISION Video/Sound Emulator
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2005 Naoyuki Sawa
 *
 *	* Thu Apr 14 05:55:00 JST 2005 Naoyuki Sawa
 *	- 作成開始。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_SV_H__
#define __CLIP_SV_H__

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

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

#define SUPERVISION_CLOCK (4000000) /* SUPERVISIONシステムクロック */

/****************************************************************************
 *	Video
 ****************************************************************************/

typedef struct _SVVIDEO {
	unsigned char* ram/*[0x0000..0x5fff]*/;	/* RAM/レジスタ */
} SVVIDEO;
extern SVVIDEO svvideo;

/* SUPERVISION Videoコアをリセットします。
 * [in]
 *	ram		RAM/レジスタ先頭へのポインタを指定してください。
 *			~~~~~~~~~~~~=65C02メインメモリ空間バッファ先頭
 * [note]
 *	* RAM/レジスタは、少なくとも[0x0000..0x5fff]の範囲が必要です。
 *	  SUPERVISION Videoモジュールは、以下の領域を使用します。
 *
 *		0x2000,   1	x size (※未対応)
 *		0x2001,   1	y size (※未対応)
 *		0x2002,   1	horicontal offset in pixel
 *		0x2003,   1	vertical   offset in pixel
 *		0x4000,8160	VRAM (0x4000..0x5fdfの範囲でWraparoundします)
 *				              ~~~~~~=0x4000+(192*170-1)
 *
 *				screen startaddress
 *				 = 0x4000+(([0x2003]*192+[0x2002])/4)%(192*170/4)
 *				  |
 *				  |	|      160      |  32  |
 *				  |	|<------------->|<---->|
 *				  +--->	+---------------+------+---
 *					|               |      | A
 *					|               |      | |
 *					|               |      | |
 *					|    visible    |      | | 160
 *					|               |      | |
 *					|               |      | |
 *					|               |      | V
 *					+---------------+------+---
 *					|               |      | A
 *					|               |      | | 10
 *					|               |      | V
 *					+---------------+------+---
 */
void svvideo_reset(unsigned char ram[/*0x0000..0x5fff*/]);

/* Videoレジスタへ書き込みます。
 * [in]
 *	addr		書き込むレジスタアドレス。(0x2000..0x2003)
 *	data		書き込むデータ。
 */
void svvideo_write(int addr, int data);

/* 画面を描画します。
 * [in]
 *	vbuff		160x160画面バッファ。
 *			NULLを指定した場合は、何もせずに、すぐに処理を返します。
 */
void svvideo_update(unsigned char vbuff[/*160*160*/]);

/* 160x160x4諧調グレイスケールを、128x88x4諧調グレイスケールへ縮小コピーします。
 * [in]
 *	src		160x160x4諧調グレイスケール画面バッファ。
 *	dst		128x 88x4諧調グレイスケール画面バッファ。
 * [note]
 *	* srcとdstは同じアドレスを指していても構いません。
 *	  最終的に128x88の画面イメージだけが必要ならば、160x160と128x88の
 *	  画面バッファを共通にして、メモリを節約できます。
 */
void svvideo_reduce(unsigned char dst[/*128*88*/], const unsigned char src[/*160*160*/]);

/****************************************************************************
 *	Sound
 ****************************************************************************/

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

/* アセンブラルーチンから直接参照するので、レイアウト固定です。 */
typedef struct _SVSOUNDTONE {
	int volume;	/* + 0,4: ボリューム (silent:0..15:max) */
	int period;	/* + 4,4: 音程(周期) */
	int polar;	/* + 8,4: 出力極性 0:-/1:+ */
	int count;	/* +12,4: 周期カウンタ */
} SVSOUNDTONE;		/* =16 */

/* アセンブラルーチンから直接参照するので、レイアウト固定です。 */
typedef struct _SVSOUNDNOISE {
	int on;		/* + 0,4: 0:Off/1:On */
	int volume;	/* + 4,4: ボリューム (silent:0..15:max) */
	int period;	/* + 8,4: 音程(周期) */
	int lfsr;	/* +12,4: ノイズLFSR */
	int count;	/* +16,4: 周期カウンタ */
} SVSOUNDNOISE;		/* =20 */

void svsound_tone_mix(SVSOUNDTONE* tone, short wbuff[/*SVSOUNDBUFLEN*/]);
void svsound_noise_mix(SVSOUNDNOISE* noise, short wbuff[/*SVSOUNDBUFLEN*/]);
void svsound_volume_shift(short wbuff[/*SVSOUNDBUFLEN*/]);

typedef struct _SVSOUND {
	      unsigned char* ram/*[0x0000..0x0x5fff]*/;		/* RAM/レジスタ */
	const unsigned char* rom/*[0x0000..0x7fff or 0xffff]*/;	/* ROMイメージ */
	//
	SVSOUNDTONE tone[2];
	SVSOUNDNOISE noise;
} SVSOUND;
extern SVSOUND svsound;

/* SUPERVISION Soundコアをリセットします。
 * [in]
 *	ram		RAM/レジスタ先頭へのポインタを指定してください。
 *			~~~~~~~~~~~~=65C02メインメモリ空間バッファ先頭
 *	rom		ROMイメージ先頭へのポインタを指定してください。
 */
void svsound_reset(unsigned char ram[/*0x0000..0x5fff*/],
             const unsigned char rom[/*0x0000..0x7fff or 0xffff*/]);

/* Soundレジスタへ書き込みます。
 * [in]
 *	addr		書き込むレジスタアドレス。
 *	data		書き込むデータ。
 */
void svsound_write(int addr, int data);

/* 出力サンプリングレート=SPEAKER_OUTPUT[Hz]で、SVSOUNDBUFLENサンプルのミキシングを行います。
 * [in]
 *	wbuff		出力サンプルバッファ。
 */
void svsound_mix(short wbuff[/*SVSOUNDBUFLEN*/]);

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

#endif /*__CLIP_SV_H__*/
