/*
 * $Id: u64patch.h,v 1.1 2003/02/07 18:15:44 wheeler Exp $
 *
 * ウルトラ６４のＳＧＩのインクルードファイルの不具合に対する修正・追加のパッチ
 * <ultra64.h> のヘッダの不具合（らしきもの）を修正します
 * この内容を、ＳＧＩに報告し、修正してもらうべきでしょう。
 *
 * #include <ultra64.h>
 * #include <u64patch.h>
 * の順に組み込んでください
 *
 * $Log: u64patch.h,v $
 * Revision 1.1  2003/02/07 18:15:44  wheeler
 * Fox's version of libultra and friends.
 *
 * Revision 1.2  1996/10/20  09:19:12  hayakawa
 * _LANGUAGE_C_PLUS_PLUS を __cplusplus に変更
 *
 * Revision 1.1  1996/10/20  06:49:42  hayakawa
 * Initial revision
 *
 * Revision 1.7  1996/10/01  05:32:43  hayakawa
 * OS_MSEC_TO_CYCLES,OS_SEC_TO_CYCLESの追加
 * Ｑマイクロコードに対応
 *
 */

#ifndef __U64PATCH_H_
#define __U64PATCH_H_

#ifdef __cplusplus
extern "C" {
#endif

/*
 * PRimage.h
 */

#ifdef	__GL_IMAGE_H__

/* 40 */
#undef  IBUFSIZE
#define	IBUFSIZE(pixels)	(((pixels)+((pixels)>>6))<<2)

#endif /* __GL_IMAGE_H__ */

/*
 * region.h
 */

#ifdef	_REGION_H_

/* 76 */
#undef  ALIGN
#define	ALIGN(s, align)	(((u32)(s) + ((align)-1)) & ~((align)-1))

#endif /* _REGION_H_ */

/*
 * os.h
 */
#ifdef _OS_H_

/* 691 C++ でワーニングが出る */
#undef OS_K0_TO_PHYSICAL
#define	OS_K0_TO_PHYSICAL(x)	(u32)((u32)(x)&0x1FFFFFFF)
#undef OS_K1_TO_PHYSICAL
#define	OS_K1_TO_PHYSICAL(x)	(u32)((u32)(x)&0x1FFFFFFF)

/* 738 */
extern void		osViRepeatLine(u8); /* osRepeatLineは間違い */

/* 単位変換の追加 */
#define OS_MSEC_TO_CYCLES(n)	(((u64)(n)*(osClockRate))/1000LL)
#define OS_SEC_TO_CYCLES(n)	((u64)(n)*(osClockRate))

#endif

/*
 * gu.h
 */ 
#ifdef _GU_H_

#undef  FTOFIX32			/* キャストを追加 */
#define	FTOFIX32(x)	(long)((x) * (float)0x00010000)

#undef 	FIX32TOF			/* 割り算を掛け算に置き換えて高速化 */
#define	FIX32TOF(x)	((float)(x) * (1.0f / (float)0x00010000))

#endif

/*
 * gbi.h
 */
#ifdef _GBI_H_

#undef G_CC_MODULATERGBDECALA_PRIM /* G_CC_MODULATEIA_PRIMではおかしいと思う */
#define	G_CC_MODULATERGBDECALA_PRIM	G_CC_MODULATEIDECALA_PRIM

/* 括弧が抜けている */

/* 1728 */
#undef  gSPSegment
#define gSPSegment(pkt, segment, base)					\
	gMoveWd(pkt, G_MW_SEGMENT, ((segment)*4), base)
#undef  gsSPSegment
#define gsSPSegment(segment, base)					\
	gsMoveWd(    G_MW_SEGMENT, ((segment)*4), base)

/* 1803 */
#undef  gSPModifyVertex
#define	gSPModifyVertex(pkt, vtx, where, val)				\
	gMoveWd(pkt, G_MW_POINTS, ((vtx)*40)+(where), val)

#undef  gsSPModifyVertex
#define	gsSPModifyVertex(vtx, where, val)				\
	gsMoveWd(G_MW_POINTS, ((vtx)*40)+(where), val)
    
/* 2010 */
#undef  gSPLookAt
#define gSPLookAt(pkt, la)						\
{									\
	gSPLookAtX(pkt,la)						\
	gSPLookAtY(pkt,((char *)(la))+16)					\
}
#undef  gsSPLookAt
#define gsSPLookAt(la)							\
	gsSPLookAtX(la),						\
	gsSPLookAtY(((char *)(la))+16)

/* 2054 */
#undef  gSPFogPosition
#define gSPFogPosition(pkt, min, max)				\
	gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, 			\
		(_SHIFTL((128000/((max)-(min))),16,16) |		\
		_SHIFTL(((500-(min))*256/((max)-(min))),0,16)))

#undef  gsSPFogPosition
#define gsSPFogPosition(min, max)				\
	gsMoveWd(G_MW_FOG, G_MWO_FOG, 				\
		(_SHIFTL((128000/((max)-(min))),16,16) |		\
		_SHIFTL(((500-(min))*256/((max)-(min))),0,16)))


#if 0
/* s, t, dsdx, dtdyが負数の時にバグるのを修正 3498-*/
#undef  gsDPTextureRectangle
#undef  gsDPTextureRectangleFlip
#undef  gsSPTextureRectangle
#undef  gsSPTextureRectangleFlip
#undef  gSPTextureRectangleFlip

#undef  gSPTextureRectangle
#define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\
{									\
    Gfx *_g = (Gfx *)(pkt);						\
									\
    _g->words.w0 = _SHIFT(G_TEXRECT, 24) | _SHIFT(xh, 12) | _SHIFT(yh, 0);    \
    _g->words.w1 = _SHIFT(tile, 24) | _SHIFT(xl, 12) | _SHIFT(yl, 0);         \
    gImmp1(pkt, G_RDPHALF_1, (_SHIFT((u16)(s), 16) | _SHIFT((u16)(t), 0)));   \
    gImmp1(pkt, G_RDPHALF_2, (_SHIFT((u16)(dsdx), 16) | _SHIFT((u16)(dtdy), 0))); \
}
#endif

/* 3692 */
#undef  gSPScisTextureRectangle
#define gSPScisTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)  \
{									\
    Gfx *_g = (Gfx *)(pkt);						\
									\
    _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | 			\
		    _SHIFTL(MAX(xh,0), 12, 12) | _SHIFTL(MAX(yh,0), 0, 12)); \
    _g->words.w1 = (_SHIFTL(tile, 24, 3) |				     \
		    _SHIFTL(MAX(xl,0), 12, 12) | _SHIFTL(MAX(yl,0), 0, 12)); \
    gImmp1(pkt, G_RDPHALF_1, 						     \
		(_SHIFTL(((s) - (MIN((((xl)*(dsdx))>>7),0))), 16, 16) |	     \
		_SHIFTL(((t) - (MIN((((yl)*(dtdy))>>7),0))), 0, 16)));	     \
    gImmp1(pkt, G_RDPHALF_2, 						     \
		(_SHIFTL(dsdx, 16, 16) |	_SHIFTL(dtdy, 0, 16)));	     \
}


#endif

/*
 * ucode.h
 */
#ifdef _UCODE_H_
/* Ｑマイクロコードに対応 */
extern long long int    gspFast3DQ_fifoTextStart[], gspFast3DQ_fifoTextEnd[];
extern long long int    gspFast3DQ_fifoDataStart[], gspFast3DQ_fifoDataEnd[];
extern long long int    gspF3DQNoN_fifoTextStart[], gspF3DQNoN_fifoTextEnd[];
extern long long int    gspF3DQNoN_fifoDataStart[], gspF3DQNoN_fifoDataEnd[];
extern long long int    gspLine3DQ_fifoTextStart[], gspLine3DQ_fifoTextEnd[];
extern long long int    gspLine3DQ_fifoDataStart[], gspLine3DQ_fifoDataEnd[];
#endif

/*
 * mbi.h
 */
#ifdef _UCODE_H_
/* 83 上位４ビットに値が入っていても動作するようにマスクした */
#undef  SEGMENT_NUMBER
#define	SEGMENT_NUMBER(a)	(((unsigned int)(a) & 0x0f000000u) >> 24)
#endif

#ifdef __cplusplus
}
#endif

#endif /* __U64PATCH_H_ */
