#if !defined(_UTIL_H_)
#define _UTIL_H_

#include <ultra64.h>

//////////////////////////////////////////////////////////////////////////////
//{### マクロ

//## セグメントの宣言
#define MSegDecl(seg) \
	extern char _##seg##SegmentStart[], _##seg##SegmentEnd[]; \
	extern char _##seg##SegmentRomStart[], _##seg##SegmentRomEnd[]; \
	extern char _##seg##SegmentTextStart[], _##seg##SegmentTextEnd[]; \
	extern char _##seg##SegmentDataStart[], _##seg##SegmentDataEnd[]; \
	extern char _##seg##SegmentBssStart[], _##seg##SegmentBssEnd[];

//## セグメントアドレスからＲＯＭアドレスに変換
#define MSeg2Rom(seg, off) \
	((u32)(off) - (u32)_##seg##SegmentStart + (u32)_##seg##SegmentRomStart)

// セグメントサイズを取得
#define MSegSize(seg) ((u32)_##seg##SegmentEnd - (u32)_##seg##SegmentStart)
#define MSegRomSize(seg) ((u32)_##seg##SegmentRomEnd - (u32)_##seg##SegmentRomStart)
#define MSegTextSize(seg) ((u32)_##seg##SegmentTextEnd - (u32)_##seg##SegmentTextStart)
#define MSegDataSize(seg) ((u32)_##seg##SegmentDataEnd - (u32)_##seg##SegmentDataStart)
#define MSegBssSize(seg) ((u32)_##seg##SegmentBssEnd - (u32)_##seg##SegmentBssStart)

//## １６バイトアライン
#define ALIGN_16(p) (((u32)(p) + 15) & ~15)

//## ６４バイトアライン
#define ALIGN_64(p) (((u32)(p) + 63) & ~63)

//## 配列の要素数を取得
#define ARRAY_SIZE(ary) (sizeof((ary)) / sizeof(*(ary)))

//## 変数の値をスワップ
#define SWAP(l, r, t) ((void)((t)=(l),(l)=(r),(r)=(t)))

//## クランプ
#define CLAMP(l, h, v) ((v) < (l) ? (l) : (v) > (h) ? (h) : (v))

//## ブール
typedef enum { false, true } bool;

//////////////////////////////////////////////////////////////////////////////

extern u32 ExpandGZip(void *src, void *dest, u32 size);

//////////////////////////////////////////////////////////////////////////////
//{### ラップ

extern int WrapI(int low, int hi, int val);
extern float WrapF(float low, float hi, float val);

//////////////////////////////////////////////////////////////////////////////

#endif // _UTIL_H_

