From a88337a2fd02386c168396fb44e355a6994ca6e5 Mon Sep 17 00:00:00 2001 From: rozlette Date: Mon, 30 Sep 2019 20:55:41 -0500 Subject: [PATCH] Use gbi.h from oot decomp --- include/PR/abi.h | 476 ++-- include/PR/gbi.h | 4610 ++++++++++++++++++++++++++++++++++++--- include/PR/mbi.h | 100 + include/PR/ultratypes.h | 7 +- 4 files changed, 4802 insertions(+), 391 deletions(-) create mode 100644 include/PR/mbi.h diff --git a/include/PR/abi.h b/include/PR/abi.h index 47a1c99214..63d6b0f99a 100644 --- a/include/PR/abi.h +++ b/include/PR/abi.h @@ -1,189 +1,391 @@ #ifndef _ABI_H_ #define _ABI_H_ -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int gain : 16; - /* 0x4 */ unsigned int addr; +/* Audio commands: */ +#define A_SPNOOP 0 +#define A_ADPCM 1 +#define A_CLEARBUFF 2 +#define A_ENVMIXER 3 +#define A_LOADBUFF 4 +#define A_RESAMPLE 5 +#define A_SAVEBUFF 6 +#define A_SEGMENT 7 +#define A_SETBUFF 8 +#define A_SETVOL 9 +#define A_DMEMMOVE 10 +#define A_LOADADPCM 11 +#define A_MIXER 12 +#define A_INTERLEAVE 13 +#define A_POLEF 14 +#define A_SETLOOP 15 + +#define ACMD_SIZE 32 +/* + * Audio flags + */ + +#define A_INIT 0x01 +#define A_CONTINUE 0x00 +#define A_LOOP 0x02 +#define A_OUT 0x02 +#define A_LEFT 0x02 +#define A_RIGHT 0x00 +#define A_VOL 0x04 +#define A_RATE 0x00 +#define A_AUX 0x08 +#define A_NOAUX 0x00 +#define A_MAIN 0x00 +#define A_MIX 0x10 + +/* + * Data Structures. + */ + +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int gain : 16; + unsigned int addr; } Aadpcm; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int gain : 16; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int gain : 16; + unsigned int addr; } Apolef; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int pad1 : 16; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int pad1 : 16; + unsigned int addr; } Aenvelope; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int pad1 : 8; - /* 0x2 */ unsigned int dmem : 16; - /* 0x4 */ unsigned int pad2 : 16; - /* 0x6 */ unsigned int count : 16; +typedef struct +{ + unsigned int cmd : 8; + unsigned int pad1 : 8; + unsigned int dmem : 16; + unsigned int pad2 : 16; + unsigned int count : 16; } Aclearbuff; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int pad1 : 8; - /* 0x2 */ unsigned int pad2 : 16; - /* 0x4 */ unsigned int inL : 16; - /* 0x6 */ unsigned int inR : 16; +typedef struct +{ + unsigned int cmd : 8; + unsigned int pad1 : 8; + unsigned int pad2 : 16; + unsigned int inL : 16; + unsigned int inR : 16; } Ainterleave; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int pad1 : 24; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int pad1 : 24; + unsigned int addr; } Aloadbuff; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int pad1 : 16; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int pad1 : 16; + unsigned int addr; } Aenvmixer; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int gain : 16; - /* 0x4 */ unsigned int dmemi : 16; - /* 0x6 */ unsigned int dmemo : 16; +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int gain : 16; + unsigned int dmemi : 16; + unsigned int dmemo : 16; } Amixer; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int dmem2 : 16; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int dmem2 : 16; + unsigned int addr; } Apan; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int pitch : 16; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int pitch : 16; + unsigned int addr; } Aresample; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int pad1 : 16; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int pad1 : 16; + unsigned int addr; } Areverb; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int pad1 : 24; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int pad1 : 24; + unsigned int addr; } Asavebuff; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int pad1 : 24; - /* 0x4 */ unsigned int pad2 : 2; - /* 0x4 */ unsigned int number : 4; - /* 0x4 */ unsigned int base : 24; +typedef struct +{ + unsigned int cmd : 8; + unsigned int pad1 : 24; + unsigned int pad2 : 2; + unsigned int number : 4; + unsigned int base : 24; } Asegment; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int dmemin : 16; - /* 0x4 */ unsigned int dmemout : 16; - /* 0x6 */ unsigned int count : 16; +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int dmemin : 16; + unsigned int dmemout : 16; + unsigned int count : 16; } Asetbuff; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int flags : 8; - /* 0x2 */ unsigned int vol : 16; - /* 0x4 */ unsigned int voltgt : 16; - /* 0x6 */ unsigned int volrate : 16; +typedef struct +{ + unsigned int cmd : 8; + unsigned int flags : 8; + unsigned int vol : 16; + unsigned int voltgt : 16; + unsigned int volrate : 16; } Asetvol; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int pad1 : 8; - /* 0x2 */ unsigned int dmemin : 16; - /* 0x4 */ unsigned int dmemout : 16; - /* 0x6 */ unsigned int count : 16; +typedef struct +{ + unsigned int cmd : 8; + unsigned int pad1 : 8; + unsigned int dmemin : 16; + unsigned int dmemout : 16; + unsigned int count : 16; } Admemmove; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int pad1 : 8; - /* 0x2 */ unsigned int count : 16; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int pad1 : 8; + unsigned int count : 16; + unsigned int addr; } Aloadadpcm; - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int pad1 : 8; - /* 0x2 */ unsigned int pad2 : 16; - /* 0x4 */ unsigned int addr; +typedef struct +{ + unsigned int cmd : 8; + unsigned int pad1 : 8; + unsigned int pad2 : 16; + unsigned int addr; } Asetloop; +/* + * Generic Acmd Packet + */ -typedef struct { - /* 0x0 */ unsigned int w0; - /* 0x4 */ unsigned int w1; +typedef struct +{ + unsigned int w0; + unsigned int w1; } Awords; - typedef union { - /* 0x0 */ Awords words; - /* 0x0 */ Aadpcm adpcm; - /* 0x0 */ Apolef polef; - /* 0x0 */ Aclearbuff clearbuff; - /* 0x0 */ Aenvelope envelope; - /* 0x0 */ Ainterleave interleave; - /* 0x0 */ Aloadbuff loadbuff; - /* 0x0 */ Aenvmixer envmixer; - /* 0x0 */ Aresample resample; - /* 0x0 */ Areverb reverb; - /* 0x0 */ Asavebuff savebuff; - /* 0x0 */ Asegment segment; - /* 0x0 */ Asetbuff setbuff; - /* 0x0 */ Asetvol setvol; - /* 0x0 */ Admemmove dmemmove; - /* 0x0 */ Aloadadpcm loadadpcm; - /* 0x0 */ Amixer mixer; - /* 0x0 */ Asetloop setloop; - /* 0x0 */ long long force_union_align; + Awords words; + Aadpcm adpcm; + Apolef polef; + Aclearbuff clearbuff; + Aenvelope envelope; + Ainterleave interleave; + Aloadbuff loadbuff; + Aenvmixer envmixer; + Aresample resample; + Areverb reverb; + Asavebuff savebuff; + Asegment segment; + Asetbuff setbuff; + Asetvol setvol; + Admemmove dmemmove; + Aloadadpcm loadadpcm; + Amixer mixer; + Asetloop setloop; + long long int force_union_align; /* dummy, force alignment */ } Acmd; -typedef short ADPCM_STATE[16]; +/* + * ADPCM State + */ +#define ADPCMVSIZE 8 +#define ADPCMFSIZE 16 +typedef short ADPCM_STATE[ADPCMFSIZE]; +/* + * Pole filter state + */ typedef short POLEF_STATE[4]; +/* + * Resampler state + */ typedef short RESAMPLE_STATE[16]; +/* + * Resampler constants + */ +#define UNITY_PITCH 0x8000 +#define MAX_RATIO 1.99996 /* within .03 cents of +1 octave */ + +/* + * Enveloper/Mixer state + */ typedef short ENVMIX_STATE[40]; -#endif +/* + * Macros to assemble the audio command list + */ + +#define aADPCMdec(pkt, f, s) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_ADPCM, 24, 8) | _SHIFTL(f, 16, 8); \ + _a->words.w1 = (unsigned int)(s); \ + } + +#define aPoleFilter(pkt, f, g, s) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_POLEF, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(g, 0, 16)); \ + _a->words.w1 = (unsigned int)(s); \ + } + +#define aClearBuffer(pkt, d, c) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(d, 0, 24); \ + _a->words.w1 = (unsigned int)(c); \ + } + +#define aEnvMixer(pkt, f, s) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_ENVMIXER, 24, 8) | _SHIFTL(f, 16, 8); \ + _a->words.w1 = (unsigned int)(s); \ + } + +#define aInterleave(pkt, l, r) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_INTERLEAVE, 24, 8); \ + _a->words.w1 = _SHIFTL(l, 16, 16) | _SHIFTL(r, 0, 16); \ + } + +#define aLoadBuffer(pkt, s) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8); \ + _a->words.w1 = (unsigned int)(s); \ + } + +#define aMix(pkt, f, g, i, o) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_MIXER, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(g, 0, 16)); \ + _a->words.w1 = _SHIFTL(i, 16, 16) | _SHIFTL(o, 0, 16); \ + } + +#define aPan(pkt, f, d, s) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_PAN, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(d, 0, 16)); \ + _a->words.w1 = (unsigned int)(s); \ + } + +#define aResample(pkt, f, p, s) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_RESAMPLE, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(p, 0, 16)); \ + _a->words.w1 = (unsigned int)(s); \ + } + +#define aSaveBuffer(pkt, s) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8); \ + _a->words.w1 = (unsigned int)(s); \ + } + +#define aSegment(pkt, s, b) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_SEGMENT, 24, 8); \ + _a->words.w1 = _SHIFTL(s, 24, 8) | _SHIFTL(b, 0, 24); \ + } + +#define aSetBuffer(pkt, f, i, o, c) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_SETBUFF, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(i, 0, 16)); \ + _a->words.w1 = _SHIFTL(c, 0, 16) | _SHIFTL(o, 16, 16); \ + } + +#define aSetVolume(pkt, f, v, t, r) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | \ + _SHIFTL(v, 0, 16)); \ + /* had to change this otherwise it doesn't want to match */ \ + _a->words.w1 = (unsigned int)(r); /*_SHIFTL(r, 0, 16)|_SHIFTL(t, 16, 16) ;*/ \ + } + +#define aSetLoop(pkt, a) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + _a->words.w0 = _SHIFTL(A_SETLOOP, 24, 8); \ + _a->words.w1 = (unsigned int)(a); \ + } + +#define aDMEMMove(pkt, i, o, c) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(i, 0, 24); \ + _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \ + } + +#define aLoadADPCM(pkt, c, d) \ + { \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_LOADADPCM, 24, 8) | _SHIFTL(c, 0, 24); \ + _a->words.w1 = (unsigned int)d; \ + } + +#endif /* !_ABI_H_ */ diff --git a/include/PR/gbi.h b/include/PR/gbi.h index 1d2b41aec9..ab3a08c107 100644 --- a/include/PR/gbi.h +++ b/include/PR/gbi.h @@ -1,386 +1,4490 @@ -#ifndef _GBI_H_ -#define _GBI_H_ +#include "mbi.h" +#ifndef _ULTRA64_GBI_H_ +#define _ULTRA64_GBI_H_ + +/* To enable Fast3DEX grucode support, define F3DEX_GBI. */ + +/* Types */ + + +#define F3DEX_GBI_2 + +#ifdef F3DEX_GBI_2 +# ifndef F3DEX_GBI +# define F3DEX_GBI +# endif +#define G_NOOP 0x00 +#define G_RDPHALF_2 0xf1 +#define G_SETOTHERMODE_H 0xe3 +#define G_SETOTHERMODE_L 0xe2 +#define G_RDPHALF_1 0xe1 +#define G_SPNOOP 0xe0 +#define G_ENDDL 0xdf +#define G_DL 0xde +#define G_LOAD_UCODE 0xdd +#define G_MOVEMEM 0xdc +#define G_MOVEWORD 0xdb +#define G_MTX 0xda +#define G_GEOMETRYMODE 0xd9 +#define G_POPMTX 0xd8 +#define G_TEXTURE 0xd7 +#define G_DMA_IO 0xd6 +#define G_SPECIAL_1 0xd5 +#define G_SPECIAL_2 0xd4 +#define G_SPECIAL_3 0xd3 + +#define G_VTX 0x01 +#define G_MODIFYVTX 0x02 +#define G_CULLDL 0x03 +#define G_BRANCH_Z 0x04 +#define G_TRI1 0x05 +#define G_TRI2 0x06 +#define G_QUAD 0x07 +#define G_LINE3D 0x08 +#else /* F3DEX_GBI_2 */ + +/* DMA commands: */ +#define G_SPNOOP 0 /* handle 0 gracefully */ +#define G_MTX 1 +#define G_RESERVED0 2 /* not implemeted */ +#define G_MOVEMEM 3 /* move a block of memory (up to 4 words) to dmem */ +#define G_VTX 4 +#define G_RESERVED1 5 /* not implemeted */ +#define G_DL 6 +#define G_RESERVED2 7 /* not implemeted */ +#define G_RESERVED3 8 /* not implemeted */ +#define G_SPRITE2D_BASE 9 /* sprite command */ + +/* IMMEDIATE commands: */ +#define G_IMMFIRST -65 +#define G_TRI1 (G_IMMFIRST-0) +#define G_CULLDL (G_IMMFIRST-1) +#define G_POPMTX (G_IMMFIRST-2) +#define G_MOVEWORD (G_IMMFIRST-3) +#define G_TEXTURE (G_IMMFIRST-4) +#define G_SETOTHERMODE_H (G_IMMFIRST-5) +#define G_SETOTHERMODE_L (G_IMMFIRST-6) +#define G_ENDDL (G_IMMFIRST-7) +#define G_SETGEOMETRYMODE (G_IMMFIRST-8) +#define G_CLEARGEOMETRYMODE (G_IMMFIRST-9) +#define G_LINE3D (G_IMMFIRST-10) +#define G_RDPHALF_1 (G_IMMFIRST-11) +#define G_RDPHALF_2 (G_IMMFIRST-12) +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +# define G_MODIFYVTX (G_IMMFIRST-13) +# define G_TRI2 (G_IMMFIRST-14) +# define G_BRANCH_Z (G_IMMFIRST-15) +# define G_LOAD_UCODE (G_IMMFIRST-16) +#else +# define G_RDPHALF_CONT (G_IMMFIRST-13) +#endif + +/* We are overloading 2 of the immediate commands + to keep the byte alignment of dmem the same */ + +#define G_SPRITE2D_SCALEFLIP (G_IMMFIRST-1) +#define G_SPRITE2D_DRAW (G_IMMFIRST-2) + +/* RDP commands: */ +#define G_NOOP 0xc0 /* 0 */ + +#endif /* F3DEX_GBI_2 */ + +/* RDP commands: */ +#define G_SETCIMG 0xff /* -1 */ +#define G_SETZIMG 0xfe /* -2 */ +#define G_SETTIMG 0xfd /* -3 */ +#define G_SETCOMBINE 0xfc /* -4 */ +#define G_SETENVCOLOR 0xfb /* -5 */ +#define G_SETPRIMCOLOR 0xfa /* -6 */ +#define G_SETBLENDCOLOR 0xf9 /* -7 */ +#define G_SETFOGCOLOR 0xf8 /* -8 */ +#define G_SETFILLCOLOR 0xf7 /* -9 */ +#define G_FILLRECT 0xf6 /* -10 */ +#define G_SETTILE 0xf5 /* -11 */ +#define G_LOADTILE 0xf4 /* -12 */ +#define G_LOADBLOCK 0xf3 /* -13 */ +#define G_SETTILESIZE 0xf2 /* -14 */ +#define G_LOADTLUT 0xf0 /* -16 */ +#define G_RDPSETOTHERMODE 0xef /* -17 */ +#define G_SETPRIMDEPTH 0xee /* -18 */ +#define G_SETSCISSOR 0xed /* -19 */ +#define G_SETCONVERT 0xec /* -20 */ +#define G_SETKEYR 0xeb /* -21 */ +#define G_SETKEYGB 0xea /* -22 */ +#define G_RDPFULLSYNC 0xe9 /* -23 */ +#define G_RDPTILESYNC 0xe8 /* -24 */ +#define G_RDPPIPESYNC 0xe7 /* -25 */ +#define G_RDPLOADSYNC 0xe6 /* -26 */ +#define G_TEXRECTFLIP 0xe5 /* -27 */ +#define G_TEXRECT 0xe4 /* -28 */ + + +/* + * The following commands are the "generated" RDP commands; the user + * never sees them, the RSP microcode generates them. + * + * The layout of the bits is magical, to save work in the ucode. + * These id's are -56, -52, -54, -50, -55, -51, -53, -49, ... + * edge, shade, texture, zbuff bits: estz + */ +#define G_TRI_FILL 0xc8 /* fill triangle: 11001000 */ +#define G_TRI_SHADE 0xcc /* shade triangle: 11001100 */ +#define G_TRI_TXTR 0xca /* texture triangle: 11001010 */ +#define G_TRI_SHADE_TXTR 0xce /* shade, texture triangle: 11001110 */ +#define G_TRI_FILL_ZBUFF 0xc9 /* fill, zbuff triangle: 11001001 */ +#define G_TRI_SHADE_ZBUFF 0xcd /* shade, zbuff triangle: 11001101 */ +#define G_TRI_TXTR_ZBUFF 0xcb /* texture, zbuff triangle: 11001011 */ +#define G_TRI_SHADE_TXTR_ZBUFF 0xcf /* shade, txtr, zbuff trngl: 11001111 */ + +/* + * A TRI_FILL triangle is just the edges. You need to set the DP + * to use primcolor, in order to see anything. (it is NOT a triangle + * that gets rendered in 'fill mode'. Triangles can't be rendered + * in 'fill mode') + * + * A TRI_SHADE is a gouraud triangle that has colors interpolated. + * Flat-shaded triangles (from the software) are still gouraud shaded, + * it's just the colors are all the same and the deltas are 0. + * + * Other triangle types, and combinations are more obvious. + */ + +/* masks to build RDP triangle commands: */ +#define G_RDP_TRI_FILL_MASK 0x08 +#define G_RDP_TRI_SHADE_MASK 0x04 +#define G_RDP_TRI_TXTR_MASK 0x02 +#define G_RDP_TRI_ZBUFF_MASK 0x01 + +/* + * HACK: + * This is a dreadful hack. For version 1.0 hardware, there are still + * some 'bowtie' hangs. This parameter can be increased to avoid + * the hangs. Every increase of 4 chops one scanline off of every + * triangle. Values of 4,8,12 should be sufficient to avoid any + * bowtie hang. + * + * Change this value, then recompile ALL of your program (including static + * display lists!) + * + * THIS WILL BE REMOVED FOR HARDWARE VERSION 2.0! + */ +#define BOWTIE_VAL 0 + + +/* gets added to RDP command, in order to test for addres fixup: */ +#define G_RDP_ADDR_FIXUP 3 /* |RDP cmds| <= this, do addr fixup */ +#ifdef _LANGUAGE_ASSEMBLY +#define G_RDP_TEXRECT_CHECK ((-1*G_TEXRECTFLIP)& 0xff) +#endif + +/* macros for command parsing: */ +#define GDMACMD(x) (x) +#define GIMMCMD(x) (G_IMMFIRST-(x)) +#define GRDPCMD(x) (0xff-(x)) + +#define G_DMACMDSIZ 128 +#define G_IMMCMDSIZ 64 +#define G_RDPCMDSIZ 64 + +/* + * Coordinate shift values, number of bits of fraction + */ +#define G_TEXTURE_IMAGE_FRAC 2 +#define G_TEXTURE_SCALE_FRAC 16 +#define G_SCALE_FRAC 8 +#define G_ROTATE_FRAC 16 + +/* + * Parameters to graphics commands + */ + +/* + * Data packing macros + */ + +/* + * Maximum z-buffer value, used to initialize the z-buffer. + * Note : this number is NOT the viewport z-scale constant. + * See the comment next to G_MAXZ for more info. + */ +#define G_MAXFBZ 0x3fff /* 3b exp, 11b mantissa */ + +#define GPACK_RGBA5551(r, g, b, a) ((((r)<<8) & 0xf800) | \ + (((g)<<3) & 0x7c0) | \ + (((b)>>2) & 0x3e) | ((a) & 0x1)) +#define GPACK_ZDZ(z, dz) ((z) << 2 | (dz)) + +/* + * G_MTX: parameter flags + */ +#ifdef F3DEX_GBI_2 +# define G_MTX_MODELVIEW 0x00 /* matrix types */ +# define G_MTX_PROJECTION 0x04 +# define G_MTX_MUL 0x00 /* concat or load */ +# define G_MTX_LOAD 0x02 +# define G_MTX_NOPUSH 0x00 /* push or not */ +# define G_MTX_PUSH 0x01 +#else /* F3DEX_GBI_2 */ +# define G_MTX_MODELVIEW 0x00 /* matrix types */ +# define G_MTX_PROJECTION 0x01 +# define G_MTX_MUL 0x00 /* concat or load */ +# define G_MTX_LOAD 0x02 +# define G_MTX_NOPUSH 0x00 /* push or not */ +# define G_MTX_PUSH 0x04 +#endif /* F3DEX_GBI_2 */ + +/* + * flags for G_SETGEOMETRYMODE + * (this rendering state is maintained in RSP) + * + * DO NOT USE THE LOW 8 BITS OF GEOMETRYMODE: + * The weird bit-ordering is for the micro-code: the lower byte + * can be OR'd in with G_TRI_SHADE (11001100) to construct + * the triangle command directly. Don't break it... + * + * DO NOT USE THE HIGH 8 BITS OF GEOMETRYMODE: + * The high byte is OR'd with 0x703 to form the clip code mask. + * If it is set to 0x04, this will cause near clipping to occur. + * If it is zero, near clipping will not occur. + * + * Further explanation: + * G_SHADE is necessary in order to see the color that you passed + * down with the vertex. If G_SHADE isn't set, you need to set the DP + * appropriately and use primcolor to see anything. + * + * G_SHADING_SMOOTH enabled means use all 3 colors of the triangle. + * If it is not set, then do 'flat shading', where only one vertex color + * is used (and all 3 vertices are set to that same color by the ucode) + * See the man page for gSP1Triangle(). + * + */ +#define G_ZBUFFER 0x00000001 +#define G_SHADE 0x00000004 /* enable Gouraud interp */ +/* rest of low byte reserved for setup ucode */ +#ifdef F3DEX_GBI_2 +# define G_TEXTURE_ENABLE 0x00000000 /* Ignored */ +# define G_SHADING_SMOOTH 0x00200000 /* flat or smooth shaded */ +# define G_CULL_FRONT 0x00000200 +# define G_CULL_BACK 0x00000400 +# define G_CULL_BOTH 0x00000600 /* To make code cleaner */ +#else +# define G_TEXTURE_ENABLE 0x00000002 /* Microcode use only */ +# define G_SHADING_SMOOTH 0x00000200 /* flat or smooth shaded */ +# define G_CULL_FRONT 0x00001000 +# define G_CULL_BACK 0x00002000 +# define G_CULL_BOTH 0x00003000 /* To make code cleaner */ +#endif +#define G_FOG 0x00010000 +#define G_LIGHTING 0x00020000 +#define G_TEXTURE_GEN 0x00040000 +#define G_TEXTURE_GEN_LINEAR 0x00080000 +#define G_LOD 0x00100000 /* NOT IMPLEMENTED */ +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +# define G_CLIPPING 0x00800000 +#else +# define G_CLIPPING 0x00000000 +#endif + +#ifdef _LANGUAGE_ASSEMBLY +#define G_FOG_H (G_FOG/0x10000) +#define G_LIGHTING_H (G_LIGHTING/0x10000) +#define G_TEXTURE_GEN_H (G_TEXTURE_GEN/0x10000) +#define G_TEXTURE_GEN_LINEAR_H (G_TEXTURE_GEN_LINEAR/0x10000) +#define G_LOD_H (G_LOD/0x10000) /* NOT IMPLEMENTED */ +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +# define G_CLIPPING_H (G_CLIPPING/0x10000) +#endif +#endif + +/* Need these defined for Sprite Microcode */ +#ifdef _LANGUAGE_ASSEMBLY +#define G_TX_LOADTILE 7 +#define G_TX_RENDERTILE 0 + +#define G_TX_NOMIRROR 0 +#define G_TX_WRAP 0 +#define G_TX_MIRROR 0x1 +#define G_TX_CLAMP 0x2 +#define G_TX_NOMASK 0 +#define G_TX_NOLOD 0 +#endif + +/* + * G_SETIMG fmt: set image formats + */ +#define G_IM_FMT_RGBA 0 +#define G_IM_FMT_YUV 1 +#define G_IM_FMT_CI 2 +#define G_IM_FMT_IA 3 +#define G_IM_FMT_I 4 + +/* + * G_SETIMG siz: set image pixel size + */ +#define G_IM_SIZ_4b 0 +#define G_IM_SIZ_8b 1 +#define G_IM_SIZ_16b 2 +#define G_IM_SIZ_32b 3 +#define G_IM_SIZ_DD 5 + +#define G_IM_SIZ_4b_BYTES 0 +#define G_IM_SIZ_4b_TILE_BYTES G_IM_SIZ_4b_BYTES +#define G_IM_SIZ_4b_LINE_BYTES G_IM_SIZ_4b_BYTES + +#define G_IM_SIZ_8b_BYTES 1 +#define G_IM_SIZ_8b_TILE_BYTES G_IM_SIZ_8b_BYTES +#define G_IM_SIZ_8b_LINE_BYTES G_IM_SIZ_8b_BYTES + +#define G_IM_SIZ_16b_BYTES 2 +#define G_IM_SIZ_16b_TILE_BYTES G_IM_SIZ_16b_BYTES +#define G_IM_SIZ_16b_LINE_BYTES G_IM_SIZ_16b_BYTES + +#define G_IM_SIZ_32b_BYTES 4 +#define G_IM_SIZ_32b_TILE_BYTES 2 +#define G_IM_SIZ_32b_LINE_BYTES 2 + +#define G_IM_SIZ_4b_LOAD_BLOCK G_IM_SIZ_16b +#define G_IM_SIZ_8b_LOAD_BLOCK G_IM_SIZ_16b +#define G_IM_SIZ_16b_LOAD_BLOCK G_IM_SIZ_16b +#define G_IM_SIZ_32b_LOAD_BLOCK G_IM_SIZ_32b + +#define G_IM_SIZ_4b_SHIFT 2 +#define G_IM_SIZ_8b_SHIFT 1 +#define G_IM_SIZ_16b_SHIFT 0 +#define G_IM_SIZ_32b_SHIFT 0 + +#define G_IM_SIZ_4b_INCR 3 +#define G_IM_SIZ_8b_INCR 1 +#define G_IM_SIZ_16b_INCR 0 +#define G_IM_SIZ_32b_INCR 0 + +/* + * G_SETCOMBINE: color combine modes + */ +/* Color combiner constants: */ +#define G_CCMUX_COMBINED 0 +#define G_CCMUX_TEXEL0 1 +#define G_CCMUX_TEXEL1 2 +#define G_CCMUX_PRIMITIVE 3 +#define G_CCMUX_SHADE 4 +#define G_CCMUX_ENVIRONMENT 5 +#define G_CCMUX_CENTER 6 +#define G_CCMUX_SCALE 6 +#define G_CCMUX_COMBINED_ALPHA 7 +#define G_CCMUX_TEXEL0_ALPHA 8 +#define G_CCMUX_TEXEL1_ALPHA 9 +#define G_CCMUX_PRIMITIVE_ALPHA 10 +#define G_CCMUX_SHADE_ALPHA 11 +#define G_CCMUX_ENV_ALPHA 12 +#define G_CCMUX_LOD_FRACTION 13 +#define G_CCMUX_PRIM_LOD_FRAC 14 +#define G_CCMUX_NOISE 7 +#define G_CCMUX_K4 7 +#define G_CCMUX_K5 15 +#define G_CCMUX_1 6 +#define G_CCMUX_0 31 + +/* Alpha combiner constants: */ +#define G_ACMUX_COMBINED 0 +#define G_ACMUX_TEXEL0 1 +#define G_ACMUX_TEXEL1 2 +#define G_ACMUX_PRIMITIVE 3 +#define G_ACMUX_SHADE 4 +#define G_ACMUX_ENVIRONMENT 5 +#define G_ACMUX_LOD_FRACTION 0 +#define G_ACMUX_PRIM_LOD_FRAC 6 +#define G_ACMUX_1 6 +#define G_ACMUX_0 7 + +/* typical CC cycle 1 modes */ +#define G_CC_PRIMITIVE 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE +#define G_CC_SHADE 0, 0, 0, SHADE, 0, 0, 0, SHADE +#define G_CC_MODULATEI TEXEL0, 0, SHADE, 0, 0, 0, 0, SHADE +#define G_CC_MODULATEIA TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0 +#define G_CC_MODULATEIDECALA TEXEL0, 0, SHADE, 0, 0, 0, 0, TEXEL0 +#define G_CC_MODULATERGB G_CC_MODULATEI +#define G_CC_MODULATERGBA G_CC_MODULATEIA +#define G_CC_MODULATERGBDECALA G_CC_MODULATEIDECALA +#define G_CC_MODULATEI_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE +#define G_CC_MODULATEIA_PRIM TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0 +#define G_CC_MODULATEIDECALA_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL0 +#define G_CC_MODULATERGB_PRIM G_CC_MODULATEI_PRIM +#define G_CC_MODULATERGBA_PRIM G_CC_MODULATEIA_PRIM +#define G_CC_MODULATERGBDECALA_PRIM G_CC_MODULATEIDECALA_PRIM +#define G_CC_DECALRGB 0, 0, 0, TEXEL0, 0, 0, 0, SHADE +#define G_CC_DECALRGBA 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0 +#define G_CC_BLENDI ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDIA ENVIRONMENT, SHADE, TEXEL0, SHADE, TEXEL0, 0, SHADE, 0 +#define G_CC_BLENDIDECALA ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_BLENDRGBA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDRGBDECALA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_ADDRGB 1, 0, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_ADDRGBDECALA 1, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_REFLECTRGB ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_REFLECTRGBDECALA ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_HILITERGB PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_HILITERGBA PRIMITIVE, SHADE, TEXEL0, SHADE, PRIMITIVE, SHADE, TEXEL0, SHADE +#define G_CC_HILITERGBDECALA PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_SHADEDECALA 0, 0, 0, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_BLENDPE PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, SHADE, 0 +#define G_CC_BLENDPEDECALA PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, TEXEL0 + +/* oddball modes */ +#define _G_CC_BLENDPE ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, TEXEL0, 0, SHADE, 0 +#define _G_CC_BLENDPEDECALA ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, 0, 0, 0, TEXEL0 +#define _G_CC_TWOCOLORTEX PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE +/* used for 1-cycle sparse mip-maps, primitive color has color of lowest LOD */ +#define _G_CC_SPARSEST PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0, PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0 +#define G_CC_TEMPLERP TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0, TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0 + +/* typical CC cycle 1 modes, usually followed by other cycle 2 modes */ +#define G_CC_TRILERP TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0 +#define G_CC_INTERFERENCE TEXEL0, 0, TEXEL1, 0, TEXEL0, 0, TEXEL1, 0 + +/* + * One-cycle color convert operation + */ +#define G_CC_1CYUV2RGB TEXEL0, K4, K5, TEXEL0, 0, 0, 0, SHADE + +/* + * NOTE: YUV2RGB expects TF step1 color conversion to occur in 2nd clock. + * Therefore, CC looks for step1 results in TEXEL1 + */ +#define G_CC_YUV2RGB TEXEL1, K4, K5, TEXEL1, 0, 0, 0, 0 + +/* typical CC cycle 2 modes */ +#define G_CC_PASS2 0, 0, 0, COMBINED, 0, 0, 0, COMBINED +#define G_CC_MODULATEI2 COMBINED, 0, SHADE, 0, 0, 0, 0, SHADE +#define G_CC_MODULATEIA2 COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0 +#define G_CC_MODULATERGB2 G_CC_MODULATEI2 +#define G_CC_MODULATERGBA2 G_CC_MODULATEIA2 +#define G_CC_MODULATEI_PRIM2 COMBINED, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE +#define G_CC_MODULATEIA_PRIM2 COMBINED, 0, PRIMITIVE, 0, COMBINED, 0, PRIMITIVE, 0 +#define G_CC_MODULATERGB_PRIM2 G_CC_MODULATEI_PRIM2 +#define G_CC_MODULATERGBA_PRIM2 G_CC_MODULATEIA_PRIM2 +#define G_CC_DECALRGB2 0, 0, 0, COMBINED, 0, 0, 0, SHADE +/* + * ? +#define G_CC_DECALRGBA2 COMBINED, SHADE, COMBINED_ALPHA, SHADE, 0, 0, 0, SHADE +*/ +#define G_CC_BLENDI2 ENVIRONMENT, SHADE, COMBINED, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDIA2 ENVIRONMENT, SHADE, COMBINED, SHADE, COMBINED, 0, SHADE, 0 +#define G_CC_CHROMA_KEY2 TEXEL0, CENTER, SCALE, 0, 0, 0, 0, 0 +#define G_CC_HILITERGB2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, SHADE +#define G_CC_HILITERGBA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, ENVIRONMENT, COMBINED, TEXEL0, COMBINED +#define G_CC_HILITERGBDECALA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, TEXEL0 +#define G_CC_HILITERGBPASSA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, COMBINED + +/* + * G_SETOTHERMODE_L sft: shift count + */ +#define G_MDSFT_ALPHACOMPARE 0 +#define G_MDSFT_ZSRCSEL 2 +#define G_MDSFT_RENDERMODE 3 +#define G_MDSFT_BLENDER 16 + +/* + * G_SETOTHERMODE_H sft: shift count + */ +#define G_MDSFT_BLENDMASK 0 /* unsupported */ +#define G_MDSFT_ALPHADITHER 4 +#define G_MDSFT_RGBDITHER 6 + +#define G_MDSFT_COMBKEY 8 +#define G_MDSFT_TEXTCONV 9 +#define G_MDSFT_TEXTFILT 12 +#define G_MDSFT_TEXTLUT 14 +#define G_MDSFT_TEXTLOD 16 +#define G_MDSFT_TEXTDETAIL 17 +#define G_MDSFT_TEXTPERSP 19 +#define G_MDSFT_CYCLETYPE 20 +#define G_MDSFT_COLORDITHER 22 /* unsupported in HW 2.0 */ +#define G_MDSFT_PIPELINE 23 + +/* G_SETOTHERMODE_H gPipelineMode */ +#define G_PM_1PRIMITIVE (1 << G_MDSFT_PIPELINE) +#define G_PM_NPRIMITIVE (0 << G_MDSFT_PIPELINE) + +/* G_SETOTHERMODE_H gSetCycleType */ +#define G_CYC_1CYCLE (0 << G_MDSFT_CYCLETYPE) +#define G_CYC_2CYCLE (1 << G_MDSFT_CYCLETYPE) +#define G_CYC_COPY (2 << G_MDSFT_CYCLETYPE) +#define G_CYC_FILL (3 << G_MDSFT_CYCLETYPE) + +/* G_SETOTHERMODE_H gSetTexturePersp */ +#define G_TP_NONE (0 << G_MDSFT_TEXTPERSP) +#define G_TP_PERSP (1 << G_MDSFT_TEXTPERSP) + +/* G_SETOTHERMODE_H gSetTextureDetail */ +#define G_TD_CLAMP (0 << G_MDSFT_TEXTDETAIL) +#define G_TD_SHARPEN (1 << G_MDSFT_TEXTDETAIL) +#define G_TD_DETAIL (2 << G_MDSFT_TEXTDETAIL) + +/* G_SETOTHERMODE_H gSetTextureLOD */ +#define G_TL_TILE (0 << G_MDSFT_TEXTLOD) +#define G_TL_LOD (1 << G_MDSFT_TEXTLOD) + +/* G_SETOTHERMODE_H gSetTextureLUT */ +#define G_TT_NONE (0 << G_MDSFT_TEXTLUT) +#define G_TT_RGBA16 (2 << G_MDSFT_TEXTLUT) +#define G_TT_IA16 (3 << G_MDSFT_TEXTLUT) + +/* G_SETOTHERMODE_H gSetTextureFilter */ +#define G_TF_POINT (0 << G_MDSFT_TEXTFILT) +#define G_TF_AVERAGE (3 << G_MDSFT_TEXTFILT) +#define G_TF_BILERP (2 << G_MDSFT_TEXTFILT) + +/* G_SETOTHERMODE_H gSetTextureConvert */ +#define G_TC_CONV (0 << G_MDSFT_TEXTCONV) +#define G_TC_FILTCONV (5 << G_MDSFT_TEXTCONV) +#define G_TC_FILT (6 << G_MDSFT_TEXTCONV) + +/* G_SETOTHERMODE_H gSetCombineKey */ +#define G_CK_NONE (0 << G_MDSFT_COMBKEY) +#define G_CK_KEY (1 << G_MDSFT_COMBKEY) + +/* G_SETOTHERMODE_H gSetColorDither */ +#define G_CD_MAGICSQ (0 << G_MDSFT_RGBDITHER) +#define G_CD_BAYER (1 << G_MDSFT_RGBDITHER) +#define G_CD_NOISE (2 << G_MDSFT_RGBDITHER) + +#ifndef _HW_VERSION_1 +#define G_CD_DISABLE (3 << G_MDSFT_RGBDITHER) +#define G_CD_ENABLE G_CD_NOISE /* HW 1.0 compatibility mode */ +#else +#define G_CD_ENABLE (1 << G_MDSFT_COLORDITHER) +#define G_CD_DISABLE (0 << G_MDSFT_COLORDITHER) +#endif + +/* G_SETOTHERMODE_H gSetAlphaDither */ +#define G_AD_PATTERN (0 << G_MDSFT_ALPHADITHER) +#define G_AD_NOTPATTERN (1 << G_MDSFT_ALPHADITHER) +#define G_AD_NOISE (2 << G_MDSFT_ALPHADITHER) +#define G_AD_DISABLE (3 << G_MDSFT_ALPHADITHER) + +/* G_SETOTHERMODE_L gSetAlphaCompare */ +#define G_AC_NONE (0 << G_MDSFT_ALPHACOMPARE) +#define G_AC_THRESHOLD (1 << G_MDSFT_ALPHACOMPARE) +#define G_AC_DITHER (3 << G_MDSFT_ALPHACOMPARE) + +/* G_SETOTHERMODE_L gSetDepthSource */ +#define G_ZS_PIXEL (0 << G_MDSFT_ZSRCSEL) +#define G_ZS_PRIM (1 << G_MDSFT_ZSRCSEL) + +/* G_SETOTHERMODE_L gSetRenderMode */ +#define AA_EN 0x8 +#define Z_CMP 0x10 +#define Z_UPD 0x20 +#define IM_RD 0x40 +#define CLR_ON_CVG 0x80 +#define CVG_DST_CLAMP 0 +#define CVG_DST_WRAP 0x100 +#define CVG_DST_FULL 0x200 +#define CVG_DST_SAVE 0x300 +#define ZMODE_OPA 0 +#define ZMODE_INTER 0x400 +#define ZMODE_XLU 0x800 +#define ZMODE_DEC 0xc00 +#define CVG_X_ALPHA 0x1000 +#define ALPHA_CVG_SEL 0x2000 +#define FORCE_BL 0x4000 +#define TEX_EDGE 0x0000 /* used to be 0x8000 */ + +#define G_BL_CLR_IN 0 +#define G_BL_CLR_MEM 1 +#define G_BL_CLR_BL 2 +#define G_BL_CLR_FOG 3 +#define G_BL_1MA 0 +#define G_BL_A_MEM 1 +#define G_BL_A_IN 0 +#define G_BL_A_FOG 1 +#define G_BL_A_SHADE 2 +#define G_BL_1 2 +#define G_BL_0 3 + +#define GBL_c1(m1a, m1b, m2a, m2b) \ + (m1a) << 30 | (m1b) << 26 | (m2a) << 22 | (m2b) << 18 +#define GBL_c2(m1a, m1b, m2a, m2b) \ + (m1a) << 28 | (m1b) << 24 | (m2a) << 20 | (m2b) << 16 + +#define RM_AA_ZB_OPA_SURF(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_ZB_OPA_SURF(clk) \ + AA_EN | Z_CMP | Z_UPD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_XLU_SURF(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ + FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_OPA_DECAL(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | ALPHA_CVG_SEL | \ + ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_ZB_OPA_DECAL(clk) \ + AA_EN | Z_CMP | CVG_DST_WRAP | ALPHA_CVG_SEL | \ + ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_XLU_DECAL(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ + FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_OPA_INTER(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + ALPHA_CVG_SEL | ZMODE_INTER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_ZB_OPA_INTER(clk) \ + AA_EN | Z_CMP | Z_UPD | CVG_DST_CLAMP | \ + ALPHA_CVG_SEL | ZMODE_INTER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_XLU_INTER(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ + FORCE_BL | ZMODE_INTER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_XLU_LINE(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_DEC_LINE(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_SAVE | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_TEX_EDGE(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_TEX_INTER(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_INTER | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_SUB_SURF(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_PCL_SURF(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_OPA_TERR(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_TEX_TERR(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_SUB_TERR(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + + +#define RM_AA_OPA_SURF(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_OPA_SURF(clk) \ + AA_EN | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_XLU_SURF(clk) \ + AA_EN | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | FORCE_BL | \ + ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_XLU_LINE(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_DEC_LINE(clk) \ + AA_EN | IM_RD | CVG_DST_FULL | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_TEX_EDGE(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_SUB_SURF(clk) \ + AA_EN | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_PCL_SURF(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_OPA_TERR(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_TEX_TERR(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_SUB_TERR(clk) \ + AA_EN | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + + +#define RM_ZB_OPA_SURF(clk) \ + Z_CMP | Z_UPD | CVG_DST_FULL | ALPHA_CVG_SEL | \ + ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_ZB_XLU_SURF(clk) \ + Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_OPA_DECAL(clk) \ + Z_CMP | CVG_DST_FULL | ALPHA_CVG_SEL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_ZB_XLU_DECAL(clk) \ + Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_CLD_SURF(clk) \ + Z_CMP | IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_OVL_SURF(clk) \ + Z_CMP | IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_PCL_SURF(clk) \ + Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | \ + G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + + +#define RM_OPA_SURF(clk) \ + CVG_DST_CLAMP | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define RM_XLU_SURF(clk) \ + IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_TEX_EDGE(clk) \ + CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL |\ + ZMODE_OPA | TEX_EDGE | AA_EN | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define RM_CLD_SURF(clk) \ + IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_PCL_SURF(clk) \ + CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ + G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define RM_ADD(clk) \ + IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_FOG, G_BL_CLR_MEM, G_BL_1) + +#define RM_NOOP(clk) \ + GBL_c##clk(0, 0, 0, 0) + +#define RM_VISCVG(clk) \ + IM_RD | FORCE_BL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_BL, G_BL_A_MEM) + +/* for rendering to an 8-bit framebuffer */ +#define RM_OPA_CI(clk) \ + CVG_DST_CLAMP | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + + + +#define G_RM_AA_ZB_OPA_SURF RM_AA_ZB_OPA_SURF(1) +#define G_RM_AA_ZB_OPA_SURF2 RM_AA_ZB_OPA_SURF(2) +#define G_RM_AA_ZB_XLU_SURF RM_AA_ZB_XLU_SURF(1) +#define G_RM_AA_ZB_XLU_SURF2 RM_AA_ZB_XLU_SURF(2) +#define G_RM_AA_ZB_OPA_DECAL RM_AA_ZB_OPA_DECAL(1) +#define G_RM_AA_ZB_OPA_DECAL2 RM_AA_ZB_OPA_DECAL(2) +#define G_RM_AA_ZB_XLU_DECAL RM_AA_ZB_XLU_DECAL(1) +#define G_RM_AA_ZB_XLU_DECAL2 RM_AA_ZB_XLU_DECAL(2) +#define G_RM_AA_ZB_OPA_INTER RM_AA_ZB_OPA_INTER(1) +#define G_RM_AA_ZB_OPA_INTER2 RM_AA_ZB_OPA_INTER(2) +#define G_RM_AA_ZB_XLU_INTER RM_AA_ZB_XLU_INTER(1) +#define G_RM_AA_ZB_XLU_INTER2 RM_AA_ZB_XLU_INTER(2) +#define G_RM_AA_ZB_XLU_LINE RM_AA_ZB_XLU_LINE(1) +#define G_RM_AA_ZB_XLU_LINE2 RM_AA_ZB_XLU_LINE(2) +#define G_RM_AA_ZB_DEC_LINE RM_AA_ZB_DEC_LINE(1) +#define G_RM_AA_ZB_DEC_LINE2 RM_AA_ZB_DEC_LINE(2) +#define G_RM_AA_ZB_TEX_EDGE RM_AA_ZB_TEX_EDGE(1) +#define G_RM_AA_ZB_TEX_EDGE2 RM_AA_ZB_TEX_EDGE(2) +#define G_RM_AA_ZB_TEX_INTER RM_AA_ZB_TEX_INTER(1) +#define G_RM_AA_ZB_TEX_INTER2 RM_AA_ZB_TEX_INTER(2) +#define G_RM_AA_ZB_SUB_SURF RM_AA_ZB_SUB_SURF(1) +#define G_RM_AA_ZB_SUB_SURF2 RM_AA_ZB_SUB_SURF(2) +#define G_RM_AA_ZB_PCL_SURF RM_AA_ZB_PCL_SURF(1) +#define G_RM_AA_ZB_PCL_SURF2 RM_AA_ZB_PCL_SURF(2) +#define G_RM_AA_ZB_OPA_TERR RM_AA_ZB_OPA_TERR(1) +#define G_RM_AA_ZB_OPA_TERR2 RM_AA_ZB_OPA_TERR(2) +#define G_RM_AA_ZB_TEX_TERR RM_AA_ZB_TEX_TERR(1) +#define G_RM_AA_ZB_TEX_TERR2 RM_AA_ZB_TEX_TERR(2) +#define G_RM_AA_ZB_SUB_TERR RM_AA_ZB_SUB_TERR(1) +#define G_RM_AA_ZB_SUB_TERR2 RM_AA_ZB_SUB_TERR(2) + +#define G_RM_RA_ZB_OPA_SURF RM_RA_ZB_OPA_SURF(1) +#define G_RM_RA_ZB_OPA_SURF2 RM_RA_ZB_OPA_SURF(2) +#define G_RM_RA_ZB_OPA_DECAL RM_RA_ZB_OPA_DECAL(1) +#define G_RM_RA_ZB_OPA_DECAL2 RM_RA_ZB_OPA_DECAL(2) +#define G_RM_RA_ZB_OPA_INTER RM_RA_ZB_OPA_INTER(1) +#define G_RM_RA_ZB_OPA_INTER2 RM_RA_ZB_OPA_INTER(2) + +#define G_RM_AA_OPA_SURF RM_AA_OPA_SURF(1) +#define G_RM_AA_OPA_SURF2 RM_AA_OPA_SURF(2) +#define G_RM_AA_XLU_SURF RM_AA_XLU_SURF(1) +#define G_RM_AA_XLU_SURF2 RM_AA_XLU_SURF(2) +#define G_RM_AA_XLU_LINE RM_AA_XLU_LINE(1) +#define G_RM_AA_XLU_LINE2 RM_AA_XLU_LINE(2) +#define G_RM_AA_DEC_LINE RM_AA_DEC_LINE(1) +#define G_RM_AA_DEC_LINE2 RM_AA_DEC_LINE(2) +#define G_RM_AA_TEX_EDGE RM_AA_TEX_EDGE(1) +#define G_RM_AA_TEX_EDGE2 RM_AA_TEX_EDGE(2) +#define G_RM_AA_SUB_SURF RM_AA_SUB_SURF(1) +#define G_RM_AA_SUB_SURF2 RM_AA_SUB_SURF(2) +#define G_RM_AA_PCL_SURF RM_AA_PCL_SURF(1) +#define G_RM_AA_PCL_SURF2 RM_AA_PCL_SURF(2) +#define G_RM_AA_OPA_TERR RM_AA_OPA_TERR(1) +#define G_RM_AA_OPA_TERR2 RM_AA_OPA_TERR(2) +#define G_RM_AA_TEX_TERR RM_AA_TEX_TERR(1) +#define G_RM_AA_TEX_TERR2 RM_AA_TEX_TERR(2) +#define G_RM_AA_SUB_TERR RM_AA_SUB_TERR(1) +#define G_RM_AA_SUB_TERR2 RM_AA_SUB_TERR(2) + +#define G_RM_RA_OPA_SURF RM_RA_OPA_SURF(1) +#define G_RM_RA_OPA_SURF2 RM_RA_OPA_SURF(2) + +#define G_RM_ZB_OPA_SURF RM_ZB_OPA_SURF(1) +#define G_RM_ZB_OPA_SURF2 RM_ZB_OPA_SURF(2) +#define G_RM_ZB_XLU_SURF RM_ZB_XLU_SURF(1) +#define G_RM_ZB_XLU_SURF2 RM_ZB_XLU_SURF(2) +#define G_RM_ZB_OPA_DECAL RM_ZB_OPA_DECAL(1) +#define G_RM_ZB_OPA_DECAL2 RM_ZB_OPA_DECAL(2) +#define G_RM_ZB_XLU_DECAL RM_ZB_XLU_DECAL(1) +#define G_RM_ZB_XLU_DECAL2 RM_ZB_XLU_DECAL(2) +#define G_RM_ZB_CLD_SURF RM_ZB_CLD_SURF(1) +#define G_RM_ZB_CLD_SURF2 RM_ZB_CLD_SURF(2) +#define G_RM_ZB_OVL_SURF RM_ZB_OVL_SURF(1) +#define G_RM_ZB_OVL_SURF2 RM_ZB_OVL_SURF(2) +#define G_RM_ZB_PCL_SURF RM_ZB_PCL_SURF(1) +#define G_RM_ZB_PCL_SURF2 RM_ZB_PCL_SURF(2) + +#define G_RM_OPA_SURF RM_OPA_SURF(1) +#define G_RM_OPA_SURF2 RM_OPA_SURF(2) +#define G_RM_XLU_SURF RM_XLU_SURF(1) +#define G_RM_XLU_SURF2 RM_XLU_SURF(2) +#define G_RM_CLD_SURF RM_CLD_SURF(1) +#define G_RM_CLD_SURF2 RM_CLD_SURF(2) +#define G_RM_TEX_EDGE RM_TEX_EDGE(1) +#define G_RM_TEX_EDGE2 RM_TEX_EDGE(2) +#define G_RM_PCL_SURF RM_PCL_SURF(1) +#define G_RM_PCL_SURF2 RM_PCL_SURF(2) +#define G_RM_ADD RM_ADD(1) +#define G_RM_ADD2 RM_ADD(2) +#define G_RM_NOOP RM_NOOP(1) +#define G_RM_NOOP2 RM_NOOP(2) +#define G_RM_VISCVG RM_VISCVG(1) +#define G_RM_VISCVG2 RM_VISCVG(2) +#define G_RM_OPA_CI RM_OPA_CI(1) +#define G_RM_OPA_CI2 RM_OPA_CI(2) + + +#define G_RM_FOG_SHADE_A GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA) +#define G_RM_FOG_PRIM_A GBL_c1(G_BL_CLR_FOG, G_BL_A_FOG, G_BL_CLR_IN, G_BL_1MA) +#define G_RM_PASS GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +/* + * G_SETCONVERT: K0-5 + */ +#define G_CV_K0 175 +#define G_CV_K1 -43 +#define G_CV_K2 -89 +#define G_CV_K3 222 +#define G_CV_K4 114 +#define G_CV_K5 42 + +/* + * G_SETSCISSOR: interlace mode + */ +#define G_SC_NON_INTERLACE 0 +#define G_SC_ODD_INTERLACE 3 +#define G_SC_EVEN_INTERLACE 2 + +/* flags to inhibit pushing of the display list (on branch) */ +#define G_DL_PUSH 0x00 +#define G_DL_NOPUSH 0x01 + +/* + * BEGIN C-specific section: (typedef's) + */ +#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) + +/* + * Data Structures + * + * NOTE: + * The DMA transfer hardware requires 64-bit aligned, 64-bit multiple- + * sized transfers. This important hardware optimization is unfortunately + * reflected in the programming interface, with some structures + * padded and alignment enforced. + * + * Since structures are aligned to the boundary of the "worst-case" + * element, we can't depend on the C compiler to align things + * properly. + * + * 64-bit structure alignment is enforced by wrapping structures with + * unions that contain a dummy "long long int". Why this works is + * explained in the ANSI C Spec, or on page 186 of the second edition + * of K&R, "The C Programming Language". + * + * The price we pay for this is a little awkwardness referencing the + * structures through the union. There is no memory penalty, since + * all the structures are at least 64-bits the dummy alignment field + * does not increase the size of the union. + * + * Static initialization of these union structures works because + * the ANSI C spec states that static initialization for unions + * works by using the first union element. We put the dummy alignment + * field last for this reason. + * + * (it's possible a newer 64-bit compiler from MIPS might make this + * easier with a flag, but we can't wait for it...) + * + */ + +/* + * Vertex (set up for use with colors) + */ typedef struct { - /* 0x0 */ short ob[3]; - /* 0x6 */ unsigned short flag; - /* 0x8 */ short tc[2]; - /* 0xC */ unsigned char cn[4]; + short ob[3]; /* x, y, z */ + unsigned short flag; + short tc[2]; /* texture coord */ + unsigned char cn[4]; /* color & alpha */ } Vtx_t; - +/* + * Vertex (set up for use with normals) + */ typedef struct { - /* 0x0 */ short ob[3]; - /* 0x6 */ unsigned short flag; - /* 0x8 */ short tc[2]; - /* 0xC */ signed char n[3]; - /* 0xF */ unsigned char a; + short ob[3]; /* x, y, z */ + unsigned short flag; + short tc[2]; /* texture coord */ + signed char n[3]; /* normal */ + unsigned char a; /* alpha */ } Vtx_tn; - typedef union { - /* 0x0 */ Vtx_t v; - /* 0x0 */ Vtx_tn n; - /* 0x0 */ long long force_structure_alignment; + Vtx_t v; /* Use this one for colors */ + Vtx_tn n; /* Use this one for normals */ + long long int force_structure_alignment; } Vtx; +/* + * Sprite structure + */ typedef struct { - /* 0x0 */ unsigned char flag; - /* 0x1 */ unsigned char v[3]; + void *SourceImagePointer; + void *TlutPointer; + short Stride; + short SubImageWidth; + short SubImageHeight; + char SourceImageType; + char SourceImageBitSize; + short SourceImageOffsetS; + short SourceImageOffsetT; + /* 20 bytes for above */ + + /* padding to bring structure size to 64 bit allignment */ + char dummy[4]; + +} uSprite_t; + +typedef union { + uSprite_t s; + + /* Need to make sure this is 64 bit aligned */ + long long int force_structure_allignment[3]; +} uSprite; + +/* + * Triangle face + */ +typedef struct { + unsigned char flag; + unsigned char v[3]; } Tri; -typedef long Mtx_t[4][4]; - - -typedef union { - /* 0x0 */ Mtx_t m; - /* 0x0 */ long long force_structure_alignment; -} Mtx; +/* + * Viewport + */ +/* + * + * This magic value is the maximum INTEGER z-range of the hardware + * (there are also 16-bits of fraction, which are introduced during + * any transformations). This is not just a good idea, it's the law. + * Feeding the hardware eventual z-coordinates (after any transforms + * or scaling) bigger than this, will not work. + * + * This number is DIFFERENT than G_MAXFBZ, which is the maximum value + * you want to use to initialize the z-buffer. + * + * The reason these are different is mildly interesting, but too long + * to explain here. It is basically the result of optimizations in the + * hardware. A more generic API might hide this detail from the users, + * but we don't have the ucode to do that... + * + */ +#define G_MAXZ 0x03ff /* 10 bits of integer screen-Z precision */ +/* + * The viewport structure elements have 2 bits of fraction, necessary + * to accomodate the sub-pixel positioning scaling for the hardware. + * This can also be exploited to handle odd-sized viewports. + * + * Accounting for these fractional bits, using the default projection + * and viewing matrices, the viewport structure is initialized thusly: + * + * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, G_MAXZ, 0, + * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, 0, 0, + */ typedef struct { - /* 0x0 */ short vscale[4]; - /* 0x8 */ short vtrans[4]; + short vscale[4]; /* scale, 2 bits fraction */ + short vtrans[4]; /* translate, 2 bits fraction */ + /* both the above arrays are padded to 64-bit boundary */ } Vp_t; - typedef union { - /* 0x0 */ Vp_t vp; - /* 0x0 */ long long force_structure_alignment; + Vp_t vp; + long long int force_structure_alignment; } Vp; +/* + * MOVEMEM indices + * + * Each of these indexes an entry in a dmem table + * which points to a 1-4 word block of dmem in + * which to store a 1-4 word DMA. + * + */ +#ifdef F3DEX_GBI_2 +/* 0,4 are reserved by G_MTX */ +# define G_MV_MMTX 2 +# define G_MV_PMTX 6 +# define G_MV_VIEWPORT 8 +# define G_MV_LIGHT 10 +# define G_MV_POINT 12 +# define G_MV_MATRIX 14 /* NOTE: this is in moveword table */ +# define G_MVO_LOOKATX (0*24) +# define G_MVO_LOOKATY (1*24) +# define G_MVO_L0 (2*24) +# define G_MVO_L1 (3*24) +# define G_MVO_L2 (4*24) +# define G_MVO_L3 (5*24) +# define G_MVO_L4 (6*24) +# define G_MVO_L5 (7*24) +# define G_MVO_L6 (8*24) +# define G_MVO_L7 (9*24) +#else /* F3DEX_GBI_2 */ +# define G_MV_VIEWPORT 0x80 +# define G_MV_LOOKATY 0x82 +# define G_MV_LOOKATX 0x84 +# define G_MV_L0 0x86 +# define G_MV_L1 0x88 +# define G_MV_L2 0x8a +# define G_MV_L3 0x8c +# define G_MV_L4 0x8e +# define G_MV_L5 0x90 +# define G_MV_L6 0x92 +# define G_MV_L7 0x94 +# define G_MV_TXTATT 0x96 +# define G_MV_MATRIX_1 0x9e /* NOTE: this is in moveword table */ +# define G_MV_MATRIX_2 0x98 +# define G_MV_MATRIX_3 0x9a +# define G_MV_MATRIX_4 0x9c +#endif /* F3DEX_GBI_2 */ + +/* + * MOVEWORD indices + * + * Each of these indexes an entry in a dmem table + * which points to a word in dmem in dmem where + * an immediate word will be stored. + * + */ +#define G_MW_MATRIX 0x00 /* NOTE: also used by movemem */ +#define G_MW_NUMLIGHT 0x02 +#define G_MW_CLIP 0x04 +#define G_MW_SEGMENT 0x06 +#define G_MW_FOG 0x08 +#define G_MW_LIGHTCOL 0x0a +#ifdef F3DEX_GBI_2 +# define G_MW_FORCEMTX 0x0c +#else /* F3DEX_GBI_2 */ +# define G_MW_POINTS 0x0c +#endif /* F3DEX_GBI_2 */ +#define G_MW_PERSPNORM 0x0e + +/* + * These are offsets from the address in the dmem table + */ +#define G_MWO_NUMLIGHT 0x00 +#define G_MWO_CLIP_RNX 0x04 +#define G_MWO_CLIP_RNY 0x0c +#define G_MWO_CLIP_RPX 0x14 +#define G_MWO_CLIP_RPY 0x1c +#define G_MWO_SEGMENT_0 0x00 +#define G_MWO_SEGMENT_1 0x01 +#define G_MWO_SEGMENT_2 0x02 +#define G_MWO_SEGMENT_3 0x03 +#define G_MWO_SEGMENT_4 0x04 +#define G_MWO_SEGMENT_5 0x05 +#define G_MWO_SEGMENT_6 0x06 +#define G_MWO_SEGMENT_7 0x07 +#define G_MWO_SEGMENT_8 0x08 +#define G_MWO_SEGMENT_9 0x09 +#define G_MWO_SEGMENT_A 0x0a +#define G_MWO_SEGMENT_B 0x0b +#define G_MWO_SEGMENT_C 0x0c +#define G_MWO_SEGMENT_D 0x0d +#define G_MWO_SEGMENT_E 0x0e +#define G_MWO_SEGMENT_F 0x0f +#define G_MWO_FOG 0x00 +#define G_MWO_aLIGHT_1 0x00 +#define G_MWO_bLIGHT_1 0x04 +#ifdef F3DEX_GBI_2 +#define G_MWO_aLIGHT_2 0x18 +#define G_MWO_bLIGHT_2 0x1c +#define G_MWO_aLIGHT_3 0x30 +#define G_MWO_bLIGHT_3 0x34 +#define G_MWO_aLIGHT_4 0x48 +#define G_MWO_bLIGHT_4 0x4c +#define G_MWO_aLIGHT_5 0x60 +#define G_MWO_bLIGHT_5 0x64 +#define G_MWO_aLIGHT_6 0x78 +#define G_MWO_bLIGHT_6 0x7c +#define G_MWO_aLIGHT_7 0x90 +#define G_MWO_bLIGHT_7 0x94 +#define G_MWO_aLIGHT_8 0xa8 +#define G_MWO_bLIGHT_8 0xac +#else +#define G_MWO_aLIGHT_2 0x20 +#define G_MWO_bLIGHT_2 0x24 +#define G_MWO_aLIGHT_3 0x40 +#define G_MWO_bLIGHT_3 0x44 +#define G_MWO_aLIGHT_4 0x60 +#define G_MWO_bLIGHT_4 0x64 +#define G_MWO_aLIGHT_5 0x80 +#define G_MWO_bLIGHT_5 0x84 +#define G_MWO_aLIGHT_6 0xa0 +#define G_MWO_bLIGHT_6 0xa4 +#define G_MWO_aLIGHT_7 0xc0 +#define G_MWO_bLIGHT_7 0xc4 +#define G_MWO_aLIGHT_8 0xe0 +#define G_MWO_bLIGHT_8 0xe4 +#endif +#define G_MWO_MATRIX_XX_XY_I 0x00 +#define G_MWO_MATRIX_XZ_XW_I 0x04 +#define G_MWO_MATRIX_YX_YY_I 0x08 +#define G_MWO_MATRIX_YZ_YW_I 0x0c +#define G_MWO_MATRIX_ZX_ZY_I 0x10 +#define G_MWO_MATRIX_ZZ_ZW_I 0x14 +#define G_MWO_MATRIX_WX_WY_I 0x18 +#define G_MWO_MATRIX_WZ_WW_I 0x1c +#define G_MWO_MATRIX_XX_XY_F 0x20 +#define G_MWO_MATRIX_XZ_XW_F 0x24 +#define G_MWO_MATRIX_YX_YY_F 0x28 +#define G_MWO_MATRIX_YZ_YW_F 0x2c +#define G_MWO_MATRIX_ZX_ZY_F 0x30 +#define G_MWO_MATRIX_ZZ_ZW_F 0x34 +#define G_MWO_MATRIX_WX_WY_F 0x38 +#define G_MWO_MATRIX_WZ_WW_F 0x3c +#define G_MWO_POINT_RGBA 0x10 +#define G_MWO_POINT_ST 0x14 +#define G_MWO_POINT_XYSCREEN 0x18 +#define G_MWO_POINT_ZSCREEN 0x1c + +/* + * Light structure. + * + * Note: only directional (infinite) lights are currently supported. + * + * Note: the weird order is for the DMEM alignment benefit of + * the microcode. + * + */ typedef struct { - /* 0x0 */ unsigned char col[3]; - /* 0x3 */ unsigned char pad1; - /* 0x4 */ unsigned char colc[3]; - /* 0x7 */ unsigned char pad2; - /* 0x8 */ signed char dir[3]; - /* 0xB */ unsigned char pad3; + unsigned char col[3]; /* diffuse light value (rgba) */ + char pad1; + unsigned char colc[3]; /* copy of diffuse light value (rgba) */ + char pad2; + signed char dir[3]; /* direction of light (normalized) */ + char pad3; } Light_t; - typedef struct { - /* 0x0 */ unsigned char col[3]; - /* 0x3 */ unsigned char pad1; - /* 0x4 */ unsigned char colc[3]; - /* 0x7 */ unsigned char pad2; + unsigned char col[3]; /* ambient light value (rgba) */ + char pad1; + unsigned char colc[3]; /* copy of ambient light value (rgba) */ + char pad2; } Ambient_t; - typedef struct { - /* 0x0 */ int x1; - /* 0x4 */ int y1; - /* 0x8 */ int x2; - /* 0xC */ int y2; + int x1,y1,x2,y2; /* texture offsets for highlight 1/2 */ } Hilite_t; - typedef union { - /* 0x0 */ Light_t l; - /* 0x0 */ long long force_structure_alignment[2]; + Light_t l; + long long int force_structure_alignment[2]; } Light; - typedef union { - /* 0x0 */ Ambient_t l; - /* 0x0 */ long long force_structure_alignment[1]; + Ambient_t l; + long long int force_structure_alignment[1]; } Ambient; - typedef struct { - /* 0x0 */ Ambient a; - /* 0x8 */ Light l[7]; + Ambient a; + Light l[7]; } Lightsn; - typedef struct { - /* 0x0 */ Ambient a; - /* 0x8 */ Light l[1]; + Ambient a; + Light l[1]; } Lights0; - typedef struct { - /* 0x0 */ Ambient a; - /* 0x8 */ Light l[1]; + Ambient a; + Light l[1]; } Lights1; - typedef struct { - /* 0x0 */ Ambient a; - /* 0x8 */ Light l[2]; + Ambient a; + Light l[2]; } Lights2; - typedef struct { - /* 0x0 */ Ambient a; - /* 0x8 */ Light l[3]; + Ambient a; + Light l[3]; } Lights3; - typedef struct { - /* 0x0 */ Ambient a; - /* 0x8 */ Light l[4]; + Ambient a; + Light l[4]; } Lights4; - typedef struct { - /* 0x0 */ Ambient a; - /* 0x8 */ Light l[5]; + Ambient a; + Light l[5]; } Lights5; - typedef struct { - /* 0x0 */ Ambient a; - /* 0x8 */ Light l[6]; + Ambient a; + Light l[6]; } Lights6; - typedef struct { - /* 0x0 */ Ambient a; - /* 0x8 */ Light l[7]; + Ambient a; + Light l[7]; } Lights7; - typedef struct { - /* 0x0 */ Light l[2]; + Light l[2]; } LookAt; - typedef union { - /* 0x0 */ Hilite_t h; - /* 0x0 */ long force_structure_alignment[4]; + Hilite_t h; + long int force_structure_alignment[4]; } Hilite; +#define gdSPDefLights0(ar,ag,ab) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ { 0, 0, 0},0,{ 0, 0, 0},0,{ 0, 0, 0},0}}} } +#define gdSPDefLights1(ar,ag,ab,r1,g1,b1,x1,y1,z1) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}} } +#define gdSPDefLights2(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}} } +#define gdSPDefLights3(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}} } +#define gdSPDefLights4(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ + {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}} } +#define gdSPDefLights5(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4,r5,g5,b5,x5,y5,z5) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ + {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}, \ + {{ {r5,g5,b5},0,{r5,g5,b5},0,{x5,y5,z5},0}}} } + +#define gdSPDefLights6(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4,r5,g5,b5,x5,y5,z5,r6,g6,b6,x6,y6,z6) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ + {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}, \ + {{ {r5,g5,b5},0,{r5,g5,b5},0,{x5,y5,z5},0}}, \ + {{ {r6,g6,b6},0,{r6,g6,b6},0,{x6,y6,z6},0}}} } + + +#define gdSPDefLights7(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4,r5,g5,b5,x5,y5,z5,r6,g6,b6,x6,y6,z6,r7,g7,b7,x7,y7,z7) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ + {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}, \ + {{ {r5,g5,b5},0,{r5,g5,b5},0,{x5,y5,z5},0}}, \ + {{ {r6,g6,b6},0,{r6,g6,b6},0,{x6,y6,z6},0}}, \ + {{ {r7,g7,b7},0,{r7,g7,b7},0,{x7,y7,z7},0}}} } + + +#define gdSPDefLookAt(rightx,righty,rightz,upx,upy,upz) \ + { {{ {{0,0,0},0,{0,0,0},0,{rightx,righty,rightz},0}}, \ + { {{0,0x80,0},0,{0,0x80,0},0,{upx,upy,upz},0}}} } + +/* + * Graphics DMA Packet + */ typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ unsigned int par : 8; - /* 0x2 */ unsigned int len : 16; - /* 0x4 */ unsigned int addr; + int cmd:8; + unsigned int par:8; + unsigned int len:16; + unsigned int addr; } Gdma; - +/* + * Graphics Immediate Mode Packet types + */ typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ int pad : 24; - /* 0x4 */ Tri tri; + int cmd:8; + int pad:24; + Tri tri; } Gtri; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ int pad1 : 24; - /* 0x4 */ int pad2 : 24; - /* 0x7 */ unsigned char param : 8; + int cmd:8; + int pad1:24; + int pad2:24; + unsigned char param:8; } Gpopmtx; - +/* + * typedef struct { + * int cmd:8; + * int pad0:24; + * int pad1:4; + * int number:4; + * int base:24; + * } Gsegment; + */ typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ int pad0 : 8; - /* 0x2 */ int mw_index : 8; - /* 0x3 */ int number : 8; - /* 0x4 */ int pad1 : 8; - /* 0x5 */ int base : 24; + int cmd:8; + int pad0:8; + int mw_index:8; + int number:8; + int pad1:8; + int base:24; } Gsegment; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ int pad0 : 8; - /* 0x2 */ int sft : 8; - /* 0x3 */ int len : 8; - /* 0x4 */ unsigned int data : 32; + int cmd:8; + int pad0:8; + int sft:8; + int len:8; + unsigned int data:32; } GsetothermodeL; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ int pad0 : 8; - /* 0x2 */ int sft : 8; - /* 0x3 */ int len : 8; - /* 0x4 */ unsigned int data : 32; + int cmd:8; + int pad0:8; + int sft:8; + int len:8; + unsigned int data:32; } GsetothermodeH; - typedef struct { - /* 0x0 */ unsigned char cmd; - /* 0x1 */ unsigned char lodscale; - /* 0x2 */ unsigned char tile; - /* 0x3 */ unsigned char on; - /* 0x4 */ unsigned short s; - /* 0x6 */ unsigned short t; + unsigned char cmd; + unsigned char lodscale; + unsigned char tile; + unsigned char on; + unsigned short s; + unsigned short t; } Gtexture; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ int pad : 24; - /* 0x4 */ Tri line; + int cmd:8; + int pad:24; + Tri line; } Gline3D; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ int pad1 : 24; - /* 0x4 */ short pad2; - /* 0x6 */ short scale; + int cmd:8; + int pad1:24; + short int pad2; + short int scale; } Gperspnorm; +/* + * RDP Packet types + */ typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ unsigned int fmt : 3; - /* 0x1 */ unsigned int siz : 2; - /* 0x1 */ unsigned int pad : 7; - /* 0x2 */ unsigned int wd : 12; - /* 0x4 */ unsigned int dram; + int cmd:8; + unsigned int fmt:3; + unsigned int siz:2; + unsigned int pad:7; + unsigned int wd:12; /* really only 10 bits, extra */ + unsigned int dram; /* to account for 1024 */ } Gsetimg; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ unsigned int muxs0 : 24; - /* 0x4 */ unsigned int muxs1 : 32; + int cmd:8; + unsigned int muxs0:24; + unsigned int muxs1:32; } Gsetcombine; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ unsigned char pad; - /* 0x2 */ unsigned char prim_min_level; - /* 0x3 */ unsigned char prim_level; - /* 0x4 */ unsigned long color; + int cmd:8; + unsigned char pad; + unsigned char prim_min_level; + unsigned char prim_level; + unsigned long color; } Gsetcolor; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ int x0 : 10; - /* 0x2 */ int x0frac : 2; - /* 0x2 */ int y0 : 10; - /* 0x3 */ int y0frac : 2; - /* 0x4 */ unsigned int pad : 8; - /* 0x5 */ int x1 : 10; - /* 0x6 */ int x1frac : 2; - /* 0x6 */ int y1 : 10; - /* 0x7 */ int y1frac : 2; + int cmd:8; + int x0:10; + int x0frac:2; + int y0:10; + int y0frac:2; + unsigned int pad:8; + int x1:10; + int x1frac:2; + int y1:10; + int y1frac:2; } Gfillrect; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ unsigned int fmt : 3; - /* 0x1 */ unsigned int siz : 2; - /* 0x1 */ unsigned int pad0 : 1; - /* 0x1 */ unsigned int line : 9; - /* 0x2 */ unsigned int tmem : 9; - /* 0x4 */ unsigned int pad1 : 5; - /* 0x4 */ unsigned int tile : 3; - /* 0x5 */ unsigned int palette : 4; - /* 0x5 */ unsigned int ct : 1; - /* 0x5 */ unsigned int mt : 1; - /* 0x5 */ unsigned int maskt : 4; - /* 0x6 */ unsigned int shiftt : 4; - /* 0x6 */ unsigned int cs : 1; - /* 0x6 */ unsigned int ms : 1; - /* 0x7 */ unsigned int masks : 4; - /* 0x7 */ unsigned int shifts : 4; + int cmd:8; + unsigned int fmt:3; + unsigned int siz:2; + unsigned int pad0:1; + unsigned int line:9; + unsigned int tmem:9; + unsigned int pad1:5; + unsigned int tile:3; + unsigned int palette:4; + unsigned int ct:1; + unsigned int mt:1; + unsigned int maskt:4; + unsigned int shiftt:4; + unsigned int cs:1; + unsigned int ms:1; + unsigned int masks:4; + unsigned int shifts:4; } Gsettile; - typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ unsigned int sl : 12; - /* 0x2 */ unsigned int tl : 12; - /* 0x4 */ int pad : 5; - /* 0x4 */ unsigned int tile : 3; - /* 0x5 */ unsigned int sh : 12; - /* 0x6 */ unsigned int th : 12; + int cmd:8; + unsigned int sl:12; + unsigned int tl:12; + int pad:5; + unsigned int tile:3; + unsigned int sh:12; + unsigned int th:12; } Gloadtile; -typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ unsigned int sl : 12; - /* 0x2 */ unsigned int tl : 12; - /* 0x4 */ int pad : 5; - /* 0x4 */ unsigned int tile : 3; - /* 0x5 */ unsigned int sh : 12; - /* 0x6 */ unsigned int th : 12; -} Gloadblock; +typedef Gloadtile Gloadblock; + +typedef Gloadtile Gsettilesize; + +typedef Gloadtile Gloadtlut; typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ unsigned int sl : 12; - /* 0x2 */ unsigned int tl : 12; - /* 0x4 */ int pad : 5; - /* 0x4 */ unsigned int tile : 3; - /* 0x5 */ unsigned int sh : 12; - /* 0x6 */ unsigned int th : 12; -} Gsettilesize; - -typedef struct { - /* 0x0 */ int cmd : 8; - /* 0x1 */ unsigned int sl : 12; - /* 0x2 */ unsigned int tl : 12; - /* 0x4 */ int pad : 5; - /* 0x4 */ unsigned int tile : 3; - /* 0x5 */ unsigned int sh : 12; - /* 0x6 */ unsigned int th : 12; -} Gloadtlut; - - -typedef struct { - /* 0x0 */ unsigned int cmd : 8; - /* 0x1 */ unsigned int xl : 12; - /* 0x2 */ unsigned int yl : 12; - /* 0x4 */ unsigned int pad1 : 5; - /* 0x4 */ unsigned int tile : 3; - /* 0x5 */ unsigned int xh : 12; - /* 0x6 */ unsigned int yh : 12; - /* 0x8 */ unsigned int s : 16; - /* 0xA */ unsigned int t : 16; - /* 0xC */ unsigned int dsdx : 16; - /* 0xE */ unsigned int dtdy : 16; + unsigned int cmd:8; /* command */ + unsigned int xl:12; /* X coordinate of upper left */ + unsigned int yl:12; /* Y coordinate of upper left */ + unsigned int pad1:5; /* Padding */ + unsigned int tile:3; /* Tile descriptor index */ + unsigned int xh:12; /* X coordinate of lower right */ + unsigned int yh:12; /* Y coordinate of lower right */ + unsigned int s:16; /* S texture coord at top left */ + unsigned int t:16; /* T texture coord at top left */ + unsigned int dsdx:16;/* Change in S per change in X */ + unsigned int dtdy:16;/* Change in T per change in Y */ } Gtexrect; +#define MakeTexRect(xh,yh,flip,tile,xl,yl,s,t,dsdx,dtdy) \ + G_TEXRECT, xh, yh, 0, flip, 0, tile, xl, yl, s, t, dsdx, dtdy +/* + * Textured rectangles are 128 bits not 64 bits + */ typedef struct { - /* 0x0 */ unsigned long w0; - /* 0x4 */ unsigned long w1; - /* 0x8 */ unsigned long w2; - /* 0xC */ unsigned long w3; + unsigned long w0; + unsigned long w1; + unsigned long w2; + unsigned long w3; } TexRect; - +/* + * Generic Gfx Packet + */ typedef struct { - /* 0x0 */ unsigned int w0; - /* 0x4 */ unsigned int w1; + unsigned int w0; + unsigned int w1; } Gwords; - +/* + * This union is the fundamental type of the display list. + * It is, by law, exactly 64 bits in size. + */ typedef union { - /* 0x0 */ Gwords words; - /* 0x0 */ Gdma dma; - /* 0x0 */ Gtri tri; - /* 0x0 */ Gline3D line; - /* 0x0 */ Gpopmtx popmtx; - /* 0x0 */ Gsegment segment; - /* 0x0 */ GsetothermodeH setothermodeH; - /* 0x0 */ GsetothermodeL setothermodeL; - /* 0x0 */ Gtexture texture; - /* 0x0 */ Gperspnorm perspnorm; - /* 0x0 */ Gsetimg setimg; - /* 0x0 */ Gsetcombine setcombine; - /* 0x0 */ Gsetcolor setcolor; - /* 0x0 */ Gfillrect fillrect; - /* 0x0 */ Gsettile settile; - /* 0x0 */ Gloadtile loadtile; - /* 0x0 */ Gloadtile settilesize; - /* 0x0 */ Gloadtile loadtlut; - /* 0x0 */ long long force_structure_alignment; + Gwords words; + Gdma dma; + Gtri tri; + Gline3D line; + Gpopmtx popmtx; + Gsegment segment; + GsetothermodeH setothermodeH; + GsetothermodeL setothermodeL; + Gtexture texture; + Gperspnorm perspnorm; + Gsetimg setimg; + Gsetcombine setcombine; + Gsetcolor setcolor; + Gfillrect fillrect; /* use for setscissor also */ + Gsettile settile; + Gloadtile loadtile; /* use for loadblock also, th is dxt */ + Gsettilesize settilesize; + Gloadtlut loadtlut; + long long int force_structure_alignment; } Gfx; +/* + * Macros to assemble the graphics display list + */ + +/* + * DMA macros + */ +#define gDma0p(pkt, c, s, l) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24); \ + _g->words.w1 = (unsigned int)(s); \ +} + +#define gsDma0p(c, s, l) \ +{ \ + _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24), (unsigned int)(s) \ +} + +#define gDma1p(pkt, c, s, l, p) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \ + _SHIFTL((l), 0, 16)); \ + _g->words.w1 = (unsigned int)(s); \ +} + +#define gsDma1p(c, s, l, p) \ +{ \ + (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \ + _SHIFTL((l), 0, 16)), \ + (unsigned int)(s) \ +} + +#define gDma2p(pkt, c, adrs, len, idx, ofs) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \ + _SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)); \ + _g->words.w1 = (unsigned int)(adrs); \ +} +#define gsDma2p(c, adrs, len, idx, ofs) \ +{ \ + (_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \ + _SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)), \ + (unsigned int)(adrs) \ +} + +#define gSPNoOp(pkt) gDma0p(pkt, G_SPNOOP, 0, 0) +#define gsSPNoOp() gsDma0p(G_SPNOOP, 0, 0) + +#ifdef F3DEX_GBI_2 +# define gSPMatrix(pkt, m, p) \ + _DW(gDma2p((pkt),G_MTX,(m),sizeof(Mtx),(p)^G_MTX_PUSH,0)) +# define gsSPMatrix(m, p) \ + gsDma2p( G_MTX,(m),sizeof(Mtx),(p)^G_MTX_PUSH,0) +#else /* F3DEX_GBI_2 */ +# define gSPMatrix(pkt, m, p) gDma1p(pkt, G_MTX, m, sizeof(Mtx), p) +# define gsSPMatrix(m, p) gsDma1p(G_MTX, m, sizeof(Mtx), p) +#endif /* F3DEX_GBI_2 */ + +#if defined(F3DEX_GBI_2) +/* + * F3DEX_GBI_2: G_VTX GBI format was changed. + * + * +--------+----+---+---+----+------+-+ + * G_VTX | cmd:8 |0000| n:8 |0000|v0+n:7|0| + * +-+---+--+----+---+---+----+------+-+ + * | |seg| address | + * +-+---+-----------------------------+ + */ +# define gSPVertex(pkt, v, n, v0) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = \ + _SHIFTL(G_VTX,24,8)|_SHIFTL((n),12,8)|_SHIFTL((v0)+(n),1,7); \ + _g->words.w1 = (unsigned int)(v); \ +} +# define gsSPVertex(v, n, v0) \ +{ \ + (_SHIFTL(G_VTX,24,8)|_SHIFTL((n),12,8)|_SHIFTL((v0)+(n),1,7)), \ + (unsigned int)(v) \ +} +#elif (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +/* + * F3DEX_GBI: G_VTX GBI format was changed to support 64 vertice. + * + * +--------+--------+------+----------+ + * G_VTX | cmd:8 | v0:8 | n:6 |length:10 | + * +-+---+--+--------+------+----------+ + * | |seg| address | + * +-+---+-----------------------------+ + */ +# define gSPVertex(pkt, v, n, v0) \ + gDma1p((pkt),G_VTX,(v),((n)<<10)|(sizeof(Vtx)*(n)-1),(v0)*2) +# define gsSPVertex(v, n, v0) \ + gsDma1p(G_VTX,(v),((n)<<10)|(sizeof(Vtx)*(n)-1),(v0)*2) +#else +# define gSPVertex(pkt, v, n, v0) \ + gDma1p(pkt, G_VTX, v, sizeof(Vtx)*(n),((n)-1)<<4|(v0)) +# define gsSPVertex(v, n, v0) \ + gsDma1p(G_VTX, v, sizeof(Vtx)*(n), ((n)-1)<<4|(v0)) +#endif + + +#ifdef F3DEX_GBI_2 +# define gSPViewport(pkt, v) \ + gDma2p((pkt), G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0) +# define gsSPViewport(v) \ + gsDma2p( G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0) +#else /* F3DEX_GBI_2 */ +# define gSPViewport(pkt,v) \ + gDma1p((pkt), G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT) +# define gsSPViewport(v) \ + gsDma1p( G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT) +#endif /* F3DEX_GBI_2 */ + +#define gSPDisplayList(pkt,dl) _DW(gDma1p(pkt,G_DL,dl,0,G_DL_PUSH)) +#define gsSPDisplayList( dl) gsDma1p( G_DL,dl,0,G_DL_PUSH) + +#define gSPBranchList(pkt,dl) gDma1p(pkt,G_DL,dl,0,G_DL_NOPUSH) +#define gsSPBranchList( dl) gsDma1p( G_DL,dl,0,G_DL_NOPUSH) + +#define gSPSprite2DBase(pkt, s) gDma1p(pkt, G_SPRITE2D_BASE, s, sizeof(uSprite), 0) +#define gsSPSprite2DBase(s) gsDma1p(G_SPRITE2D_BASE, s, sizeof(uSprite), 0) + +/* + * RSP short command (no DMA required) macros + */ +#define gImmp0(pkt, c) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ +} + +#define gsImmp0(c) \ +{ \ + _SHIFTL((c), 24, 8) \ +} + +#define gImmp1(pkt, c, p0) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ + _g->words.w1 = (unsigned int)(p0); \ +} + +#define gsImmp1(c, p0) \ +{ \ + _SHIFTL((c), 24, 8), (unsigned int)(p0) \ +} + +#define gImmp2(pkt, c, p0, p1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ + _g->words.w1 = _SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8); \ +} + +#define gsImmp2(c, p0, p1) \ +{ \ + _SHIFTL((c), 24, 8), _SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8)\ +} + +#define gImmp3(pkt, c, p0, p1, p2) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ + _g->words.w1 = (_SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8) | \ + _SHIFTL((p2), 0, 8)); \ +} + +#define gsImmp3(c, p0, p1, p2) \ +{ \ + _SHIFTL((c), 24, 8), (_SHIFTL((p0), 16, 16) | \ + _SHIFTL((p1), 8, 8) | _SHIFTL((p2), 0, 8))\ +} + +#define gImmp21(pkt, c, p0, p1, dat) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | \ + _SHIFTL((p1), 0, 8)); \ + _g->words.w1 = (unsigned int) (dat); \ +} + +#define gsImmp21(c, p0, p1, dat) \ +{ \ + _SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | _SHIFTL((p1), 0, 8),\ + (unsigned int) (dat) \ +} + +#ifdef F3DEX_GBI_2 +#define gMoveWd(pkt, index, offset, data) \ + gDma1p((pkt), G_MOVEWORD, data, offset, index) +#define gsMoveWd( index, offset, data) \ + gsDma1p( G_MOVEWORD, data, offset, index) +#else /* F3DEX_GBI_2 */ +#define gMoveWd(pkt, index, offset, data) \ + gImmp21((pkt), G_MOVEWORD, offset, index, data) +#define gsMoveWd( index, offset, data) \ + gsImmp21( G_MOVEWORD, offset, index, data) +#endif /* F3DEX_GBI_2 */ + +/* Sprite immediate macros, there is also a sprite dma macro above */ + +#define gSPSprite2DScaleFlip(pkt, sx, sy, fx, fy) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SPRITE2D_SCALEFLIP, 24, 8) | \ + _SHIFTL((fx), 8, 8) | \ + _SHIFTL((fy), 0, 8)); \ + _g->words.w1 = (_SHIFTL((sx), 16, 16) | \ + _SHIFTL((sy), 0, 16)); \ +} + +#define gsSPSprite2DScaleFlip(sx, sy, fx, fy) \ +{ \ + (_SHIFTL(G_SPRITE2D_SCALEFLIP, 24, 8) | \ + _SHIFTL((fx), 8, 8) | \ + _SHIFTL((fy), 0, 8)), \ + (_SHIFTL((sx), 16, 16) | \ + _SHIFTL((sy), 0, 16)) \ +} + +#define gSPSprite2DDraw(pkt, px, py) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SPRITE2D_DRAW, 24, 8)); \ + _g->words.w1 = (_SHIFTL((px), 16, 16) | \ + _SHIFTL((py), 0, 16)); \ +} + +#define gsSPSprite2DDraw(px, py) \ +{ \ + (_SHIFTL(G_SPRITE2D_DRAW, 24, 8)), \ + (_SHIFTL((px), 16, 16) | \ + _SHIFTL((py), 0, 16)) \ +} + + +/* + * Note: the SP1Triangle() and line macros multiply the vertex indices + * by 10, this is an optimization for the microcode. + */ +#if (defined(F3DLP_GBI)||defined(F3DEX_GBI)) +# define __gsSP1Triangle_w1(v0, v1, v2) \ + (_SHIFTL((v0)*2,16,8)|_SHIFTL((v1)*2,8,8)|_SHIFTL((v2)*2,0,8)) +# define __gsSP1Triangle_w1f(v0, v1, v2, flag) \ + (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2): \ + ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v0): \ + __gsSP1Triangle_w1(v2, v0, v1)) +# define __gsSPLine3D_w1(v0, v1, wd) \ + (_SHIFTL((v0)*2,16,8)|_SHIFT((v1)*2,8,8)|_SHIFT((wd),0,8)) +# define __gsSPLine3D_w1f(v0, v1, wd, flag) \ + (((flag) == 0) ? __gsSPLine3D_w1(v0, v1, wd): \ + __gsSPLine3D_w1(v1, v0, wd)) +# define __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag) \ + (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2): \ + ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v3): \ + ((flag) == 2) ? __gsSP1Triangle_w1(v2, v3, v0): \ + __gsSP1Triangle_w1(v3, v0, v1)) +# define __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ + (((flag) == 0) ? __gsSP1Triangle_w1(v0, v2, v3): \ + ((flag) == 1) ? __gsSP1Triangle_w1(v1, v3, v0): \ + ((flag) == 2) ? __gsSP1Triangle_w1(v2, v0, v1): \ + __gsSP1Triangle_w1(v3, v1, v2)) +#else +# define __gsSP1Triangle_w1f(v0, v1, v2, flag) \ + (_SHIFTL((flag), 24,8)|_SHIFTL((v0)*10,16,8)| \ + _SHIFTL((v1)*10, 8,8)|_SHIFTL((v2)*10, 0,8)) +# define __gsSPLine3D_w1f(v0, v1, wd, flag) \ + (_SHIFTL((flag), 24,8)|_SHIFTL((v0)*10,16,8)| \ + _SHIFTL((v1)*10, 8,8)|_SHIFTL((wd), 0,8)) +#endif + +#ifdef F3DEX_GBI_2 +/*** + *** 1 Triangle + ***/ +#define gSP1Triangle(pkt, v0, v1, v2, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_TRI1, 24, 8)| \ + __gsSP1Triangle_w1f(v0, v1, v2, flag); \ + _g->words.w1 = 0; \ +} +#define gsSP1Triangle(v0, v1, v2, flag) \ +{ \ + _SHIFTL(G_TRI1, 24, 8)|__gsSP1Triangle_w1f(v0, v1, v2, flag), \ + 0 \ +} + +/*** + *** Line + ***/ +#define gSPLine3D(pkt, v0, v1, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8)| \ + __gsSPLine3D_w1f(v0, v1, 0, flag); \ + _g->words.w1 = 0; \ +} +#define gsSPLine3D(v0, v1, flag) \ +{ \ + _SHIFTL(G_LINE3D, 24, 8)|__gsSPLine3D_w1f(v0, v1, 0, flag), \ + 0 \ +} + +/*** + *** LineW + ***/ +/* these macros are the same as SPLine3D, except they have an + * additional parameter for width. The width is added to the "minimum" + * thickness, which is 1.5 pixels. The units for width are in + * half-pixel units, so a width of 1 translates to (.5 + 1.5) or + * a 2.0 pixels wide line. + */ +#define gSPLineW3D(pkt, v0, v1, wd, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8)| \ + __gsSPLine3D_w1f(v0, v1, wd, flag); \ + _g->words.w1 = 0; \ +} +#define gsSPLineW3D(v0, v1, wd, flag) \ +{ \ + _SHIFTL(G_LINE3D, 24, 8)|__gsSPLine3D_w1f(v0, v1, wd, flag), \ + 0 \ +} + +/*** + *** 1 Quadrangle + ***/ +#define gSP1Quadrangle(pkt, v0, v1, v2, v3, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_QUAD, 24, 8)| \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)); \ + _g->words.w1 = __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag); \ +} + +#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \ +{ \ + (_SHIFTL(G_QUAD, 24, 8)| \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)), \ + __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ +} +#else /* F3DEX_GBI_2 */ + +/*** + *** 1 Triangle + ***/ +#define gSP1Triangle(pkt, v0, v1, v2, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_TRI1, 24, 8); \ + _g->words.w1 = __gsSP1Triangle_w1f(v0, v1, v2, flag); \ +} +#define gsSP1Triangle(v0, v1, v2, flag) \ +{ \ + _SHIFTL(G_TRI1, 24, 8), \ + __gsSP1Triangle_w1f(v0, v1, v2, flag) \ +} + +/*** + *** Line + ***/ +#define gSPLine3D(pkt, v0, v1, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8); \ + _g->words.w1 = __gsSPLine3D_w1f(v0, v1, 0, flag); \ +} +#define gsSPLine3D(v0, v1, flag) \ +{ \ + _SHIFTL(G_LINE3D, 24, 8), \ + __gsSPLine3D_w1f(v0, v1, 0, flag) \ +} + +/*** + *** LineW + ***/ +/* these macros are the same as SPLine3D, except they have an + * additional parameter for width. The width is added to the "minimum" + * thickness, which is 1.5 pixels. The units for width are in + * half-pixel units, so a width of 1 translates to (.5 + 1.5) or + * a 2.0 pixels wide line. + */ +#define gSPLineW3D(pkt, v0, v1, wd, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8); \ + _g->words.w1 = __gsSPLine3D_w1f(v0, v1, wd, flag); \ +} +#define gsSPLineW3D(v0, v1, wd, flag) \ +{ \ + _SHIFTL(G_LINE3D, 24, 8), \ + __gsSPLine3D_w1f(v0, v1, wd, flag) \ +} + +/*** + *** 1 Quadrangle + ***/ +#define gSP1Quadrangle(pkt, v0, v1, v2, v3, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TRI2, 24, 8)| \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)); \ + _g->words.w1 = __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag); \ +} + +#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \ +{ \ + (_SHIFTL(G_TRI2, 24, 8)| \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)), \ + __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ +} +#endif /* F3DEX_GBI_2 */ + +#if (defined(F3DLP_GBI)||defined(F3DEX_GBI)) +/*** + *** 2 Triangles + ***/ +#define gSP2Triangles(pkt, v00, v01, v02, flag0, v10, v11, v12, flag1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TRI2, 24, 8)| \ + __gsSP1Triangle_w1f(v00, v01, v02, flag0)); \ + _g->words.w1 = __gsSP1Triangle_w1f(v10, v11, v12, flag1); \ +} + +#define gsSP2Triangles(v00, v01, v02, flag0, v10, v11, v12, flag1) \ +{ \ + (_SHIFTL(G_TRI2, 24, 8)| \ + __gsSP1Triangle_w1f(v00, v01, v02, flag0)), \ + __gsSP1Triangle_w1f(v10, v11, v12, flag1) \ +} + +#endif /* F3DEX_GBI/F3DLP_GBI */ + +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +#define gSPCullDisplayList(pkt,vstart,vend) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | \ + _SHIFTL((vstart)*2, 0, 16); \ + _g->words.w1 = _SHIFTL((vend)*2, 0, 16); \ +} + +#define gsSPCullDisplayList(vstart,vend) \ +{ \ + _SHIFTL(G_CULLDL, 24, 8) | _SHIFTL((vstart)*2, 0, 16), \ + _SHIFTL((vend)*2, 0, 16) \ +} + +#else +#define gSPCullDisplayList(pkt,vstart,vend) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | \ + ((0x0f & (vstart))*40); \ + _g->words.w1 = (unsigned int)((0x0f & ((vend)+1))*40); \ +} + +#define gsSPCullDisplayList(vstart,vend) \ +{ \ + _SHIFTL(G_CULLDL, 24, 8) | ((0x0f & (vstart))*40), \ + ((0x0f & ((vend)+1))*40) \ +} +#endif + +#define gSPSegment(pkt, segment, base) \ + gMoveWd(pkt, G_MW_SEGMENT, (segment)*4, base) +#define gsSPSegment(segment, base) \ + gsMoveWd( G_MW_SEGMENT, (segment)*4, base) + +/* + * Clipping Macros + */ +#define FR_NEG_FRUSTRATIO_1 0x00000001 +#define FR_POS_FRUSTRATIO_1 0x0000ffff +#define FR_NEG_FRUSTRATIO_2 0x00000002 +#define FR_POS_FRUSTRATIO_2 0x0000fffe +#define FR_NEG_FRUSTRATIO_3 0x00000003 +#define FR_POS_FRUSTRATIO_3 0x0000fffd +#define FR_NEG_FRUSTRATIO_4 0x00000004 +#define FR_POS_FRUSTRATIO_4 0x0000fffc +#define FR_NEG_FRUSTRATIO_5 0x00000005 +#define FR_POS_FRUSTRATIO_5 0x0000fffb +#define FR_NEG_FRUSTRATIO_6 0x00000006 +#define FR_POS_FRUSTRATIO_6 0x0000fffa +/* + * r should be one of: FRUSTRATIO_1, FRUSTRATIO_2, FRUSTRATIO_3, ... FRUSTRATIO_6 + */ +#define gSPClipRatio(pkt, r) \ +{ \ + gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RNX, FR_NEG_##r); \ + gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RNY, FR_NEG_##r); \ + gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RPX, FR_POS_##r); \ + gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RPY, FR_POS_##r); \ +} + +#define gsSPClipRatio(r) \ + gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RNX, FR_NEG_##r), \ + gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RNY, FR_NEG_##r), \ + gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RPX, FR_POS_##r), \ + gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RPY, FR_POS_##r) + +/* + * Insert values into Matrix + * + * where = element of matrix (byte offset) + * num = new element (32 bit value replacing 2 int or 2 frac matrix + * componants + */ +#ifdef F3DEX_GBI_2 +#define gSPInsertMatrix(pkt, where, num) \ + ERROR!! gSPInsertMatrix is no longer supported. +#define gsSPInsertMatrix(where, num) \ + ERROR!! gsSPInsertMatrix is no longer supported. +#else +#define gSPInsertMatrix(pkt, where, num) \ + gMoveWd(pkt, G_MW_MATRIX, where, num) +#define gsSPInsertMatrix(where, num) \ + gsMoveWd(G_MW_MATRIX, where, num) +#endif + +/* + * Load new matrix directly + * + * mptr = pointer to matrix + */ +#ifdef F3DEX_GBI_2 +#define gSPForceMatrix(pkt, mptr) \ +{ gDma2p((pkt),G_MOVEMEM,(mptr),sizeof(Mtx),G_MV_MATRIX,0); \ + gMoveWd((pkt), G_MW_FORCEMTX,0,0x00010000); \ +} +#define gsSPForceMatrix(mptr) \ + gsDma2p(G_MOVEMEM,(mptr),sizeof(Mtx),G_MV_MATRIX,0), \ + gsMoveWd(G_MW_FORCEMTX,0,0x00010000) + +#else /* F3DEX_GBI_2 */ +#define gSPForceMatrix(pkt, mptr) \ +{ \ + gDma1p(pkt, G_MOVEMEM, mptr, 16, G_MV_MATRIX_1); \ + gDma1p(pkt, G_MOVEMEM, (char *)(mptr)+16, 16, G_MV_MATRIX_2); \ + gDma1p(pkt, G_MOVEMEM, (char *)(mptr)+32, 16, G_MV_MATRIX_3); \ + gDma1p(pkt, G_MOVEMEM, (char *)(mptr)+48, 16, G_MV_MATRIX_4); \ +} +#define gsSPForceMatrix(mptr) \ + gsDma1p( G_MOVEMEM, mptr, 16, G_MV_MATRIX_1), \ + gsDma1p( G_MOVEMEM, (char *)(mptr)+16, 16, G_MV_MATRIX_2), \ + gsDma1p( G_MOVEMEM, (char *)(mptr)+32, 16, G_MV_MATRIX_3), \ + gsDma1p( G_MOVEMEM, (char *)(mptr)+48, 16, G_MV_MATRIX_4) +#endif /* F3DEX_GBI_2 */ + +/* + * Insert values into Points + * + * point = point number 0-15 + * where = which element of point to modify (byte offset into point) + * num = new value (32 bit) + */ +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +# define gSPModifyVertex(pkt, vtx, where, val) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_MODIFYVTX,24,8)| \ + _SHIFTL((where),16,8)|_SHIFTL((vtx)*2,0,16)); \ + _g->words.w1 = (unsigned int)(val); \ +} +# define gsSPModifyVertex(vtx, where, val) \ +{ \ + _SHIFTL(G_MODIFYVTX,24,8)| \ + _SHIFTL((where),16,8)|_SHIFTL((vtx)*2,0,16), \ + (unsigned int)(val) \ +} +#else +# define gSPModifyVertex(pkt, vtx, where, val) \ + gMoveWd(pkt, G_MW_POINTS, (vtx)*40+(where), val) +# define gsSPModifyVertex(vtx, where, val) \ + gsMoveWd(G_MW_POINTS, (vtx)*40+(where), val) +#endif + +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +/* + * gSPBranchLessZ Branch DL if (vtx.z) less than or equal (zval). + * + * dl = DL branch to + * vtx = Vertex + * zval = Screen depth + * near = Near plane + * far = Far plane + * flag = G_BZ_PERSP or G_BZ_ORTHO + */ + +#define G_BZ_PERSP 0 +#define G_BZ_ORTHO 1 + +#define G_DEPTOZSrg(zval, near, far, flag, zmin, zmax) \ +(((unsigned int)FTOFIX32(((flag) == G_BZ_PERSP ? \ + (1.0f-(float)(near)/(float)(zval)) / \ + (1.0f-(float)(near)/(float)(far )) : \ + ((float)(zval) - (float)(near)) / \ + ((float)(far ) - (float)(near))))) * \ + (((int)((zmax) - (zmin)))&~1) + (int)FTOFIX32(zmin)) + +#define G_DEPTOZS(zval, near, far, flag) \ + G_DEPTOZSrg(zval, near, far, flag, 0, G_MAXZ) + +#define gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, zmin, zmax) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ + _g->words.w1 = (unsigned int)(dl); \ + _g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_BRANCH_Z,24,8)| \ + _SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12)); \ + _g->words.w1 = G_DEPTOZSrg(zval, near, far, flag, zmin, zmax); \ +} + +#define gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, zmin, zmax) \ +{ _SHIFTL(G_RDPHALF_1,24,8), \ + (unsigned int)(dl), }, \ +{ _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\ + G_DEPTOZSrg(zval, near, far, flag, zmin, zmax), } + +#define gSPBranchLessZ(pkt, dl, vtx, zval, near, far, flag) \ + gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, 0, G_MAXZ) +#define gsSPBranchLessZ(dl, vtx, zval, near, far, flag) \ + gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, 0, G_MAXZ) + +/* + * gSPBranchLessZraw Branch DL if (vtx.z) less than or equal (raw zval). + * + * dl = DL branch to + * vtx = Vertex + * zval = Raw value of screen depth + */ +#define gSPBranchLessZraw(pkt, dl, vtx, zval) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ + _g->words.w1 = (unsigned int)(dl); \ + _g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_BRANCH_Z,24,8)| \ + _SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12)); \ + _g->words.w1 = (unsigned int)(zval); \ +} + +#define gsSPBranchLessZraw(dl, vtx, zval) \ +{ _SHIFTL(G_RDPHALF_1,24,8), \ + (unsigned int)(dl), }, \ +{ _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\ + (unsigned int)(zval), } + +/* + * gSPLoadUcode RSP loads specified ucode. + * + * uc_start = ucode text section start + * uc_dstart = ucode data section start + */ +#define gSPLoadUcodeEx(pkt, uc_start, uc_dstart, uc_dsize) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ + _g->words.w1 = (unsigned int)(uc_dstart); \ + _g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_LOAD_UCODE,24,8)| \ + _SHIFTL((int)(uc_dsize)-1,0,16)); \ + _g->words.w1 = (unsigned int)(uc_start); \ +} + +#define gsSPLoadUcodeEx(uc_start, uc_dstart, uc_dsize) \ +{ _SHIFTL(G_RDPHALF_1,24,8), \ + (unsigned int)(uc_dstart), }, \ +{ _SHIFTL(G_LOAD_UCODE,24,8)| \ + _SHIFTL((int)(uc_dsize)-1,0,16), \ + (unsigned int)(uc_start), } + +#define gSPLoadUcode(pkt, uc_start, uc_dstart) \ + gSPLoadUcodeEx((pkt), (uc_start), (uc_dstart), SP_UCODE_DATA_SIZE) +#define gsSPLoadUcode(uc_start, uc_dstart) \ + gsSPLoadUcodeEx((uc_start), (uc_dstart), SP_UCODE_DATA_SIZE) + +#define gSPLoadUcodeL(pkt, ucode) \ + gSPLoadUcode((pkt), OS_K0_TO_PHYSICAL(&##ucode##TextStart), \ + OS_K0_TO_PHYSICAL(&##ucode##DataStart)) +#define gsSPLoadUcodeL(ucode) \ + gsSPLoadUcode(OS_K0_TO_PHYSICAL(&##ucode##TextStart), \ + OS_K0_TO_PHYSICAL(&##ucode##DataStart)) +#endif + +#ifdef F3DEX_GBI_2 +/* + * gSPDma_io DMA to/from DMEM/IMEM for DEBUG. + */ +#define gSPDma_io(pkt, flag, dmem, dram, size) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_DMA_IO,24,8)|_SHIFTL((flag),23,1)| \ + _SHIFTL((dmem)/8,13,10)|_SHIFTL((size)-1,0,12); \ + _g->words.w1 = (unsigned int)(dram); \ +} + +#define gsSPDma_io(flag, dmem, dram, size) \ +{ \ + _SHIFTL(G_DMA_IO,24,8)|_SHIFTL((flag),23,1)| \ + _SHIFTL((dmem)/8,13,10)|_SHIFTL((size)-1,0,12), \ + (unsigned int)(dram) \ +} + +#define gSPDmaRead(pkt,dmem,dram,size) gSPDma_io((pkt),0,(dmem),(dram),(size)) +#define gsSPDmaRead(dmem,dram,size) gsSPDma_io(0,(dmem),(dram),(size)) +#define gSPDmaWrite(pkt,dmem,dram,size) gSPDma_io((pkt),1,(dmem),(dram),(size)) +#define gsSPDmaWrite(dmem,dram,size) gsSPDma_io(1,(dmem),(dram),(size)) +#endif + +/* + * Lighting Macros + */ +#ifdef F3DEX_GBI_2 +# define NUML(n) ((n)*24) +#else +# define NUML(n) (((n)+1)*32 + 0x80000000) +#endif +#define NUMLIGHTS_0 1 +#define NUMLIGHTS_1 1 +#define NUMLIGHTS_2 2 +#define NUMLIGHTS_3 3 +#define NUMLIGHTS_4 4 +#define NUMLIGHTS_5 5 +#define NUMLIGHTS_6 6 +#define NUMLIGHTS_7 7 +/* + * n should be one of: NUMLIGHTS_0, NUMLIGHTS_1, ..., NUMLIGHTS_7 + * NOTE: in addition to the number of directional lights specified, + * there is always 1 ambient light + */ +#define gSPNumLights(pkt, n) \ + gMoveWd(pkt, G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n)) +#define gsSPNumLights(n) \ + gsMoveWd( G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n)) + +#define LIGHT_1 1 +#define LIGHT_2 2 +#define LIGHT_3 3 +#define LIGHT_4 4 +#define LIGHT_5 5 +#define LIGHT_6 6 +#define LIGHT_7 7 +#define LIGHT_8 8 +/* + * l should point to a Light struct + * n should be one of: LIGHT_1, LIGHT_2, ..., LIGHT_8 + * NOTE: the highest numbered light is always the ambient light (eg if there are + * 3 directional lights defined: gsSPNumLights(NUMLIGHTS_3), then lights + * LIGHT_1 through LIGHT_3 will be the directional lights and light + * LIGHT_4 will be the ambient light. + */ +#ifdef F3DEX_GBI_2 +# define gSPLight(pkt, l, n) \ + gDma2p((pkt),G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,(n)*24+24) +# define gsSPLight(l, n) \ + gsDma2p( G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,(n)*24+24) +#else /* F3DEX_GBI_2 */ +# define gSPLight(pkt, l, n) \ + gDma1p(pkt, G_MOVEMEM, l, sizeof(Light),((n)-1)*2+G_MV_L0) +# define gsSPLight(l, n) \ + gsDma1p( G_MOVEMEM, l, sizeof(Light),((n)-1)*2+G_MV_L0) +#endif /* F3DEX_GBI_2 */ + +/* + * gSPLightColor changes color of light without recalculating light direction + * col is a 32 bit word with r,g,b,a (alpha is ignored) + * n should be one of LIGHT_1, LIGHT_2, ..., LIGHT_8 + */ +#define gSPLightColor(pkt, n, col) \ +{ \ + gMoveWd(pkt, G_MW_LIGHTCOL, G_MWO_a##n, col); \ + gMoveWd(pkt, G_MW_LIGHTCOL, G_MWO_b##n, col); \ +} +#define gsSPLightColor(n, col) \ + gsMoveWd(G_MW_LIGHTCOL, G_MWO_a##n, col), \ + gsMoveWd(G_MW_LIGHTCOL, G_MWO_b##n, col) + +/* These macros use a structure "name" which is init'd with the gdSPDefLights macros*/ + +#define gSPSetLights0(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_0); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.a,2); \ +} +#define gsSPSetLights0(name) \ + gsSPNumLights(NUMLIGHTS_0), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.a,2) + +#define gSPSetLights1(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_1); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.a,2); \ +} +#define gsSPSetLights1(name) \ + gsSPNumLights(NUMLIGHTS_1), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.a,2) + +#define gSPSetLights2(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_2); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.a,3); \ +} +#define gsSPSetLights2(name) \ + gsSPNumLights(NUMLIGHTS_2), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.a,3) + +#define gSPSetLights3(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_3); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.a,4); \ +} +#define gsSPSetLights3(name) \ + gsSPNumLights(NUMLIGHTS_3), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.a,4) + +#define gSPSetLights4(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_4); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.l[3],4); \ + gSPLight(pkt,&name.a,5); \ +} +#define gsSPSetLights4(name) \ + gsSPNumLights(NUMLIGHTS_4), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.l[3],4), \ + gsSPLight(&name.a,5) + +#define gSPSetLights5(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_5); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.l[3],4); \ + gSPLight(pkt,&name.l[4],5); \ + gSPLight(pkt,&name.a,6); \ +} + +#define gsSPSetLights5(name) \ + gsSPNumLights(NUMLIGHTS_5), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.l[3],4), \ + gsSPLight(&name.l[4],5), \ + gsSPLight(&name.a,6) + +#define gSPSetLights6(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_6); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.l[3],4); \ + gSPLight(pkt,&name.l[4],5); \ + gSPLight(pkt,&name.l[5],6); \ + gSPLight(pkt,&name.a,7); \ +} + +#define gsSPSetLights6(name) \ + gsSPNumLights(NUMLIGHTS_6), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.l[3],4), \ + gsSPLight(&name.l[4],5), \ + gsSPLight(&name.l[5],6), \ + gsSPLight(&name.a,7) + +#define gSPSetLights7(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_7); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.l[3],4); \ + gSPLight(pkt,&name.l[4],5); \ + gSPLight(pkt,&name.l[5],6); \ + gSPLight(pkt,&name.l[6],7); \ + gSPLight(pkt,&name.a,8); \ +} + +#define gsSPSetLights7(name) \ + gsSPNumLights(NUMLIGHTS_7), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.l[3],4), \ + gsSPLight(&name.l[4],5), \ + gsSPLight(&name.l[5],6), \ + gsSPLight(&name.l[6],7), \ + gsSPLight(&name.a,8) + +/* + * Reflection/Hiliting Macros + */ +#ifdef F3DEX_GBI_2 +# define gSPLookAtX(pkt, l) \ + gDma2p((pkt),G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATX) +# define gsSPLookAtX(l) \ + gsDma2p( G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATX) +# define gSPLookAtY(pkt, l) \ + gDma2p((pkt),G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATY) +# define gsSPLookAtY(l) \ + gsDma2p( G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATY) +#else /* F3DEX_GBI_2 */ +# define gSPLookAtX(pkt, l) \ + gDma1p(pkt, G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATX) +# define gsSPLookAtX(l) \ + gsDma1p( G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATX) +# define gSPLookAtY(pkt, l) \ + gDma1p(pkt, G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATY) +# define gsSPLookAtY(l) \ + gsDma1p( G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATY) +#endif /* F3DEX_GBI_2 */ + +#define gSPLookAt(pkt, la) \ +{ \ + gSPLookAtX(pkt,la) \ + gSPLookAtY(pkt,(char *)(la)+16) \ +} +#define gsSPLookAt(la) \ + gsSPLookAtX(la), \ + gsSPLookAtY((char *)(la)+16) + +#define gDPSetHilite1Tile(pkt, tile, hilite, width, height) \ + gDPSetTileSize(pkt, tile, (hilite)->h.x1 & 0xfff, (hilite)->h.y1 & 0xfff, \ + ((((width)-1)*4)+(hilite)->h.x1) & 0xfff, ((((height)-1)*4)+(hilite)->h.y1) & 0xfff) +#define gsDPSetHilite1Tile(tile, hilite, width, height) \ + gsDPSetTileSize(tile, (hilite)->h.x1 & 0xfff, (hilite)->h.y1 & 0xfff, \ + ((((width)-1)*4)+(hilite)->h.x1) & 0xfff, ((((height)-1)*4)+(hilite)->h.y1) & 0xfff) + +#define gDPSetHilite2Tile(pkt, tile, hilite, width, height) \ + gDPSetTileSize(pkt, tile, (hilite)->h.x2 & 0xfff, (hilite)->h.y2 & 0xfff, \ + ((((width)-1)*4)+(hilite)->h.x2) & 0xfff, ((((height)-1)*4)+(hilite)->h.y2) & 0xfff) +#define gsDPSetHilite2Tile(tile, hilite, width, height) \ + gsDPSetTileSize(tile, (hilite)->h.x2 & 0xfff, (hilite)->h.y2 & 0xfff, \ + ((((width)-1)*4)+(hilite)->h.x2) & 0xfff, ((((height)-1)*4)+(hilite)->h.y2) & 0xfff) + +/* + * FOG macros + * fm = z multiplier + * fo = z offset + * FOG FORMULA: alpha(fog) = (eyespace z) * fm + fo CLAMPED 0 to 255 + * note: (eyespace z) ranges -1 to 1 + * + * Alternate method of setting fog: + * min, max: range 0 to 1000: 0=nearplane, 1000=farplane + * min is where fog begins (usually less than max and often 0) + * max is where fog is thickest (usually 1000) + * + */ +#define gSPFogFactor(pkt, fm, fo) \ + gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL(fm,16,16) | _SHIFTL(fo,0,16))) + +#define gsSPFogFactor(fm, fo) \ + gsMoveWd(G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL(fm,16,16) | _SHIFTL(fo,0,16))) + +#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))) + +#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))) + +#ifdef F3DEX_GBI_2 +/* + * Macros to turn texture on/off + */ +# define gSPTexture(pkt, s, t, level, tile, on) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8) | \ + _SHIFTL(BOWTIE_VAL,16,8) | \ + _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | \ + _SHIFTL((on),1,7)); \ + _g->words.w1 = (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)); \ +} +# define gsSPTexture(s, t, level, tile, on) \ +{ \ + (_SHIFTL(G_TEXTURE,24,8) | _SHIFTL(BOWTIE_VAL,16,8) | \ + _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | _SHIFTL((on),1,7)),\ + (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)) \ +} +/* + * Different version of SPTexture macro, has an additional parameter + * which is currently reserved in the microcode. + */ +# define gSPTextureL(pkt, s, t, level, xparam, tile, on) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8) | \ + _SHIFTL((xparam),16,8) | \ + _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | \ + _SHIFTL((on),1,7)); \ + _g->words.w1 = (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)); \ +} +# define gsSPTextureL(s, t, level, xparam, tile, on) \ +{ \ + (_SHIFTL(G_TEXTURE,24,8) | _SHIFTL((xparam),16,8) | \ + _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | _SHIFTL((on),1,7)),\ + (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)) \ +} +#else +/* + * Macros to turn texture on/off + */ +# define gSPTexture(pkt, s, t, level, tile, on) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL(BOWTIE_VAL,16,8)|\ + _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)| \ + _SHIFTL((on),0,8)); \ + _g->words.w1 = (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)); \ +} +# define gsSPTexture(s, t, level, tile, on) \ +{ \ + (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL(BOWTIE_VAL,16,8)| \ + _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)|_SHIFTL((on),0,8)), \ + (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)) \ +} +/* + * Different version of SPTexture macro, has an additional parameter + * which is currently reserved in the microcode. + */ +# define gSPTextureL(pkt, s, t, level, xparam, tile, on) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL((xparam),16,8)| \ + _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)| \ + _SHIFTL((on),0,8)); \ + _g->words.w1 = (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)); \ +} +# define gsSPTextureL(s, t, level, xparam, tile, on) \ +{ \ + (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL((xparam),16,8)| \ + _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)|_SHIFTL((on),0,8)), \ + (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)) \ +} +#endif + +#define gSPPerspNormalize(pkt, s) gMoveWd(pkt, G_MW_PERSPNORM, 0, (s)) +#define gsSPPerspNormalize(s) gsMoveWd( G_MW_PERSPNORM, 0, (s)) + +#ifdef F3DEX_GBI_2 +# define gSPPopMatrixN(pkt, n, num) gDma2p((pkt),G_POPMTX,(num)*64,64,2,0) +# define gsSPPopMatrixN(n, num) gsDma2p( G_POPMTX,(num)*64,64,2,0) +# define gSPPopMatrix(pkt, n) gSPPopMatrixN((pkt), (n), 1) +# define gsSPPopMatrix(n) gsSPPopMatrixN( (n), 1) +#else /* F3DEX_GBI_2 */ +# define gSPPopMatrix(pkt, n) gImmp1(pkt, G_POPMTX, n) +# define gsSPPopMatrix(n) gsImmp1( G_POPMTX, n) +#endif /* F3DEX_GBI_2 */ + +#define gSPEndDisplayList(pkt) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_ENDDL, 24, 8); \ + _g->words.w1 = 0; \ +} + +#define gsSPEndDisplayList() \ +{ \ + _SHIFTL(G_ENDDL, 24, 8), 0 \ +} + +#ifdef F3DEX_GBI_2 +/* + * One gSPGeometryMode(pkt,c,s) GBI is equal to these two GBIs. + * + * gSPClearGeometryMode(pkt,c) + * gSPSetGeometryMode(pkt,s) + * + * gSPLoadGeometryMode(pkt, word) sets GeometryMode directly. + */ +#define gSPGeometryMode(pkt, c, s) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_GEOMETRYMODE,24,8)|_SHIFTL(~(u32)(c),0,24);\ + _g->words.w1 = (u32)(s); \ +} + +#define gsSPGeometryMode(c, s) \ +{ \ + (_SHIFTL(G_GEOMETRYMODE,24,8)|_SHIFTL(~(u32)(c),0,24)),(u32)(s) \ +} +#define gSPSetGeometryMode(pkt, word) gSPGeometryMode((pkt),0,(word)) +#define gsSPSetGeometryMode(word) gsSPGeometryMode(0,(word)) +#define gSPClearGeometryMode(pkt, word) gSPGeometryMode((pkt),(word),0) +#define gsSPClearGeometryMode(word) gsSPGeometryMode((word),0) +#define gSPLoadGeometryMode(pkt, word) gSPGeometryMode((pkt),-1,(word)) +#define gsSPLoadGeometryMode(pkt, word) gsSPGeometryMode(-1,(word)) + +#else /* F3DEX_GBI_2 */ +#define gSPSetGeometryMode(pkt, word) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETGEOMETRYMODE, 24, 8); \ + _g->words.w1 = (unsigned int)(word); \ +} + +#define gsSPSetGeometryMode(word) \ +{ \ + _SHIFTL(G_SETGEOMETRYMODE, 24, 8), (unsigned int)(word) \ +} + +#define gSPClearGeometryMode(pkt, word) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8); \ + _g->words.w1 = (unsigned int)(word); \ +} + +#define gsSPClearGeometryMode(word) \ +{ \ + _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8), (unsigned int)(word) \ +} +#endif /* F3DEX_GBI_2 */ + +#ifdef F3DEX_GBI_2 +#define gSPSetOtherMode(pkt, cmd, sft, len, data) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(cmd,24,8)|_SHIFTL(32-(sft)-(len),8,8)| \ + _SHIFTL((len)-1,0,8)); \ + _g->words.w1 = (unsigned int)(data); \ +} + +#define gsSPSetOtherMode(cmd, sft, len, data) \ +{ \ + _SHIFTL(cmd,24,8)|_SHIFTL(32-(sft)-(len),8,8)|_SHIFTL((len)-1,0,8), \ + (unsigned int)(data) \ +} +#else +#define gSPSetOtherMode(pkt, cmd, sft, len, data) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | \ + _SHIFTL(len, 0, 8)); \ + _g->words.w1 = (unsigned int)(data); \ +} + +#define gsSPSetOtherMode(cmd, sft, len, data) \ +{ \ + _SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | _SHIFTL(len, 0, 8), \ + (unsigned int)(data) \ +} +#endif + +/* + * RDP setothermode register commands - register shadowed in RSP + */ +#define gDPPipelineMode(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode) +#define gsDPPipelineMode(mode) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode) + +#define gDPSetCycleType(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type) +#define gsDPSetCycleType(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type) + +#define gDPSetTexturePersp(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type) +#define gsDPSetTexturePersp(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type) + +#define gDPSetTextureDetail(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type) +#define gsDPSetTextureDetail(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type) + +#define gDPSetTextureLOD(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type) +#define gsDPSetTextureLOD(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type) + +#define gDPSetTextureLUT(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type) +#define gsDPSetTextureLUT(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type) + +#define gDPSetTextureFilter(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type) +#define gsDPSetTextureFilter(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type) + +#define gDPSetTextureConvert(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type) +#define gsDPSetTextureConvert(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type) + +#define gDPSetCombineKey(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type) +#define gsDPSetCombineKey(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type) + +#ifndef _HW_VERSION_1 +#define gDPSetColorDither(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode) +#define gsDPSetColorDither(mode) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode) +#else +#define gDPSetColorDither(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_COLORDITHER, 1, mode) +#define gsDPSetColorDither(mode) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_COLORDITHER, 1, mode) +#endif + +#ifndef _HW_VERSION_1 +#define gDPSetAlphaDither(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode) +#define gsDPSetAlphaDither(mode) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode) +#endif + +/* 'blendmask' is not supported anymore. + * The bits are reserved for future use. + * Fri May 26 13:45:55 PDT 1995 + */ +#define gDPSetBlendMask(pkt, mask) gDPNoOp(pkt) +#define gsDPSetBlendMask(mask) gsDPNoOp() + +#define gDPSetAlphaCompare(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type) +#define gsDPSetAlphaCompare(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type) + +#define gDPSetDepthSource(pkt, src) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src) +#define gsDPSetDepthSource(src) \ + gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src) + +#define gDPSetRenderMode(pkt, c0, c1) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, \ + (c0) | (c1)) +#define gsDPSetRenderMode(c0, c1) \ + gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, \ + (c0) | (c1)) + +#define gSetImage(pkt, cmd, fmt, siz, width, i) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12); \ + _g->words.w1 = (unsigned int)(i); \ +} + +#define gsSetImage(cmd, fmt, siz, width, i) \ +{ \ + _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12), \ + (unsigned int)(i) \ +} + +#define gDPSetColorImage(pkt, f, s, w, i) gSetImage(pkt, G_SETCIMG, f, s, w, i) +#define gsDPSetColorImage(f, s, w, i) gsSetImage(G_SETCIMG, f, s, w, i) + + +/* use these for new code */ +#define gDPSetDepthImage(pkt, i) gSetImage(pkt, G_SETZIMG, 0, 0, 1, i) +#define gsDPSetDepthImage(i) gsSetImage(G_SETZIMG, 0, 0, 1, i) +/* kept for compatibility */ +#define gDPSetMaskImage(pkt, i) gDPSetDepthImage(pkt, i) +#define gsDPSetMaskImage(i) gsDPSetDepthImage(i) + +#define gDPSetTextureImage(pkt, f, s, w, i) gSetImage(pkt, G_SETTIMG, f, s, w, i) +#define gsDPSetTextureImage(f, s, w, i) gsSetImage(G_SETTIMG, f, s, w, i) + +/* + * RDP macros + */ + +#define gDPSetCombine(pkt, muxs0, muxs1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24);\ + _g->words.w1 = (unsigned int)(muxs1); \ +} + +#define gsDPSetCombine(muxs0, muxs1) \ +{ \ + _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24), \ + (unsigned int)(muxs1) \ +} + +#define GCCc0w0(saRGB0, mRGB0, saA0, mA0) \ + (_SHIFTL((saRGB0), 20, 4) | _SHIFTL((mRGB0), 15, 5) | \ + _SHIFTL((saA0), 12, 3) | _SHIFTL((mA0), 9, 3)) + +#define GCCc1w0(saRGB1, mRGB1) \ + (_SHIFTL((saRGB1), 5, 4) | _SHIFTL((mRGB1), 0, 5)) + +#define GCCc0w1(sbRGB0, aRGB0, sbA0, aA0) \ + (_SHIFTL((sbRGB0), 28, 4) | _SHIFTL((aRGB0), 15, 3) | \ + _SHIFTL((sbA0), 12, 3) | _SHIFTL((aA0), 9, 3)) + +#define GCCc1w1(sbRGB1, saA1, mA1, aRGB1, sbA1, aA1) \ + (_SHIFTL((sbRGB1), 24, 4) | _SHIFTL((saA1), 21, 3) | \ + _SHIFTL((mA1), 18, 3) | _SHIFTL((aRGB1), 6, 3) | \ + _SHIFTL((sbA1), 3, 3) | _SHIFTL((aA1), 0, 3)) + +#define gDPSetCombineLERP(pkt, a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \ + a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | \ + _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, \ + G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \ + GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), \ + 0, 24); \ + _g->words.w1 = (unsigned int)(GCCc0w1(G_CCMUX_##b0, \ + G_CCMUX_##d0, \ + G_ACMUX_##Ab0, \ + G_ACMUX_##Ad0) | \ + GCCc1w1(G_CCMUX_##b1, \ + G_ACMUX_##Aa1, \ + G_ACMUX_##Ac1, \ + G_CCMUX_##d1, \ + G_ACMUX_##Ab1, \ + G_ACMUX_##Ad1)); \ +} + +#define gsDPSetCombineLERP(a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \ + a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \ +{ \ + _SHIFTL(G_SETCOMBINE, 24, 8) | \ + _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, \ + G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \ + GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), 0, 24), \ + (unsigned int)(GCCc0w1(G_CCMUX_##b0, G_CCMUX_##d0, \ + G_ACMUX_##Ab0, G_ACMUX_##Ad0) | \ + GCCc1w1(G_CCMUX_##b1, G_ACMUX_##Aa1, \ + G_ACMUX_##Ac1, G_CCMUX_##d1, \ + G_ACMUX_##Ab1, G_ACMUX_##Ad1)) \ +} + +/* + * SetCombineMode macros are NOT redunant. It allow the C preprocessor + * to substitute single parameter which includes commas in the token and + * rescan for higher parameter count macro substitution. + * + * eg. gsDPSetCombineMode(G_CC_MODULATE, G_CC_MODULATE) turns into + * gsDPSetCombineLERP(TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0, + * TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0) + */ + +#define gDPSetCombineMode(pkt, a, b) gDPSetCombineLERP(pkt, a, b) +#define gsDPSetCombineMode(a, b) gsDPSetCombineLERP(a, b) + +#define gDPSetColor(pkt, c, d) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(c, 24, 8); \ + _g->words.w1 = (unsigned int)(d); \ +} + +#define gsDPSetColor(c, d) \ +{ \ + _SHIFTL(c, 24, 8), (unsigned int)(d) \ +} + +#define DPRGBColor(pkt, cmd, r, g, b, a) \ + gDPSetColor(pkt, cmd, \ + (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8))) +#define sDPRGBColor(cmd, r, g, b, a) \ + gsDPSetColor(cmd, \ + (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8))) + +#define gDPSetEnvColor(pkt, r, g, b, a) \ + DPRGBColor(pkt, G_SETENVCOLOR, r,g,b,a) +#define gsDPSetEnvColor(r, g, b, a) \ + sDPRGBColor(G_SETENVCOLOR, r,g,b,a) +#define gDPSetBlendColor(pkt, r, g, b, a) \ + DPRGBColor(pkt, G_SETBLENDCOLOR, r,g,b,a) +#define gsDPSetBlendColor(r, g, b, a) \ + sDPRGBColor(G_SETBLENDCOLOR, r,g,b,a) +#define gDPSetFogColor(pkt, r, g, b, a) \ + DPRGBColor(pkt, G_SETFOGCOLOR, r,g,b,a) +#define gsDPSetFogColor(r, g, b, a) \ + sDPRGBColor(G_SETFOGCOLOR, r,g,b,a) +#define gDPSetFillColor(pkt, d) \ + gDPSetColor(pkt, G_SETFILLCOLOR, (d)) +#define gsDPSetFillColor(d) \ + gsDPSetColor(G_SETFILLCOLOR, (d)) + +#define gDPSetPrimDepth(pkt, z, dz) \ + gDPSetColor(pkt, G_SETPRIMDEPTH, \ + _SHIFTL(z, 16, 16) | _SHIFTL(dz, 0, 16)) +#define gsDPSetPrimDepth(z, dz) \ + gsDPSetColor(G_SETPRIMDEPTH, _SHIFTL(z, 16, 16) | \ + _SHIFTL(dz, 0, 16)) + +#define gDPSetPrimColor(pkt, m, l, r, g, b, a) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | \ + _SHIFTL(m, 8, 8) | _SHIFTL(l, 0, 8)); \ + _g->words.w1 = (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8)); \ +} + +#define gsDPSetPrimColor(m, l, r, g, b, a) \ +{ \ + (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | _SHIFTL(m, 8, 8) | \ + _SHIFTL(l, 0, 8)), \ + (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | \ + _SHIFTL(a, 0, 8)) \ +} + +/* + * gDPSetOtherMode (This is for expert user.) + * + * This command makes all othermode parameters set. + * Do not use this command in the same DL with another g*SPSetOtherMode DLs. + * + * [Usage] + * gDPSetOtherMode(pkt, modeA, modeB) + * + * 'modeA' is described all parameters of GroupA GBI command. + * 'modeB' is also described all parameters of GroupB GBI command. + * + * GroupA: + * gDPPipelineMode, gDPSetCycleType, gSPSetTexturePersp, + * gDPSetTextureDetail, gDPSetTextureLOD, gDPSetTextureLUT, + * gDPSetTextureFilter, gDPSetTextureConvert, gDPSetCombineKey, + * gDPSetColorDither, gDPSetAlphaDither + * + * GroupB: + * gDPSetAlphaCompare, gDPSetDepthSource, gDPSetRenderMode + * + * Use 'OR' operation to get modeA and modeB. + * + * modeA = G_PM_* | G_CYC_* | G_TP_* | G_TD_* | G_TL_* | G_TT_* | G_TF_* + * G_TC_* | G_CK_* | G_CD_* | G_AD_*; + * + * modeB = G_AC_* | G_ZS_* | G_RM_* | G_RM_*2; + */ +#define gDPSetOtherMode(pkt, mode0, mode1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24);\ + _g->words.w1 = (unsigned int)(mode1); \ +} + +#define gsDPSetOtherMode(mode0, mode1) \ +{ \ + _SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24), \ + (unsigned int)(mode1) \ +} + +/* + * Texturing macros + */ + +/* These are also defined defined above for Sprite Microcode */ + +#define G_TX_LOADTILE 7 +#define G_TX_RENDERTILE 0 + +#define G_TX_NOMIRROR 0 +#define G_TX_WRAP 0 +#define G_TX_MIRROR 0x1 +#define G_TX_CLAMP 0x2 +#define G_TX_NOMASK 0 +#define G_TX_NOLOD 0 + + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +/* + * Dxt is the inverse of the number of 64-bit words in a line of + * the texture being loaded using the load_block command. If + * there are any 1's to the right of the 11th fractional bit, + * dxt should be rounded up. The following macros accomplish + * this. The 4b macros are a special case since 4-bit textures + * are loaded as 8-bit textures. Dxt is fixed point 1.11. RJM + */ +#define G_TX_DXT_FRAC 11 + +/* + * For RCP 2.0, the maximum number of texels that can be loaded + * using a load_block command is 2048. In order to load the total + * 4kB of Tmem, change the texel size when loading to be G_IM_SIZ_16b, + * then change the tile to the proper texel size after the load. + * The g*DPLoadTextureBlock macros already do this, so this change + * will be transparent if you use these macros. If you use + * the g*DPLoadBlock macros directly, you will need to handle this + * tile manipulation yourself. RJM. + */ +#ifdef _HW_VERSION_1 +#define G_TX_LDBLK_MAX_TXL 4095 +#else +#define G_TX_LDBLK_MAX_TXL 2047 +#endif /* _HW_VERSION_1 */ + +#define TXL2WORDS(txls, b_txl) MAX(1, ((txls)*(b_txl)/8)) +#define CALC_DXT(width, b_txl) \ + (((1 << G_TX_DXT_FRAC) + TXL2WORDS(width, b_txl) - 1) / \ + TXL2WORDS(width, b_txl)) + +#define TXL2WORDS_4b(txls) MAX(1, ((txls)/16)) +#define CALC_DXT_4b(width) \ + (((1 << G_TX_DXT_FRAC) + TXL2WORDS_4b(width) - 1) / \ + TXL2WORDS_4b(width)) + +#define gDPLoadTileGeneric(pkt, c, tile, uls, ult, lrs, lrt) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(c, 24, 8) | _SHIFTL(uls, 12, 12) | \ + _SHIFTL(ult, 0, 12); \ + _g->words.w1 = _SHIFTL(tile, 24, 3) | _SHIFTL(lrs, 12, 12) | \ + _SHIFTL(lrt, 0, 12); \ +} + +#define gsDPLoadTileGeneric(c, tile, uls, ult, lrs, lrt) \ +{ \ + _SHIFTL(c, 24, 8) | _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12), \ + _SHIFTL(tile, 24, 3) | _SHIFTL(lrs, 12, 12) | _SHIFTL(lrt, 0, 12)\ +} + +#define gDPSetTileSize(pkt, t, uls, ult, lrs, lrt) \ + gDPLoadTileGeneric(pkt, G_SETTILESIZE, t, uls, ult, lrs, lrt) +#define gsDPSetTileSize(t, uls, ult, lrs, lrt) \ + gsDPLoadTileGeneric(G_SETTILESIZE, t, uls, ult, lrs, lrt) +#define gDPLoadTile(pkt, t, uls, ult, lrs, lrt) \ + gDPLoadTileGeneric(pkt, G_LOADTILE, t, uls, ult, lrs, lrt) +#define gsDPLoadTile(t, uls, ult, lrs, lrt) \ + gsDPLoadTileGeneric(G_LOADTILE, t, uls, ult, lrs, lrt) + +#define gDPSetTile(pkt, fmt, siz, line, tmem, tile, palette, cmt, \ + maskt, shiftt, cms, masks, shifts) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETTILE, 24, 8) | _SHIFTL(fmt, 21, 3) |\ + _SHIFTL(siz, 19, 2) | _SHIFTL(line, 9, 9) | \ + _SHIFTL(tmem, 0, 9); \ + _g->words.w1 = _SHIFTL(tile, 24, 3) | _SHIFTL(palette, 20, 4) | \ + _SHIFTL(cmt, 18, 2) | _SHIFTL(maskt, 14, 4) | \ + _SHIFTL(shiftt, 10, 4) |_SHIFTL(cms, 8, 2) | \ + _SHIFTL(masks, 4, 4) | _SHIFTL(shifts, 0, 4); \ +} + +#define gsDPSetTile(fmt, siz, line, tmem, tile, palette, cmt, \ + maskt, shiftt, cms, masks, shifts) \ +{ \ + (_SHIFTL(G_SETTILE, 24, 8) | _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | _SHIFTL(line, 9, 9) | _SHIFTL(tmem, 0, 9)),\ + (_SHIFTL(tile, 24, 3) | _SHIFTL(palette, 20, 4) | \ + _SHIFTL(cmt, 18, 2) | _SHIFTL(maskt, 14, 4) | \ + _SHIFTL(shiftt, 10, 4) | _SHIFTL(cms, 8, 2) | \ + _SHIFTL(masks, 4, 4) | _SHIFTL(shifts, 0, 4)) \ +} + +/* + * For RCP 2.0, the maximum number of texels that can be loaded + * using a load_block command is 2048. In order to load the total + * 4kB of Tmem, change the texel size when loading to be G_IM_SIZ_16b, + * then change the tile to the proper texel size after the load. + * The g*DPLoadTextureBlock macros already do this, so this change + * will be transparent if you use these macros. If you use + * the g*DPLoadBlock macros directly, you will need to handle this + * tile manipulation yourself. RJM. + */ +#define gDPLoadBlock(pkt, tile, uls, ult, lrs, dxt) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_LOADBLOCK, 24, 8) | \ + _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ + _SHIFTL((MIN(lrs,G_TX_LDBLK_MAX_TXL)), 12, 12) |\ + _SHIFTL(dxt, 0, 12)); \ +} + +#define gsDPLoadBlock(tile, uls, ult, lrs, dxt) \ +{ \ + (_SHIFTL(G_LOADBLOCK, 24, 8) | _SHIFTL(uls, 12, 12) | \ + _SHIFTL(ult, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | \ + _SHIFTL((MIN(lrs,G_TX_LDBLK_MAX_TXL)), 12, 12) | \ + _SHIFTL(dxt, 0, 12)) \ +} + +#define gDPLoadTLUTCmd(pkt, tile, count) \ +{ \ + Gfx *_g = (Gfx *)pkt; \ + \ + _g->words.w0 = _SHIFTL(G_LOADTLUT, 24, 8); \ + _g->words.w1 = _SHIFTL((tile), 24, 3) | _SHIFTL((count), 14, 10);\ +} + +#define gsDPLoadTLUTCmd(tile, count) \ +{ \ + _SHIFTL(G_LOADTLUT, 24, 8), \ + _SHIFTL((tile), 24, 3) | _SHIFTL((count), 14, 10) \ +} + +#define gDPLoadTextureBlock(pkt, timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT) -1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES)+7)>>3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +#define gDPLoadTextureBlockYuv(pkt, timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT) -1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * 1)+7)>>3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* Load fix rww 27jun95 */ +/* The S at the end means odd lines are already word Swapped */ + +#define gDPLoadTextureBlockS(pkt, timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1,0); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES)+7)>>3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * Allow tmem address and render tile to be specified. + * The S at the end means odd lines are already word Swapped + */ +#define gDPLoadMultiBlockS(pkt, timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1,0); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES)+7)>>3, tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + + +#define gDPLoadTextureBlockYuvS(pkt, timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1,0); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * 1)+7)>>3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * allows tmem address to be specified + */ +#define _gDPLoadTextureBlock(pkt, timg, tmem, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES)+7)>>3, \ + tmem, G_TX_RENDERTILE, pal, cmt, \ + maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * allows tmem address and render tile to be specified + */ +#define _gDPLoadTextureBlockTile(pkt, timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0,\ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES)+7)>>3, \ + tmem, rtile, pal, cmt, \ + maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * allows tmem address and render tile to be specified + */ +#define gDPLoadMultiBlock(pkt, timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0,\ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES)+7)>>3, \ + tmem, rtile, pal, cmt, \ + maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +#define gsDPLoadTextureBlock(timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, \ + masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +/* Here is the static form of the pre-swapped texture block loading */ +/* See gDPLoadTextureBlockS() for reference. Basically, just don't + calculate DxT, use 0 */ + +#define gsDPLoadTextureBlockS(timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0 , \ + cmt, maskt,shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, 0 ),\ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +/* + * Allow tmem address to be specified + */ +#define _gsDPLoadTextureBlock(timg, tmem, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES)+7)>>3), tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * Allow tmem address and render_tile to be specified + */ +#define _gsDPLoadTextureBlockTile(timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * Allow tmem address and render_tile to be specified, useful when loading + * mutilple tiles at a time. + */ +#define gsDPLoadMultiBlock(timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +/* + * Allows tmem and render tile to be specified. Useful when loading + * several tiles at a time. + * + * Here is the static form of the pre-swapped texture block loading + * See gDPLoadTextureBlockS() for reference. Basically, just don't + * calculate DxT, use 0 + */ + +#define gsDPLoadMultiBlockS(timg, tmem, rtile, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0 , \ + cmt, maskt,shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, 0 ),\ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES)+7)>>3), tmem,\ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +#define gDPLoadTextureBlock_4b(pkt, timg, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* Load fix rww 27jun95 */ +/* The S at the end means odd lines are already word Swapped */ + +#define gDPLoadTextureBlock_4bS(pkt, timg, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, 0 ); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * 4-bit load block. Useful when loading multiple tiles + */ +#define gDPLoadMultiBlock_4b(pkt, timg, tmem, rtile, fmt, width, height,\ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * 4-bit load block. Allows tmem and render tile to be specified. Useful when + * loading multiple tiles. The S means odd lines are already word swapped. + */ +#define gDPLoadMultiBlock_4bS(pkt, timg, tmem, rtile, fmt, width, height,\ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, 0 ); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + + +#define _gDPLoadTextureBlock_4b(pkt, timg, tmem, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +#define gsDPLoadTextureBlock_4b(timg, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +#define gsDPLoadTextureBlock_4bS(timg, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1,0),\ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +/* + * 4-bit load block. Allows tmem address and render tile to be specified. + * Useful when loading multiple tiles. + */ +#define gsDPLoadMultiBlock_4b(timg, tmem, rtile, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * 4-bit load block. Allows tmem address and render tile to be specified. + * Useful when loading multiple tiles. S means odd lines are already swapped. + */ +#define gsDPLoadMultiBlock_4bS(timg, tmem, rtile, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1,0),\ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * Allows tmem address to be specified + */ +#define _gsDPLoadTextureBlock_4b(timg, tmem, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +#ifndef _HW_VERSION_1 + +#define gDPLoadTextureTile(pkt, timg, fmt, siz, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz, width, timg); \ + gDPSetTile(pkt, fmt, siz, \ + (((((lrs)-(uls)+1) * siz##_TILE_BYTES)+7)>>3), 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPLoadSync(pkt); \ + gDPLoadTile( pkt, G_TX_LOADTILE, \ + (uls)<>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, \ + (uls)<>3), tmem, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPLoadSync(pkt); \ + gDPLoadTile( pkt, G_TX_LOADTILE, \ + (uls)<>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, \ + (uls)<>3), 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile( G_TX_LOADTILE, \ + (uls)<>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks,\ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, \ + (uls)<>3), \ + tmem, G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, \ + masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile( G_TX_LOADTILE, \ + (uls)<>3), \ + tmem, rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, \ + (uls)<>1), timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_8b, \ + (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPLoadSync(pkt); \ + gDPLoadTile( pkt, G_TX_LOADTILE, \ + (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (ult)<<(G_TEXTURE_IMAGE_FRAC), \ + (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (lrt)<<(G_TEXTURE_IMAGE_FRAC)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, \ + masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, \ + (uls)<>1), timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_8b, \ + (((((lrs)-(uls)+1)>>1)+7)>>3), tmem, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPLoadSync(pkt); \ + gDPLoadTile( pkt, G_TX_LOADTILE, \ + (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (ult)<<(G_TEXTURE_IMAGE_FRAC), \ + (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (lrt)<<(G_TEXTURE_IMAGE_FRAC)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + (((((lrs)-(uls)+1)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, \ + (uls)<>1), timg), \ + gsDPSetTile(fmt, G_IM_SIZ_8b, (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile( G_TX_LOADTILE, \ + (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (ult)<<(G_TEXTURE_IMAGE_FRAC), \ + (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (lrt)<<(G_TEXTURE_IMAGE_FRAC)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, \ + (uls)<>1), timg), \ + gsDPSetTile(fmt, G_IM_SIZ_8b, (((((lrs)-(uls)+1)>>1)+7)>>3), \ + tmem, G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, \ + masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile( G_TX_LOADTILE, \ + (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (ult)<<(G_TEXTURE_IMAGE_FRAC), \ + (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (lrt)<<(G_TEXTURE_IMAGE_FRAC)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, (((((lrs)-(uls)+1)>>1)+7)>>3), \ + tmem, rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, \ + (uls)<words.w0 = _SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((float)(ulx)*4.0F), 12, 12) | \ + _SHIFTL((int)((float)(uly)*4.0F), 0, 12); \ + _g->words.w1 = _SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)((float)(lrx)*4.0F), 12, 12) | \ + _SHIFTL((int)((float)(lry)*4.0F), 0, 12); \ +} + + +#define gDPSetScissorFrac(pkt, mode, ulx, uly, lrx, lry) \ +{ \ + Gfx *_g = (Gfx *)pkt; \ + \ + _g->words.w0 = _SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((ulx)), 12, 12) | \ + _SHIFTL((int)((uly)), 0, 12); \ + _g->words.w1 = _SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)((lrx)), 12, 12) | \ + _SHIFTL((int)((lry)), 0, 12); \ +} + +#define gsDPSetScissor(mode, ulx, uly, lrx, lry) \ +{ \ + _SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((float)(ulx)*4.0F), 12, 12) | \ + _SHIFTL((int)((float)(uly)*4.0F), 0, 12), \ + _SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)((float)(lrx)*4.0F), 12, 12) | \ + _SHIFTL((int)((float)(lry)*4.0F), 0, 12) \ +} + +#define gsDPSetScissorFrac(mode, ulx, uly, lrx, lry) \ +{ \ + _SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((ulx)), 12, 12) | \ + _SHIFTL((int)((uly)), 0, 12), \ + _SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)(lrx), 12, 12) | \ + _SHIFTL((int)(lry), 0, 12) \ +} + +/* Fraction never used in fill */ +#define gDPFillRectangle(pkt, ulx, uly, lrx, lry) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | \ + _SHIFTL((lrx), 14, 10) | _SHIFTL((lry), 2, 10));\ + _g->words.w1 = (_SHIFTL((ulx), 14, 10) | _SHIFTL((uly), 2, 10));\ +} + +#define gsDPFillRectangle(ulx, uly, lrx, lry) \ +{ \ + (_SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL((lrx), 14, 10) | \ + _SHIFTL((lry), 2, 10)), \ + (_SHIFTL((ulx), 14, 10) | _SHIFTL((uly), 2, 10)) \ +} + +/* like gDPFillRectangle but accepts negative arguments */ +#define gDPScisFillRectangle(pkt, ulx, uly, lrx, lry) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | \ + _SHIFTL(MAX((lrx),0), 14, 10) | \ + _SHIFTL(MAX((lry),0), 2, 10)); \ + _g->words.w1 = (_SHIFTL(MAX((ulx),0), 14, 10) | \ + _SHIFTL(MAX((uly),0), 2, 10)); \ +} + +#define gDPSetConvert(pkt, k0, k1, k2, k3, k4, k5) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETCONVERT, 24, 8) | \ + _SHIFTL(k0, 13, 9) | _SHIFTL(k1, 4, 9) | \ + _SHIFTR(k2, 5, 4)); \ + _g->words.w1 = (_SHIFTL(k2, 27, 5) | _SHIFTL(k3, 18, 9) | \ + _SHIFTL(k4, 9, 9) | _SHIFTL(k5, 0, 9)); \ +} + +#define gsDPSetConvert(k0, k1, k2, k3, k4, k5) \ +{ \ + (_SHIFTL(G_SETCONVERT, 24, 8) | \ + _SHIFTL(k0, 13, 9) | _SHIFTL(k1, 4, 9) | _SHIFTL(k2, 5, 4)), \ + (_SHIFTL(k2, 27, 5) | _SHIFTL(k3, 18, 9) | _SHIFTL(k4, 9, 9) | \ + _SHIFTL(k5, 0, 9)) \ +} + +#define gDPSetKeyR(pkt, cR, sR, wR) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETKEYR, 24, 8); \ + _g->words.w1 = (_SHIFTL(wR, 16, 12) | _SHIFTL(cR, 8, 8) | \ + _SHIFTL(sR, 0, 8)); \ +} + +#define gsDPSetKeyR(cR, sR, wR) \ +{ \ + _SHIFTL(G_SETKEYR, 24, 8), \ + _SHIFTL(wR, 16, 12) | _SHIFTL(cR, 8, 8) | _SHIFTL(sR, 0, 8) \ +} + +#define gDPSetKeyGB(pkt, cG, sG, wG, cB, sB, wB) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETKEYGB, 24, 8) | \ + _SHIFTL(wG, 12, 12) | _SHIFTL(wB, 0, 12)); \ + _g->words.w1 = (_SHIFTL(cG, 24, 8) | _SHIFTL(sG, 16, 8) | \ + _SHIFTL(cB, 8, 8) | _SHIFTL(sB, 0, 8)); \ +} + +#define gsDPSetKeyGB(cG, sG, wG, cB, sB, wB) \ +{ \ + (_SHIFTL(G_SETKEYGB, 24, 8) | _SHIFTL(wG, 12, 12) | \ + _SHIFTL(wB, 0, 12)), \ + (_SHIFTL(cG, 24, 8) | _SHIFTL(sG, 16, 8) | _SHIFTL(cB, 8, 8) | \ + _SHIFTL(sB, 0, 8)) \ +} + +#define gDPNoParam(pkt, cmd) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(cmd, 24, 8); \ + _g->words.w1 = 0; \ +} + +#define gsDPNoParam(cmd) \ +{ \ + _SHIFTL(cmd, 24, 8), 0 \ +} + +#define gDPParam(pkt, cmd, param) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(cmd, 24, 8); \ + _g->words.w1 = (param); \ +} + +#define gsDPParam(cmd, param) \ +{ \ + _SHIFTL(cmd, 24, 8), (param) \ +} + +/* Notice that textured rectangles are 128-bit commands, therefore + * gsDPTextureRectangle() should not be used in display lists + * under normal circumstances (use gsSPTextureRectangle()). + * That is also why there is no gDPTextureRectangle() macros. + */ +#define gsDPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \ +}, \ +{ \ + _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), \ + _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) \ +} + +#define gDPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + if (pkt); \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + _g ++; \ + _g->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ + _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ +} + +#define gsDPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \ +}, \ +{ \ + _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), \ + _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) \ +} + +#define gDPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + if (pkt); \ + _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + _g ++; \ + _g->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ + _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ +} + +#define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ + (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)),\ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \ + gsImmp1(G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ + gsImmp1(G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) + +#define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + gImmp1(pkt, G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ + gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)));\ +} + +/* like gSPTextureRectangle but accepts negative position arguments */ +#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((s16)(xh),0), 12, 12) | \ + _SHIFTL(MAX((s16)(yh),0), 0, 12)); \ + _g->words.w1 = (_SHIFTL((tile), 24, 3) | \ + _SHIFTL(MAX((s16)(xl),0), 12, 12) | \ + _SHIFTL(MAX((s16)(yl),0), 0, 12)); \ + gImmp1(pkt, G_RDPHALF_1, \ + (_SHIFTL(((s) - \ + (((s16)(xl) < 0) ? \ + (((s16)(dsdx) < 0) ? \ + (MAX((((s16)(xl)*(s16)(dsdx))>>7),0)) : \ + (MIN((((s16)(xl)*(s16)(dsdx))>>7),0))) : 0)), \ + 16, 16) | \ + _SHIFTL(((t) - \ + (((yl) < 0) ? \ + (((s16)(dtdy) < 0) ? \ + (MAX((((s16)(yl)*(s16)(dtdy))>>7),0)) : \ + (MIN((((s16)(yl)*(s16)(dtdy))>>7),0))) : 0)), \ + 0, 16))); \ + gImmp1(pkt, G_RDPHALF_2, (_SHIFTL((dsdx), 16, 16) | \ + _SHIFTL((dtdy), 0, 16))); \ +} + +#define gsSPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ + (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \ + gsImmp1(G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ + gsImmp1(G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) + +#define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) |\ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + gImmp1(pkt, G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ + gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \ +} + +#define gsDPWord(wordhi, wordlo) \ + gsImmp1(G_RDPHALF_1, (unsigned int)(wordhi)), \ + gsImmp1(G_RDPHALF_2, (unsigned int)(wordlo)) + +#define gDPWord(pkt, wordhi, wordlo) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + gImmp1(pkt, G_RDPHALF_1, (unsigned int)(wordhi)); \ + gImmp1(pkt, G_RDPHALF_2, (unsigned int)(wordlo)); \ +} + +#define gDPFullSync(pkt) gDPNoParam(pkt, G_RDPFULLSYNC) +#define gsDPFullSync() gsDPNoParam(G_RDPFULLSYNC) +#define gDPTileSync(pkt) gDPNoParam(pkt, G_RDPTILESYNC) +#define gsDPTileSync() gsDPNoParam(G_RDPTILESYNC) +#define gDPPipeSync(pkt) gDPNoParam(pkt, G_RDPPIPESYNC) +#define gsDPPipeSync() gsDPNoParam(G_RDPPIPESYNC) +#define gDPLoadSync(pkt) gDPNoParam(pkt, G_RDPLOADSYNC) +#define gsDPLoadSync() gsDPNoParam(G_RDPLOADSYNC) +#define gDPNoOp(pkt) gDPNoParam(pkt, G_NOOP) +#define gsDPNoOp() gsDPNoParam(G_NOOP) +#define gDPNoOpTag(pkt, tag) gDPParam(pkt, G_NOOP, tag) +#define gsDPNoOpTag(tag) gsDPParam(G_NOOP, tag) + +#endif + +/* Private macro to wrap other macros in do {...} while (0) */ +#define _DW(macro) do {macro} while (0) + #endif diff --git a/include/PR/mbi.h b/include/PR/mbi.h new file mode 100644 index 0000000000..0f8503d1f6 --- /dev/null +++ b/include/PR/mbi.h @@ -0,0 +1,100 @@ +#ifndef _MBI_H_ +#define _MBI_H_ + +/************************************************************************** + * * + * Copyright (C) 1994, Silicon Graphics, Inc. * + * * + * These coded instructions, statements, and computer programs contain * + * unpublished proprietary information of Silicon Graphics, Inc., and * + * are protected by Federal copyright law. They may not be disclosed * + * to third parties or copied or duplicated in any form, in whole or * + * in part, without the prior written consent of Silicon Graphics, Inc. * + * * + **************************************************************************/ + +/************************************************************************** + * + * $Revision: 1.136 $ + * $Date: 1999/01/05 13:04:00 $ + * $Source: /hosts/gate3/exdisk2/cvs/N64OS/Master/cvsmdev2/PR/include/mbi.h,v $ + * + **************************************************************************/ + +/* + * Header file for the Media Binary Interface + * + * NOTE: This file is included by the RSP microcode, so any C-specific + * constructs must be bracketed by #ifdef _LANGUAGE_C + * + */ + + +/* + * the SHIFT macros are used to build display list commands, inserting + * bit-fields into a 32-bit word. They take a value, a shift amount, + * and a width. + * + * For the left shift, the lower bits of the value are masked, + * then shifted left. + * + * For the right shift, the value is shifted right, then the lower bits + * are masked. + * + * (NOTE: _SHIFTL(v, 0, 32) won't work, just use an assignment) + * + */ +#define _SHIFTL(v, s, w) \ + ((unsigned int) (((unsigned int)(v) & ((0x01 << (w)) - 1)) << (s))) +#define _SHIFTR(v, s, w) \ + ((unsigned int)(((unsigned int)(v) >> (s)) & ((0x01 << (w)) - 1))) + +#define _SHIFT _SHIFTL /* old, for compatibility only */ + +#define G_ON (1) +#define G_OFF (0) + +/************************************************************************** + * + * Graphics Binary Interface + * + **************************************************************************/ + +#include + +/************************************************************************** + * + * Audio Binary Interface + * + **************************************************************************/ + +#include + +/************************************************************************** + * + * Task list + * + **************************************************************************/ + +#define M_GFXTASK 1 +#define M_AUDTASK 2 +#define M_VIDTASK 3 +#define M_HVQTASK 6 +#define M_HVQMTASK 7 + +/************************************************************************** + * + * Segment macros and definitions + * + **************************************************************************/ + +#define NUM_SEGMENTS (16) +#define SEGMENT_OFFSET(a) ((unsigned int)(a) & 0x00ffffff) +#define SEGMENT_NUMBER(a) (((unsigned int)(a) << 4) >> 28) +#define SEGMENT_ADDR(num, off) (((num) << 24) + (off)) + +#ifndef NULL +#define NULL 0 +#endif + +#endif /* !_MBI_H_ */ diff --git a/include/PR/ultratypes.h b/include/PR/ultratypes.h index da894df75f..d648e9b1d9 100644 --- a/include/PR/ultratypes.h +++ b/include/PR/ultratypes.h @@ -22,6 +22,11 @@ typedef volatile long long vs64; typedef float f32; typedef double f64; -#define NULL ((void*)0) +typedef long int Mtx_t[4][4]; +typedef union +{ + Mtx_t m; + long long int forc_structure_alignment; +} Mtx; #endif