/*
 * $Id: m_lib.h,v 1.1 2003/06/06 00:15:12 tong Exp $
 *	
 *
 * */


#ifndef INCLUDE_M_LIB_H
#define INCLUDE_M_LIB_H

#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif	/* _LANGUAGE_C_PLUS_PLUS */

#include "math64.h"		/* 浮動小数演算関係 */
#include "m_types.h"
#include "m_actor_h.h"
#include "game.h"
#include "m_play_h.h"
    
/************************************************************************
 *
 *	ライブラリー
 *
 ************************************************************************/

/*-----------------------------------------------------------------------
 *
 *	符号チェック
 *
 *----------------------------------------------------------------------*/
#define	signd(xx)		((xx) >= 0 ? 1 : -1) 
#define	signf(xx)		((xx) >= 0.0f ? 1.0f : -1.0f) 

/*-----------------------------------------------------------------------
 *
 *	ビット操作マクロ
 *
 * xx, yy がともに以下の型である必要があります。
 * もし、shortやchar型にしてしまうとワーニングが出ます。
 * そして返り値も同じ型になります。
 * int, unsigned int, long, unsigned long, long long, unsigned long long
 *----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------
 *
 *	ビットセット
 *
 *----------------------------------------------------------------------*/
#define	bitset(xx, yy)		((xx) |= (yy)) 

/*-----------------------------------------------------------------------
 *
 *	ビットクリアー
 *
 *----------------------------------------------------------------------*/
#define	bitclr(xx, yy)		((xx) &= ~(yy)) 

/*-----------------------------------------------------------------------
 *
 *	ビット反転
 *
 *----------------------------------------------------------------------*/
#define	bitreverse(xx, yy)	((xx) ^= (yy)) 

/*-----------------------------------------------------------------------
 *
 *	ビットチェック
 *
 *----------------------------------------------------------------------*/
#define	bitcheck(xx, yy)	((xx) & (yy)) 

/*-----------------------------------------------------------------------
 *
 *	ラジアンからＳＨＯＲＴ型角度へ
 *
 *----------------------------------------------------------------------*/
#define	rad_to_angle(xx)	((short)(int)((xx) * (65536.0f/(F_PI*2.0f))))

/*-----------------------------------------------------------------------
 *
 *	度からＳＨＯＲＴ型角度へ
 *
 *----------------------------------------------------------------------*/
#define	deg_to_angle(xx)	((short)((xx) * (65536.0f/360.0f)))

/*-----------------------------------------------------------------------
 *
 *	ＳＨＯＲＴ型角度範囲計算
 *
 *----------------------------------------------------------------------*/
#define	distance_angle(xx, yy)	((short)((xx) - (yy))) 

/*-----------------------------------------------------------------------
 *
 *	メモリーコピー
 *
 *----------------------------------------------------------------------*/
extern void	mem_copy(
    unchar	*dst_p,
    unchar	*src_p,
    size_t	size
    );

/*-----------------------------------------------------------------------
 *
 *	メモリークリアー
 *
 *----------------------------------------------------------------------*/
extern void mem_clear(
    unchar *mem,
    size_t size,
    unchar clear_data
);

/*-----------------------------------------------------------------------
 *
 *	メモリー一致チェック
 *
 *	一致：	TRUE
 *	不一致:	FALSE
 *
 *----------------------------------------------------------------------*/
extern int	mem_cmp(
    unchar	*dst_p,
    unchar	*src_p,
    size_t	size
    );

/*-----------------------------------------------------------------------
 *
 *	ＣＯＳ
 *
 *----------------------------------------------------------------------*/
extern float cos_s(
    short angle
);

/*-----------------------------------------------------------------------
 *
 *	ＳＩＮ
 *
 *----------------------------------------------------------------------*/
extern float sin_s(
    short angle
);

/*-----------------------------------------------------------------------
 *
 *	目的値へ
 *
 * [my-step , my+step]の範囲でaimにもっとも近い値を得る
 *
 *----------------------------------------------------------------------*/
extern int chase_angle(
    short * const my,
    const short aim,
    short step
);

/*-----------------------------------------------------------------------
 *
 *	目的値へ
 *
 *----------------------------------------------------------------------*/
extern int chase_s(
    short * const my,
    const short aim,
    short step
);

/*-----------------------------------------------------------------------
 *
 *	目的値へ
 *
 *----------------------------------------------------------------------*/
extern int chase_f(
    float * const my,
    const float aim,
    float step
);

/*-----------------------------------------------------------------------
 *
 *	目的値へ（可変目的値）
 *
 *----------------------------------------------------------------------*/
extern int chase_angle2(
    short * const my,
    const short aim,
    const short step
);

/*-----------------------------------------------------------------------
 *
 *	目的値へ（可変目的値）
 *
 *----------------------------------------------------------------------*/
extern int chase_s2(
    short * const my,
    const short aim,
    const short step
);

/*-----------------------------------------------------------------------
 *
 *	目的値へ
 *
 *----------------------------------------------------------------------*/
extern int chase_s3(
    short * const my,
    const short aim,
    short step
);

/*-----------------------------------------------------------------------
 *
 *	目的値へ（可変目的値）
 *
 *----------------------------------------------------------------------*/
extern int chase_f2(
    float * const my,
    const float aim,
    const float step
);

/*-----------------------------------------------------------------------
 *
 *	目的値へ
 *
 *----------------------------------------------------------------------*/
extern int chase_f3(
    float * const my,
    const float aim,
    const float add_step,
    const float sub_step
);

/*-----------------------------------------------------------------------
 *
 *	線形補間
 *
 *----------------------------------------------------------------------*/
extern void inter_float(
    float * const v,	/* セット対象 */
    const float t,	/* ターゲット */
    const int p	/* カウンタ:(== 0の時ターゲットへ) */
);

/*-----------------------------------------------------------------------
 *
 *	最大,最小チェック
 *
 *----------------------------------------------------------------------*/
#define	min_max_limit(xx, min, max)	((xx) < (min) ? (min) : ((xx) > (max) ? (max) : (xx)))

/*-----------------------------------------------------------------------
 *
 *	最大チェック
 *
 *----------------------------------------------------------------------*/
#define	max_limit(xx, max)	((xx) > (max) ? (max) : (xx))

/*-----------------------------------------------------------------------
 *
 *	最小チェック
 *
 *----------------------------------------------------------------------*/
#define	min_limit(xx, min)	((xx) < (min) ? (min) : (xx))

/*-----------------------------------------------------------------------
 *
 *	スティックコントロール情報セット
 *
 *----------------------------------------------------------------------*/
extern void stick_ratio_set(
    float	* const lenght,		/* スティック入力長さ */
    short	* const angle,		/*               方向 */
    pad_t	* const pad 
);

/*-----------------------------------------------------------------------
 *
 *	ランダム符号セット
 *
 *----------------------------------------------------------------------*/
#define	rnd_sign()	(rnd() < 0.5f ? -1 : 1)
#define	rnd_signf()	(rnd() < 0.5f ? -1.0f : 1.0f)

/*-----------------------------------------------------------------------
 *
 *	ランダムタイマーセット
 *
 *----------------------------------------------------------------------*/
#define	get_random_data(\
    min_timer,\
    random_timer\
)\
(\
    get_random_timer(min_timer, random_timer)\
)
    
extern short get_random_timer(
    const short min_timer,
    const short random_timer
);

/*-----------------------------------------------------------------------
 *
 *	パターンランダムタイマーセット
 *
 *----------------------------------------------------------------------*/
#define	get_random_pattern_data(\
    min_time,\
    random_time,\
    pattern_no\
)\
(\
    get_random_pattern_timer(time, random_time, pattern_no)\
)
    
extern short get_random_pattern_timer(
    const short min_time,
    const short random_time,
    const short pattern_no
);

/*-----------------------------------------------------------------------
 *
 *	ＸＹＺ代入
 *
 *----------------------------------------------------------------------*/
extern void xyz_t_move(
    xyz_t * const p1,
    const xyz_t * const p2
);

/*-----------------------------------------------------------------------
 *
 *	ＸＹＺ代入 s_xyz
 *
 *----------------------------------------------------------------------*/
extern void xyz_t_move_s_xyz(
    xyz_t * const p1,
    const s_xyz * const ps2
    );

/*-----------------------------------------------------------------------
 *
 *	ＸＹＺ同士の加算
 *
 *----------------------------------------------------------------------*/
extern void xyz_t_add(
    const xyz_t * const p1,
    const xyz_t * const p2,
    xyz_t * const p3
);

/*-----------------------------------------------------------------------
 *
 *	ＸＹＺ同士の減算
 *
 *----------------------------------------------------------------------*/
extern void xyz_t_sub(
    const xyz_t * const p1,
    const xyz_t * const p2,
    xyz_t * const p3
);

/*==========================================================================
 *
 * 減算処理
 * s_xyz - s_xyz = xyz_t
 *
 *=========================================================================*/
extern void xyz_t_sub_ss(
    xyz_t * const p1,
    const s_xyz * const s1,
    const s_xyz * const s2
    );

/*===========================================================================
 *
 * 乗算(float)
 * vをxyzに乗算します。
 *
 *=========================================================================*/
extern void xyz_t_mult_v(
    xyz_t * const p,
    const float v
    );

/*-----------------------------------------------------------------------
 *
 *	サーチ座標３Ｄ距離計算
 *
 *----------------------------------------------------------------------*/
extern float search_position_distance(
    const xyz_t * const my_position,
    const xyz_t * const target_position
);

/*-----------------------------------------------------------------------
 *
 *	サーチ座標３Ｄ距離計算
 *
 *----------------------------------------------------------------------*/
extern float search_position_distance2(
    const xyz_t * const my_position,
    const xyz_t * const target_position,
    xyz_t * const distance
);

/*-----------------------------------------------------------------------
 *
 *	サーチ座標ＸＺ平面距離計算
 *
 *----------------------------------------------------------------------*/
extern float search_position_distanceXZ(
    const xyz_t * const my_position,
    const xyz_t * const target_position
);

/*-----------------------------------------------------------------------
 *
 *	サーチ座標Ｙ距離計算
 *
 *----------------------------------------------------------------------*/
extern float search_position_high(
    const xyz_t * const my_position,
    const xyz_t * const target_position
);

/*-----------------------------------------------------------------------
 *
 *	サーチ座標ＸＺ平面方向計算
 *
 *----------------------------------------------------------------------*/
extern short search_position_angleY(
    const xyz_t * const my_position,
    const xyz_t * const target_position
);

/*-----------------------------------------------------------------------
 *
 *	サーチ座標ＹＺ平面方向計算
 *
 *----------------------------------------------------------------------*/
extern short search_position_angleX(
    const xyz_t * const my_position,
    const xyz_t * const target_position
);
/*======================================================================*
 *	減速接近計算     						*
 *======================================================================*/
extern float add_calc(
    float *a,	/* 現在値のポインタ 	*/
    float  b,	/* 目的値 		*/
    float  p,	/* 目的値に近づくpercent*/
    float max,	/* 変化値ＭＡＸ		*/
    float min	/* 目標達成差		*/
);
/* 目標達成差は０です */
extern void add_calc2(
    float *a,	/* 現在値のポインタ	*/
    float  b,	/* 目的値		*/
    float  p,	/* 目的値に近づくpercent*/
    float max	/* 変化値ＭＡＸ		*/
);
/* ０に向かっていきます */
extern void add_calc0(
    float *a,	/* 現在値のポインタ	*/
    float p,	/* 目的地に近づくpercent*/
    float max	/* 変化値ＭＡＸ		*/
);

/*======================================================================*
 *	減速接近計算（角度用） 						*
 *======================================================================*/
extern float add_calc_a(
    float *a,	
    float b,	
    float p,
    float max,	
    float min	
);
/*======================================================================*
 *	減速接近計算（short 角度用） 					*
 *======================================================================*/
#define add_calc_short_angle(a, b, p, max, min)\
	add_calc_short_angle2((a), (b), (float)(p), (max), (min))
/*======================================================================*
 *	減速接近計算（short 角度用 改造バージョン）			*
 *======================================================================*/
extern short add_calc_short_angle2(
    short *, 	/* 現在値のポインタ	*/
    short ,	/* 目的値		*/
    float ,	/* 目的地に近づくpercent 10なら1/10 */
    short ,	/* 変化値ＭＡＸ		*/
    short 	/* 目標達成値		*/
);

/*======================================================================*
 *	減速接近計算（short 角度用 改造バージョン＋加算のみ）		*
 *
 *	a:	実際に値を入れる変数のポインタ
 *		（ポインタの先には現在値が入っている）
 *	b:	目的値
 *	p:	ABS(現在値ー目的値)を何分割して加算値とするかの逆数
 *	max:	加算値の最大値
 *	min:	加算値の最小値
 *	返り値:	（現在値ー目的値）
 *======================================================================*/
extern short add_calc_short_angle3(short *a,
				   short b,
				   float p,
				   short max,
				   short min);

/*======================================================================*
      最適化
 *======================================================================*/
extern void adds(short *, short, short, short);

/*-----------------------------------------------------------------------
 *
 *	タイマーチェック＆減算
 *
 *----------------------------------------------------------------------*/
#define	timer_check_dec(timer)	((*(timer)) == 0 ? 0 : --(*timer))


/*-----------------------------------------------------------------------
 *
 *	変数初期化マクロ言語
 *
 *----------------------------------------------------------------------*/
typedef struct {
    unint		endcode :1;	/* 処理の終了を表す */
    unint		opcode  :4;	/* 下のenumを表現出来るだけのビットが必要 */
    unint		offset  :11;	/* 代入するポインタのオフセット値 */
    signed int		data    :16;	/* 扱うデータ */
} ValueSet_W;

enum {
    V_E,	/* ValueSet_W の endcode でエンドコードとして使用 */
    V_C		/* ValueSet_W の endcode でエンドコード以外で使用 */
};

/* m_lib.c の ValueSet_process 内 opcode_proc の順番に一致 */
enum {
    V_S_CHAR,
    V_U_CHAR,
    V_S_SHORT,
    V_U_SHORT,
    V_S_INT,
    V_U_INT,
    V_FLOAT,
    V_FLOAT_X1000,
    V_XYZ_T,
    V_XYZ_T_X1000,
    V_S_XYZ
};
    
extern void ValueSet_process(
    char	*p,
    ValueSet_W	*valueset_w
);

/*===========================================================================
 *
 * rgba_t用処理
 *
 *=========================================================================*/
/*--------------------------------------------------------------------------
 *
 * rgba_t代入
 *
 *--------------------------------------------------------------------------*/
extern void rgba_t_move(
    rgba_t * const rgba1,
    const rgba_t * const rgba2);

/*
 ******************************************************************
 *	みんなが良く使うであろう関数群
 ******************************************************************
 */

/* var の型が type_p 型で無いとエラーになるマクロ */
#define TYPE_CHECK1(type_p, var) (void)(((type_p)0) - (var))

/* ポインタ変換取得 */
/*
 * type PTR_SEG_TO_K0(type, ptr)
 * type:ptrの型（ポインタ型）
 * ptr:ポインタ(type型で無ければならない)
 * 返り値:ptrをK0に変換したアドレス
 */
extern void *ptr_seg_to_k0(void *var);
#define PTR_SEG_TO_K0_void(ptr) \
	ptr_seg_to_k0((void *)(ptr))
#define PTR_SEG_TO_K0_A(type, ptr) \
	(TYPE_CHECK1(type *, ptr), (type *)PTR_SEG_TO_K0_void(ptr))
#define PTR_SEG_TO_K0_P(type_p, ptr) \
	(TYPE_CHECK1(type_p, ptr), (type_p)PTR_SEG_TO_K0_void(ptr))
#define PTR_SEG_TO_K0(type, ptr) PTR_SEG_TO_K0_P(type, ptr)

extern void *ptr_seg_to_k0_null(void *var);
#define PTR_SEG_TO_K0_NULL_void(ptr) \
	ptr_seg_to_k0_null((void *)(ptr))
#define PTR_SEG_TO_K0_NULL(type_p, ptr) \
	(TYPE_CHECK1(type_p, ptr), (type_p)PTR_SEG_TO_K0_NULL_void(ptr))

/* ポインタ変換設定 */
#define CVT_SEG_TO_K0(type_p, ptr) \
	(void)(ptr = PTR_SEG_TO_K0_P(type_p, ptr))
#define CVT_SEG_TO_K0_NULL(type_p, ptr) \
	(void)(ptr = PTR_SEG_TO_K0_NULL(type_p, ptr))

extern u32 ptr_k0_to_phy_or_null(void * const ptr);
#define PTR_K0_TO_PHY_OR_NULL(ptr) \
	ptr_k0_to_phy_or_null((void *)(ptr))

#define PTR_K0_TO_PHY(ptr) \
	OS_K0_TO_PHYSICAL(ptr)

extern void *ptr_phy_to_k0_or_null(u32 const ptr);
#define PTR_PHY_TO_K0_OR_NULL(ptr) \
	(TYPE_CHECK1(u32 *, ptr), ptr_phy_to_k0_or_null(ptr))

#define PTR_PHY_TO_K0(type_p, ptr) \
	(TYPE_CHECK1(u32 *, &(ptr)), OS_PHYSICAL_TO_K0(ptr))

/* 何もしない関数(型その１) */
#define NOPFUNC         none_proc1
extern int none_proc1(void);
extern void none_proc2(ACTOR *, GAME *);

/* 安上がり 表示処理 */
extern void Cheap_gfx_display(GAME *game_p, Gfx *gfx);
/* 安上がり 表示処理（半透明）*/
extern void Cheap_gfx_display_xlu(GAME *game_p, Gfx *gfx);


/************************************************************************
 *
 *	ポーズ中かどうかを調べる(元々はm_play.cにあった)
 *			
 ************************************************************************/
#define Game_play_isPause(this) \
       _Game_play_isPause(this) 
extern int _Game_play_isPause( GAME_PLAY *this );

/************************************************************************
 *	パーセントチェック(絶対値タイプ)
 *		(質問は小松まで)	
 ************************************************************************/
extern float check_percent_abs(float point,	/* 位置 */
			       float min_abs,	/* 認識最小位置 */
			       float max_abs,	/* 認識最大位置 */
			       float reciprocal_range,	/* 認識範囲の逆数 */
			       int recognize_flag	/* 認識範囲内で
							   パーセント計算？ */
    );

/*-----------------------------------------------------------------------
 *
 *	変化率をもとめる（加速減速有り版）
 *
 *	end_frame	エンドフレーム
 *	start_frame	スタートフレーム
 *	now_frame	現在のフレーム
 *	accel_between	何フレームかけて加速するか(０も可能)
 *	brake_between	何フレームかけて減速するか(０も可能)
 *
 *	(end_frame-start_frame) >= (accel_between+brake_between)を
 *	守って下さい
 *----------------------------------------------------------------------*/
extern float get_percent_forAccelBrake(float now_frame,
				       float start_frame,
				       float end_frame,
				       float accel_between,
				       float brake_between);



/*-----------------------------------------------------------------------
 *
 *	２Ｄ座標変換(ワールド座標系を現在の画面座標系に直す)
 *
 *	[入力]	xyz_t     *world_position	３Ｄ座標  ＸＹＺ
 *	[出力]	xyz_t     *display_position	２Ｄ座標  ＸＹ
 *
 *----------------------------------------------------------------------*/
extern void Game_play_Projection_Trans(
    GAME_PLAY *this,
    xyz_t     *world_position,
    xyz_t     *display_position
);

/*
 ******************************************************************************
 *
 *	変化率をもとめる
 *
 *	[ in  ]	int	max	最大値
 *		int	min	最小値
 *		int	now	調べたい値
 *
 *	[ out ]	float		変化率
 *				now < min のとき変化率0.0f
 *				now >= max のとき変化率1.0f
 *
 ******************************************************************************
 */
extern float	get_percent(
    int	max,
    int	min,
    int	now
    );

#ifdef _LANGUAGE_C_PLUS_PLUS
} /* extern "C" */
#endif	/* _LANGUAGE_C_PLUS_PLUS */

#endif	/* INCLUDE_M_LIB_H */

/*** m_lib.h end ***/
