Mario Kart 64
Loading...
Searching...
No Matches
gbi.h
Go to the documentation of this file.
1/**************************************************************************
2 * *
3 * Copyright (C) 1994, Silicon Graphics, Inc. *
4 * *
5 * These coded instructions, statements, and computer programs contain *
6 * unpublished proprietary information of Silicon Graphics, Inc., and *
7 * are protected by Federal copyright law. They may not be disclosed *
8 * to third parties or copied or duplicated in any form, in whole or *
9 * in part, without the prior written consent of Silicon Graphics, Inc. *
10 * *
11 **************************************************************************/
12/**************************************************************************
13 *
14 * $Revision: 1.141 $
15 * $Date: 1999/09/03 03:43:08 $
16 * $Source: /exdisk2/cvs/N64OS/Master/cvsmdev2/PR/include/gbi.h,v $
17 *
18 **************************************************************************/
19
20#ifndef _GBI_H_
21#define _GBI_H_
22
23#include <PR/ultratypes.h>
24
25/*
26 * To use the F3DEX ucodes, define F3DEX_GBI before include this file.
27 *
28 * #define F3DEX_GBI
29 * #include <ultra64.h>
30 *
31 * or
32 *
33 * cc -c -DF3DEX_GBI -I.... foo.c
34 *
35 */
36
37/**************************************************************************
38 *
39 * Graphics Binary Interface
40 *
41 **************************************************************************/
42
43/*
44 * Graphics Commands, 'xxx' parts may be generated from ucode
45 *
46 * The command format is
47 *
48 * |00xxxxxx| = DMA 0,..,127
49 * |10xxxxxx| = Immediate Mode -65,..,-128
50 * |11xxxxxx| = RDP cmds -1,..,-64
51 *
52 * Note: in order for the RSP microcode to process RDP commands opaquely,
53 * we need to further identify those RDP commands that need DRAM address
54 * "fixup". To do this, we have the dummy command G_RDP_ADDR_FIXUP, and
55 * all |RDP commands| less than this are commands with embedded DRAM
56 * addresses. Further, the format of these commands should be similar so
57 * only one fixup routine is needed.
58 *
59 * Further explanation:
60 * The names of the commands are somewhat misleading. Here is clarification:
61 *
62 * - a 'DMA' type command has a pointer to additional data and
63 * causes a DMA transfer to bring that into DMEM.
64 *
65 * - an 'Immediate' type command isn't really 'immediate', in the
66 * traditional sense. This just means that the entire command fits
67 * in the 64-bit word, and the ucode can execute it 'immediately'
68 * without additional memory transfers.
69 *
70 * - an 'RDP' command is identified as such because the RDP
71 * commands can be passed-thru the RSP and sent to the RDP
72 * directly. One further confusing thing, is that some 'DP'
73 * macros below actually generate immediate commands, not
74 * not direct DP commands.
75 *
76 * IMPLEMENTATION NOTE:
77 * There is another group of RDP commands that includes the triangle commands
78 * generated by the RSP code. These are the raw commands the rasterizer
79 * hardware chews on, with slope info, etc. They will follow the RDP
80 * ordering...
81 *
82 * IMPLEMENTATION NOTE:
83 * The RDP hardware has some of these bit patterns wired up. If the hardware
84 * changes, we must adjust this table, likewise we can't change/add things
85 * once the hardware is frozen. (actually, the RDP hardware only looks at
86 * the lower 6 bits of the command byte)
87 *
88 */
89
90#ifdef F3DEX_GBI_2
91#ifndef F3DEX_GBI
92#define F3DEX_GBI
93#endif
94#define G_NOOP 0x00
95#define G_RDPHALF_2 0xf1
96#define G_SETOTHERMODE_H 0xe3
97#define G_SETOTHERMODE_L 0xe2
98#define G_RDPHALF_1 0xe1
99#define G_SPNOOP 0xe0
100#define G_ENDDL 0xdf
101#define G_DL 0xde
102#define G_LOAD_UCODE 0xdd
103#define G_MOVEMEM 0xdc
104#define G_MOVEWORD 0xdb
105#define G_MTX 0xda
106#define G_GEOMETRYMODE 0xd9
107#define G_POPMTX 0xd8
108#define G_TEXTURE 0xd7
109#define G_DMA_IO 0xd6
110#define G_SPECIAL_1 0xd5
111#define G_SPECIAL_2 0xd4
112#define G_SPECIAL_3 0xd3
113
114#define G_VTX 0x01
115#define G_MODIFYVTX 0x02
116#define G_CULLDL 0x03
117#define G_BRANCH_Z 0x04
118#define G_TRI1 0x05
119#define G_TRI2 0x06
120#define G_QUAD 0x07
121#define G_LINE3D 0x08
122#else /* F3DEX_GBI_2 */
123
124/* DMA commands: */
125#define G_SPNOOP 0 /* handle 0 gracefully */
126#define G_MTX 1
127#define G_RESERVED0 2 /* not implemeted */
128#define G_MOVEMEM 3 /* move a block of memory (up to 4 words) to dmem */
129#define G_VTX 4
130#define G_RESERVED1 5 /* not implemeted */
131#define G_DL 6
132#define G_RESERVED2 7 /* not implemeted */
133#define G_RESERVED3 8 /* not implemeted */
134#define G_SPRITE2D_BASE 9 /* sprite command */
135
136/* IMMEDIATE commands: */
137#define G_IMMFIRST -65
138#define G_TRI1 (G_IMMFIRST - 0)
139#define G_CULLDL (G_IMMFIRST - 1)
140#define G_POPMTX (G_IMMFIRST - 2)
141#define G_MOVEWORD (G_IMMFIRST - 3)
142#define G_TEXTURE (G_IMMFIRST - 4)
143#define G_SETOTHERMODE_H (G_IMMFIRST - 5)
144#define G_SETOTHERMODE_L (G_IMMFIRST - 6)
145#define G_ENDDL (G_IMMFIRST - 7)
146#define G_SETGEOMETRYMODE (G_IMMFIRST - 8)
147#define G_CLEARGEOMETRYMODE (G_IMMFIRST - 9)
148#define G_LINE3D (G_IMMFIRST - 10)
149#define G_RDPHALF_1 (G_IMMFIRST - 11)
150#define G_RDPHALF_2 (G_IMMFIRST - 12)
151#define G_RDPHALF_CONT (G_IMMFIRST - 13) // From F3D_OLD used to render lap & timer UI.
152#if (defined(F3DEX_GBI) || defined(F3DLP_GBI))
153#ifndef F3D_OLD
154#define G_MODIFYVTX (G_IMMFIRST - 13) // older versions of f3dex still used G_RDPHALF_CONT
155#endif
156#define G_TRI2 (G_IMMFIRST - 14)
157#define G_BRANCH_Z (G_IMMFIRST - 15)
158#define G_LOAD_UCODE (G_IMMFIRST - 16)
159#define G_QUAD (G_IMMFIRST - 10)
160#endif
161
162/* We are overloading 2 of the immediate commands
163 to keep the byte alignment of dmem the same */
164
165#define G_SPRITE2D_SCALEFLIP (G_IMMFIRST - 1)
166#define G_SPRITE2D_DRAW (G_IMMFIRST - 2)
167
168/* RDP commands: */
169#define G_NOOP 0xc0 /* 0 */
170
171#endif /* F3DEX_GBI_2 */
172
173/* RDP commands: */
174#define G_SETCIMG 0xff /* -1 */
175#define G_SETZIMG 0xfe /* -2 */
176#define G_SETTIMG 0xfd /* -3 */
177#define G_SETCOMBINE 0xfc /* -4 */
178#define G_SETENVCOLOR 0xfb /* -5 */
179#define G_SETPRIMCOLOR 0xfa /* -6 */
180#define G_SETBLENDCOLOR 0xf9 /* -7 */
181#define G_SETFOGCOLOR 0xf8 /* -8 */
182#define G_SETFILLCOLOR 0xf7 /* -9 */
183#define G_FILLRECT 0xf6 /* -10 */
184#define G_SETTILE 0xf5 /* -11 */
185#define G_LOADTILE 0xf4 /* -12 */
186#define G_LOADBLOCK 0xf3 /* -13 */
187#define G_SETTILESIZE 0xf2 /* -14 */
188#define G_LOADTLUT 0xf0 /* -16 */
189#define G_RDPSETOTHERMODE 0xef /* -17 */
190#define G_SETPRIMDEPTH 0xee /* -18 */
191#define G_SETSCISSOR 0xed /* -19 */
192#define G_SETCONVERT 0xec /* -20 */
193#define G_SETKEYR 0xeb /* -21 */
194#define G_SETKEYGB 0xea /* -22 */
195#define G_RDPFULLSYNC 0xe9 /* -23 */
196#define G_RDPTILESYNC 0xe8 /* -24 */
197#define G_RDPPIPESYNC 0xe7 /* -25 */
198#define G_RDPLOADSYNC 0xe6 /* -26 */
199#define G_TEXRECTFLIP 0xe5 /* -27 */
200#define G_TEXRECT 0xe4 /* -28 */
201
202/*
203 * The following commands are the "generated" RDP commands; the user
204 * never sees them, the RSP microcode generates them.
205 *
206 * The layout of the bits is magical, to save work in the ucode.
207 * These id's are -56, -52, -54, -50, -55, -51, -53, -49, ...
208 * edge, shade, texture, zbuff bits: estz
209 */
210#define G_TRI_FILL 0xc8 /* fill triangle: 11001000 */
211#define G_TRI_SHADE 0xcc /* shade triangle: 11001100 */
212#define G_TRI_TXTR 0xca /* texture triangle: 11001010 */
213#define G_TRI_SHADE_TXTR 0xce /* shade, texture triangle: 11001110 */
214#define G_TRI_FILL_ZBUFF 0xc9 /* fill, zbuff triangle: 11001001 */
215#define G_TRI_SHADE_ZBUFF 0xcd /* shade, zbuff triangle: 11001101 */
216#define G_TRI_TXTR_ZBUFF 0xcb /* texture, zbuff triangle: 11001011 */
217#define G_TRI_SHADE_TXTR_ZBUFF 0xcf /* shade, txtr, zbuff trngl: 11001111 */
218
219/*
220 * A TRI_FILL triangle is just the edges. You need to set the DP
221 * to use primcolor, in order to see anything. (it is NOT a triangle
222 * that gets rendered in 'fill mode'. Triangles can't be rendered
223 * in 'fill mode')
224 *
225 * A TRI_SHADE is a gouraud triangle that has colors interpolated.
226 * Flat-shaded triangles (from the software) are still gouraud shaded,
227 * it's just the colors are all the same and the deltas are 0.
228 *
229 * Other triangle types, and combinations are more obvious.
230 */
231
232/* masks to build RDP triangle commands: */
233#define G_RDP_TRI_FILL_MASK 0x08
234#define G_RDP_TRI_SHADE_MASK 0x04
235#define G_RDP_TRI_TXTR_MASK 0x02
236#define G_RDP_TRI_ZBUFF_MASK 0x01
237
238/*
239 * HACK:
240 * This is a dreadful hack. For version 1.0 hardware, there are still
241 * some 'bowtie' hangs. This parameter can be increased to avoid
242 * the hangs. Every increase of 4 chops one scanline off of every
243 * triangle. Values of 4,8,12 should be sufficient to avoid any
244 * bowtie hang.
245 *
246 * Change this value, then recompile ALL of your program (including static
247 * display lists!)
248 *
249 * THIS WILL BE REMOVED FOR HARDWARE VERSION 2.0!
250 */
251#define BOWTIE_VAL 0
252
253/* gets added to RDP command, in order to test for addres fixup: */
254#define G_RDP_ADDR_FIXUP 3 /* |RDP cmds| <= this, do addr fixup */
255#ifdef _LANGUAGE_ASSEMBLY
256#define G_RDP_TEXRECT_CHECK ((-1 * G_TEXRECTFLIP) & 0xff)
257#endif
258
259/* macros for command parsing: */
260#define GDMACMD(x) (x)
261#define GIMMCMD(x) (G_IMMFIRST - (x))
262#define GRDPCMD(x) (0xff - (x))
263
264#define G_DMACMDSIZ 128
265#define G_IMMCMDSIZ 64
266#define G_RDPCMDSIZ 64
267
268/*
269 * Coordinate shift values, number of bits of fraction
270 */
271#define G_TEXTURE_IMAGE_FRAC 2
272#define G_TEXTURE_SCALE_FRAC 16
273#define G_SCALE_FRAC 8
274#define G_ROTATE_FRAC 16
275
276/*
277 * Parameters to graphics commands
278 */
279
280/*
281 * Data packing macros
282 */
283
284/*
285 * Maximum z-buffer value, used to initialize the z-buffer.
286 * Note : this number is NOT the viewport z-scale constant.
287 * See the comment next to G_MAXZ for more info.
288 */
289#define G_MAXFBZ 0x3fff /* 3b exp, 11b mantissa */
290
291#define GPACK_RGBA5551(r, g, b, a) ((((r) << 8) & 0xf800) | (((g) << 3) & 0x7c0) | (((b) >> 2) & 0x3e) | ((a) & 0x1))
292#define GPACK_ZDZ(z, dz) ((z) << 2 | (dz))
293
294/*
295 * G_MTX: parameter flags
296 */
297#ifdef F3DEX_GBI_2
298#define G_MTX_MODELVIEW 0x00 /* matrix types */
299#define G_MTX_PROJECTION 0x04
300#define G_MTX_MUL 0x00 /* concat or load */
301#define G_MTX_LOAD 0x02
302#define G_MTX_NOPUSH 0x00 /* push or not */
303#define G_MTX_PUSH 0x01
304#else /* F3DEX_GBI_2 */
305#define G_MTX_MODELVIEW 0x00 /* matrix types */
306#define G_MTX_PROJECTION 0x01
307#define G_MTX_MUL 0x00 /* concat or load */
308#define G_MTX_LOAD 0x02
309#define G_MTX_NOPUSH 0x00 /* push or not */
310#define G_MTX_PUSH 0x04
311#endif /* F3DEX_GBI_2 */
312
313/*
314 * flags for G_SETGEOMETRYMODE
315 * (this rendering state is maintained in RSP)
316 *
317 * DO NOT USE THE LOW 8 BITS OF GEOMETRYMODE:
318 * The weird bit-ordering is for the micro-code: the lower byte
319 * can be OR'd in with G_TRI_SHADE (11001100) to construct
320 * the triangle command directly. Don't break it...
321 *
322 * DO NOT USE THE HIGH 8 BITS OF GEOMETRYMODE:
323 * The high byte is OR'd with 0x703 to form the clip code mask.
324 * If it is set to 0x04, this will cause near clipping to occur.
325 * If it is zero, near clipping will not occur.
326 *
327 * Further explanation:
328 * G_SHADE is necessary in order to see the color that you passed
329 * down with the vertex. If G_SHADE isn't set, you need to set the DP
330 * appropriately and use primcolor to see anything.
331 *
332 * G_SHADING_SMOOTH enabled means use all 3 colors of the triangle.
333 * If it is not set, then do 'flat shading', where only one vertex color
334 * is used (and all 3 vertices are set to that same color by the ucode)
335 * See the man page for gSP1Triangle().
336 *
337 */
338#define G_ZBUFFER 0x00000001
339#define G_SHADE 0x00000004 /* enable Gouraud interp */
340/* rest of low byte reserved for setup ucode */
341#ifdef F3DEX_GBI_2
342#define G_TEXTURE_ENABLE 0x00000000 /* Ignored */
343#define G_SHADING_SMOOTH 0x00200000 /* flat or smooth shaded */
344#define G_CULL_FRONT 0x00000200
345#define G_CULL_BACK 0x00000400
346#define G_CULL_BOTH 0x00000600 /* To make code cleaner */
347#else
348#define G_TEXTURE_ENABLE 0x00000002 /* Microcode use only */
349#define G_SHADING_SMOOTH 0x00000200 /* flat or smooth shaded */
350#define G_CULL_FRONT 0x00001000
351#define G_CULL_BACK 0x00002000
352#define G_CULL_BOTH 0x00003000 /* To make code cleaner */
353#endif
354#define G_FOG 0x00010000
355#define G_LIGHTING 0x00020000
356#define G_TEXTURE_GEN 0x00040000
357#define G_TEXTURE_GEN_LINEAR 0x00080000
358#define G_LOD 0x00100000 /* NOT IMPLEMENTED */
359#if (defined(F3DEX_GBI) || defined(F3DLP_GBI))
360#define G_CLIPPING 0x00800000
361#else
362#define G_CLIPPING 0x00000000
363#endif
364
365#ifdef _LANGUAGE_ASSEMBLY
366#define G_FOG_H (G_FOG / 0x10000)
367#define G_LIGHTING_H (G_LIGHTING / 0x10000)
368#define G_TEXTURE_GEN_H (G_TEXTURE_GEN / 0x10000)
369#define G_TEXTURE_GEN_LINEAR_H (G_TEXTURE_GEN_LINEAR / 0x10000)
370#define G_LOD_H (G_LOD / 0x10000) /* NOT IMPLEMENTED */
371#if (defined(F3DEX_GBI) || defined(F3DLP_GBI))
372#define G_CLIPPING_H (G_CLIPPING / 0x10000)
373#endif
374#endif
375
376/* Need these defined for Sprite Microcode */
377#ifdef _LANGUAGE_ASSEMBLY
378#define G_TX_LOADTILE 7
379#define G_TX_RENDERTILE 0
380
381#define G_TX_NOMIRROR 0
382#define G_TX_WRAP 0
383#define G_TX_MIRROR 0x1
384#define G_TX_CLAMP 0x2
385#define G_TX_NOMASK 0
386#define G_TX_NOLOD 0
387#endif
388
389/*
390 * G_SETIMG fmt: set image formats
391 */
392#define G_IM_FMT_RGBA 0
393#define G_IM_FMT_YUV 1
394#define G_IM_FMT_CI 2
395#define G_IM_FMT_IA 3
396#define G_IM_FMT_I 4
397
398/*
399 * G_SETIMG siz: set image pixel size
400 */
401#define G_IM_SIZ_4b 0
402#define G_IM_SIZ_8b 1
403#define G_IM_SIZ_16b 2
404#define G_IM_SIZ_32b 3
405#define G_IM_SIZ_DD 5
406
407#define G_IM_SIZ_4b_BYTES 0
408#define G_IM_SIZ_4b_TILE_BYTES G_IM_SIZ_4b_BYTES
409#define G_IM_SIZ_4b_LINE_BYTES G_IM_SIZ_4b_BYTES
410
411#define G_IM_SIZ_8b_BYTES 1
412#define G_IM_SIZ_8b_TILE_BYTES G_IM_SIZ_8b_BYTES
413#define G_IM_SIZ_8b_LINE_BYTES G_IM_SIZ_8b_BYTES
414
415#define G_IM_SIZ_16b_BYTES 2
416#define G_IM_SIZ_16b_TILE_BYTES G_IM_SIZ_16b_BYTES
417#define G_IM_SIZ_16b_LINE_BYTES G_IM_SIZ_16b_BYTES
418
419#define G_IM_SIZ_32b_BYTES 4
420#define G_IM_SIZ_32b_TILE_BYTES 2
421#define G_IM_SIZ_32b_LINE_BYTES 2
422
423#define G_IM_SIZ_4b_LOAD_BLOCK G_IM_SIZ_16b
424#define G_IM_SIZ_8b_LOAD_BLOCK G_IM_SIZ_16b
425#define G_IM_SIZ_16b_LOAD_BLOCK G_IM_SIZ_16b
426#define G_IM_SIZ_32b_LOAD_BLOCK G_IM_SIZ_32b
427
428#define G_IM_SIZ_4b_SHIFT 2
429#define G_IM_SIZ_8b_SHIFT 1
430#define G_IM_SIZ_16b_SHIFT 0
431#define G_IM_SIZ_32b_SHIFT 0
432
433#define G_IM_SIZ_4b_INCR 3
434#define G_IM_SIZ_8b_INCR 1
435#define G_IM_SIZ_16b_INCR 0
436#define G_IM_SIZ_32b_INCR 0
437
438/*
439 * G_SETCOMBINE: color combine modes
440 */
441/* Color combiner constants: */
442#define G_CCMUX_COMBINED 0
443#define G_CCMUX_TEXEL0 1
444#define G_CCMUX_TEXEL1 2
445#define G_CCMUX_PRIMITIVE 3
446#define G_CCMUX_SHADE 4
447#define G_CCMUX_ENVIRONMENT 5
448#define G_CCMUX_CENTER 6
449#define G_CCMUX_SCALE 6
450#define G_CCMUX_COMBINED_ALPHA 7
451#define G_CCMUX_TEXEL0_ALPHA 8
452#define G_CCMUX_TEXEL1_ALPHA 9
453#define G_CCMUX_PRIMITIVE_ALPHA 10
454#define G_CCMUX_SHADE_ALPHA 11
455#define G_CCMUX_ENV_ALPHA 12
456#define G_CCMUX_LOD_FRACTION 13
457#define G_CCMUX_PRIM_LOD_FRAC 14
458#define G_CCMUX_NOISE 7
459#define G_CCMUX_K4 7
460#define G_CCMUX_K5 15
461#define G_CCMUX_1 6
462#define G_CCMUX_0 31
463
464/* Alpha combiner constants: */
465#define G_ACMUX_COMBINED 0
466#define G_ACMUX_TEXEL0 1
467#define G_ACMUX_TEXEL1 2
468#define G_ACMUX_PRIMITIVE 3
469#define G_ACMUX_SHADE 4
470#define G_ACMUX_ENVIRONMENT 5
471#define G_ACMUX_LOD_FRACTION 0
472#define G_ACMUX_PRIM_LOD_FRAC 6
473#define G_ACMUX_1 6
474#define G_ACMUX_0 7
475
476/* typical CC cycle 1 modes */
477#define G_CC_PRIMITIVE 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE
478#define G_CC_SHADE 0, 0, 0, SHADE, 0, 0, 0, SHADE
479
480#define G_CC_MODULATEI TEXEL0, 0, SHADE, 0, 0, 0, 0, SHADE
481#define G_CC_MODULATEIDECALA TEXEL0, 0, SHADE, 0, 0, 0, 0, TEXEL0
482#define G_CC_MODULATEIFADE TEXEL0, 0, SHADE, 0, 0, 0, 0, ENVIRONMENT
483
484#define G_CC_MODULATERGB G_CC_MODULATEI
485#define G_CC_MODULATERGBDECALA G_CC_MODULATEIDECALA
486#define G_CC_MODULATERGBFADE G_CC_MODULATEIFADE
487
488#define G_CC_MODULATEIA TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0
489#define G_CC_MODULATEIFADEA TEXEL0, 0, SHADE, 0, TEXEL0, 0, ENVIRONMENT, 0
490
491#define G_CC_MODULATEFADE TEXEL0, 0, SHADE, 0, ENVIRONMENT, 0, TEXEL0, 0
492
493#define G_CC_MODULATERGBA G_CC_MODULATEIA
494#define G_CC_MODULATERGBFADEA G_CC_MODULATEIFADEA
495
496#define G_CC_MODULATEI_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE
497#define G_CC_MODULATEIA_PRIM TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0
498#define G_CC_MODULATEIDECALA_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL0
499
500#define G_CC_MODULATERGB_PRIM G_CC_MODULATEI_PRIM
501#define G_CC_MODULATERGBA_PRIM G_CC_MODULATEIA_PRIM
502#define G_CC_MODULATERGBDECALA_PRIM G_CC_MODULATEIDECALA_PRIM
503
504#define G_CC_FADE SHADE, 0, ENVIRONMENT, 0, SHADE, 0, ENVIRONMENT, 0
505#define G_CC_FADEA TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0
506
507#define G_CC_DECALRGB 0, 0, 0, TEXEL0, 0, 0, 0, SHADE
508#define G_CC_DECALRGBA 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0
509#define G_CC_DECALFADE 0, 0, 0, TEXEL0, 0, 0, 0, ENVIRONMENT
510
511#define G_CC_DECALFADEA 0, 0, 0, TEXEL0, TEXEL0, 0, ENVIRONMENT, 0
512
513#define G_CC_BLENDI ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE
514#define G_CC_BLENDIA ENVIRONMENT, SHADE, TEXEL0, SHADE, TEXEL0, 0, SHADE, 0
515#define G_CC_BLENDIDECALA ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0
516
517#define G_CC_BLENDRGBA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, SHADE
518#define G_CC_BLENDRGBDECALA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, TEXEL0
519#define G_CC_BLENDRGBFADEA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, ENVIRONMENT
520
521#define G_CC_ADDRGB TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, SHADE
522#define G_CC_ADDRGBDECALA TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0
523#define G_CC_ADDRGBFADE TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, ENVIRONMENT
524
525#define G_CC_REFLECTRGB ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, SHADE
526#define G_CC_REFLECTRGBDECALA ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0
527
528#define G_CC_HILITERGB PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE
529#define G_CC_HILITERGBA PRIMITIVE, SHADE, TEXEL0, SHADE, PRIMITIVE, SHADE, TEXEL0, SHADE
530#define G_CC_HILITERGBDECALA PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0
531
532#define G_CC_SHADEDECALA 0, 0, 0, SHADE, 0, 0, 0, TEXEL0
533#define G_CC_SHADEFADEA 0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT
534
535#define G_CC_BLENDPE PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, SHADE, 0
536#define G_CC_BLENDPEDECALA PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, TEXEL0
537
538/* oddball modes */
539#define _G_CC_BLENDPE ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, TEXEL0, 0, SHADE, 0
540#define _G_CC_BLENDPEDECALA ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, 0, 0, 0, TEXEL0
541#define _G_CC_TWOCOLORTEX PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE
542/* used for 1-cycle sparse mip-maps, primitive color has color of lowest LOD */
543#define _G_CC_SPARSEST PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0, PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0
544#define G_CC_TEMPLERP TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0, TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0
545
546/* typical CC cycle 1 modes, usually followed by other cycle 2 modes */
547#define G_CC_TRILERP TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0
548#define G_CC_INTERFERENCE TEXEL0, 0, TEXEL1, 0, TEXEL0, 0, TEXEL1, 0
549
550/*
551 * One-cycle color convert operation
552 */
553#define G_CC_1CYUV2RGB TEXEL0, K4, K5, TEXEL0, 0, 0, 0, SHADE
554
555/*
556 * NOTE: YUV2RGB expects TF step1 color conversion to occur in 2nd clock.
557 * Therefore, CC looks for step1 results in TEXEL1
558 */
559#define G_CC_YUV2RGB TEXEL1, K4, K5, TEXEL1, 0, 0, 0, 0
560
561/* typical CC cycle 2 modes */
562#define G_CC_PASS2 0, 0, 0, COMBINED, 0, 0, 0, COMBINED
563#define G_CC_MODULATEI2 COMBINED, 0, SHADE, 0, 0, 0, 0, SHADE
564#define G_CC_MODULATEIA2 COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0
565#define G_CC_MODULATERGB2 G_CC_MODULATEI2
566#define G_CC_MODULATERGBA2 G_CC_MODULATEIA2
567#define G_CC_MODULATEI_PRIM2 COMBINED, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE
568#define G_CC_MODULATEIA_PRIM2 COMBINED, 0, PRIMITIVE, 0, COMBINED, 0, PRIMITIVE, 0
569#define G_CC_MODULATERGB_PRIM2 G_CC_MODULATEI_PRIM2
570#define G_CC_MODULATERGBA_PRIM2 G_CC_MODULATEIA_PRIM2
571#define G_CC_DECALRGB2 0, 0, 0, COMBINED, 0, 0, 0, SHADE
572/*
573 * ?
574#define G_CC_DECALRGBA2 COMBINED, SHADE, COMBINED_ALPHA, SHADE, 0, 0, 0, SHADE
575*/
576#define G_CC_BLENDI2 ENVIRONMENT, SHADE, COMBINED, SHADE, 0, 0, 0, SHADE
577#define G_CC_BLENDIA2 ENVIRONMENT, SHADE, COMBINED, SHADE, COMBINED, 0, SHADE, 0
578#define G_CC_CHROMA_KEY2 TEXEL0, CENTER, SCALE, 0, 0, 0, 0, 0
579#define G_CC_HILITERGB2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, SHADE
580#define G_CC_HILITERGBA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, ENVIRONMENT, COMBINED, TEXEL0, COMBINED
581#define G_CC_HILITERGBDECALA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, TEXEL0
582#define G_CC_HILITERGBPASSA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, COMBINED
583
584/*
585 * G_SETOTHERMODE_L sft: shift count
586 */
587#define G_MDSFT_ALPHACOMPARE 0
588#define G_MDSFT_ZSRCSEL 2
589#define G_MDSFT_RENDERMODE 3
590#define G_MDSFT_BLENDER 16
591
592/*
593 * G_SETOTHERMODE_H sft: shift count
594 */
595#define G_MDSFT_BLENDMASK 0 /* unsupported */
596#define G_MDSFT_ALPHADITHER 4
597#define G_MDSFT_RGBDITHER 6
598
599#define G_MDSFT_COMBKEY 8
600#define G_MDSFT_TEXTCONV 9
601#define G_MDSFT_TEXTFILT 12
602#define G_MDSFT_TEXTLUT 14
603#define G_MDSFT_TEXTLOD 16
604#define G_MDSFT_TEXTDETAIL 17
605#define G_MDSFT_TEXTPERSP 19
606#define G_MDSFT_CYCLETYPE 20
607#define G_MDSFT_COLORDITHER 22 /* unsupported in HW 2.0 */
608#define G_MDSFT_PIPELINE 23
609
610/* G_SETOTHERMODE_H gPipelineMode */
611#define G_PM_1PRIMITIVE (1 << G_MDSFT_PIPELINE)
612#define G_PM_NPRIMITIVE (0 << G_MDSFT_PIPELINE)
613
614/* G_SETOTHERMODE_H gSetCycleType */
615#define G_CYC_1CYCLE (0 << G_MDSFT_CYCLETYPE)
616#define G_CYC_2CYCLE (1 << G_MDSFT_CYCLETYPE)
617#define G_CYC_COPY (2 << G_MDSFT_CYCLETYPE)
618#define G_CYC_FILL (3 << G_MDSFT_CYCLETYPE)
619
620/* G_SETOTHERMODE_H gSetTexturePersp */
621#define G_TP_NONE (0 << G_MDSFT_TEXTPERSP)
622#define G_TP_PERSP (1 << G_MDSFT_TEXTPERSP)
623
624/* G_SETOTHERMODE_H gSetTextureDetail */
625#define G_TD_CLAMP (0 << G_MDSFT_TEXTDETAIL)
626#define G_TD_SHARPEN (1 << G_MDSFT_TEXTDETAIL)
627#define G_TD_DETAIL (2 << G_MDSFT_TEXTDETAIL)
628
629/* G_SETOTHERMODE_H gSetTextureLOD */
630#define G_TL_TILE (0 << G_MDSFT_TEXTLOD)
631#define G_TL_LOD (1 << G_MDSFT_TEXTLOD)
632
633/* G_SETOTHERMODE_H gSetTextureLUT */
634#define G_TT_NONE (0 << G_MDSFT_TEXTLUT)
635#define G_TT_RGBA16 (2 << G_MDSFT_TEXTLUT)
636#define G_TT_IA16 (3 << G_MDSFT_TEXTLUT)
637
638/* G_SETOTHERMODE_H gSetTextureFilter */
639#define G_TF_POINT (0 << G_MDSFT_TEXTFILT)
640#define G_TF_AVERAGE (3 << G_MDSFT_TEXTFILT)
641#define G_TF_BILERP (2 << G_MDSFT_TEXTFILT)
642
643/* G_SETOTHERMODE_H gSetTextureConvert */
644#define G_TC_CONV (0 << G_MDSFT_TEXTCONV)
645#define G_TC_FILTCONV (5 << G_MDSFT_TEXTCONV)
646#define G_TC_FILT (6 << G_MDSFT_TEXTCONV)
647
648/* G_SETOTHERMODE_H gSetCombineKey */
649#define G_CK_NONE (0 << G_MDSFT_COMBKEY)
650#define G_CK_KEY (1 << G_MDSFT_COMBKEY)
651
652/* G_SETOTHERMODE_H gSetColorDither */
653#define G_CD_MAGICSQ (0 << G_MDSFT_RGBDITHER)
654#define G_CD_BAYER (1 << G_MDSFT_RGBDITHER)
655#define G_CD_NOISE (2 << G_MDSFT_RGBDITHER)
656
657#ifndef _HW_VERSION_1
658#define G_CD_DISABLE (3 << G_MDSFT_RGBDITHER)
659#define G_CD_ENABLE G_CD_NOISE /* HW 1.0 compatibility mode */
660#else
661#define G_CD_ENABLE (1 << G_MDSFT_COLORDITHER)
662#define G_CD_DISABLE (0 << G_MDSFT_COLORDITHER)
663#endif
664
665/* G_SETOTHERMODE_H gSetAlphaDither */
666#define G_AD_PATTERN (0 << G_MDSFT_ALPHADITHER)
667#define G_AD_NOTPATTERN (1 << G_MDSFT_ALPHADITHER)
668#define G_AD_NOISE (2 << G_MDSFT_ALPHADITHER)
669#define G_AD_DISABLE (3 << G_MDSFT_ALPHADITHER)
670
671/* G_SETOTHERMODE_L gSetAlphaCompare */
672#define G_AC_NONE (0 << G_MDSFT_ALPHACOMPARE)
673#define G_AC_THRESHOLD (1 << G_MDSFT_ALPHACOMPARE)
674#define G_AC_DITHER (3 << G_MDSFT_ALPHACOMPARE)
675
676/* G_SETOTHERMODE_L gSetDepthSource */
677#define G_ZS_PIXEL (0 << G_MDSFT_ZSRCSEL)
678#define G_ZS_PRIM (1 << G_MDSFT_ZSRCSEL)
679
680/* G_SETOTHERMODE_L gSetRenderMode */
681#define AA_EN 0x8
682#define Z_CMP 0x10
683#define Z_UPD 0x20
684#define IM_RD 0x40
685#define CLR_ON_CVG 0x80
686#define CVG_DST_CLAMP 0
687#define CVG_DST_WRAP 0x100
688#define CVG_DST_FULL 0x200
689#define CVG_DST_SAVE 0x300
690#define ZMODE_OPA 0
691#define ZMODE_INTER 0x400
692#define ZMODE_XLU 0x800
693#define ZMODE_DEC 0xc00
694#define CVG_X_ALPHA 0x1000
695#define ALPHA_CVG_SEL 0x2000
696#define FORCE_BL 0x4000
697#define TEX_EDGE 0x0000 /* used to be 0x8000 */
698
699#define G_BL_CLR_IN 0
700#define G_BL_CLR_MEM 1
701#define G_BL_CLR_BL 2
702#define G_BL_CLR_FOG 3
703#define G_BL_1MA 0
704#define G_BL_A_MEM 1
705#define G_BL_A_IN 0
706#define G_BL_A_FOG 1
707#define G_BL_A_SHADE 2
708#define G_BL_1 2
709#define G_BL_0 3
710
711#define GBL_c1(m1a, m1b, m2a, m2b) (m1a) << 30 | (m1b) << 26 | (m2a) << 22 | (m2b) << 18
712#define GBL_c2(m1a, m1b, m2a, m2b) (m1a) << 28 | (m1b) << 24 | (m2a) << 20 | (m2b) << 16
713
714#define RM_AA_ZB_OPA_SURF(clk) \
715 AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | \
716 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
717
718#define RM_RA_ZB_OPA_SURF(clk) \
719 AA_EN | Z_CMP | Z_UPD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | \
720 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
721
722#define RM_AA_ZB_XLU_SURF(clk) \
723 AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | FORCE_BL | ZMODE_XLU | \
724 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
725
726#define RM_AA_ZB_OPA_DECAL(clk) \
727 AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | ALPHA_CVG_SEL | ZMODE_DEC | \
728 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
729
730#define RM_RA_ZB_OPA_DECAL(clk) \
731 AA_EN | Z_CMP | CVG_DST_WRAP | ALPHA_CVG_SEL | ZMODE_DEC | \
732 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
733
734#define RM_AA_ZB_XLU_DECAL(clk) \
735 AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | FORCE_BL | ZMODE_DEC | \
736 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
737
738#define RM_AA_ZB_OPA_INTER(clk) \
739 AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | ALPHA_CVG_SEL | ZMODE_INTER | \
740 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
741
742#define RM_RA_ZB_OPA_INTER(clk) \
743 AA_EN | Z_CMP | Z_UPD | CVG_DST_CLAMP | ALPHA_CVG_SEL | ZMODE_INTER | \
744 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
745
746#define RM_AA_ZB_XLU_INTER(clk) \
747 AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | FORCE_BL | ZMODE_INTER | \
748 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
749
750#define RM_AA_ZB_XLU_LINE(clk) \
751 AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL | ZMODE_XLU | \
752 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
753
754#define RM_AA_ZB_DEC_LINE(clk) \
755 AA_EN | Z_CMP | IM_RD | CVG_DST_SAVE | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL | ZMODE_DEC | \
756 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
757
758#define RM_AA_ZB_TEX_EDGE(clk) \
759 AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \
760 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
761
762#define RM_AA_ZB_TEX_INTER(clk) \
763 AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_INTER | TEX_EDGE | \
764 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
765
766#define RM_AA_ZB_SUB_SURF(clk) \
767 AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | ZMODE_OPA | ALPHA_CVG_SEL | \
768 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
769
770#define RM_AA_ZB_PCL_SURF(clk) \
771 AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | G_AC_DITHER | \
772 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
773
774#define RM_AA_ZB_OPA_TERR(clk) \
775 AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | \
776 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
777
778#define RM_AA_ZB_TEX_TERR(clk) \
779 AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \
780 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
781
782#define RM_AA_ZB_SUB_TERR(clk) \
783 AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | ZMODE_OPA | ALPHA_CVG_SEL | \
784 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
785
786#define RM_AA_OPA_SURF(clk) \
787 AA_EN | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | \
788 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
789
790#define RM_RA_OPA_SURF(clk) \
791 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)
792
793#define RM_AA_XLU_SURF(clk) \
794 AA_EN | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | FORCE_BL | ZMODE_OPA | \
795 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
796
797#define RM_AA_XLU_LINE(clk) \
798 AA_EN | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \
799 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
800
801#define RM_AA_DEC_LINE(clk) \
802 AA_EN | IM_RD | CVG_DST_FULL | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \
803 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
804
805#define RM_AA_TEX_EDGE(clk) \
806 AA_EN | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \
807 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
808
809#define RM_AA_SUB_SURF(clk) \
810 AA_EN | IM_RD | CVG_DST_FULL | ZMODE_OPA | ALPHA_CVG_SEL | \
811 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
812
813#define RM_AA_PCL_SURF(clk) \
814 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)
815
816#define RM_AA_OPA_TERR(clk) \
817 AA_EN | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | \
818 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
819
820#define RM_AA_TEX_TERR(clk) \
821 AA_EN | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \
822 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
823
824#define RM_AA_SUB_TERR(clk) \
825 AA_EN | IM_RD | CVG_DST_FULL | ZMODE_OPA | ALPHA_CVG_SEL | \
826 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
827
828#define RM_ZB_OPA_SURF(clk) \
829 Z_CMP | Z_UPD | CVG_DST_FULL | ALPHA_CVG_SEL | ZMODE_OPA | \
830 GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)
831
832#define RM_ZB_XLU_SURF(clk) \
833 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)
834
835#define RM_ZB_OPA_DECAL(clk) \
836 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)
837
838#define RM_ZB_XLU_DECAL(clk) \
839 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)
840
841#define RM_ZB_CLD_SURF(clk) \
842 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)
843
844#define RM_ZB_OVL_SURF(clk) \
845 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)
846
847#define RM_ZB_PCL_SURF(clk) \
848 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)
849
850#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)
851
852#define RM_XLU_SURF(clk) \
853 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)
854
855#define RM_TEX_EDGE(clk) \
856 CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | TEX_EDGE | AA_EN | \
857 GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1)
858
859#define RM_CLD_SURF(clk) \
860 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)
861
862#define RM_PCL_SURF(clk) \
863 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)
864
865#define RM_ADD(clk) \
866 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)
867
868#define RM_NOOP(clk) GBL_c##clk(0, 0, 0, 0)
869
870#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)
871
872/* for rendering to an 8-bit framebuffer */
873#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)
874
875/* Custom version of RM_AA_ZB_XLU_SURF with Z_UPD */
876#define RM_CUSTOM_AA_ZB_XLU_SURF(clk) RM_AA_ZB_XLU_SURF(clk) | Z_UPD
877
878#define G_RM_AA_ZB_OPA_SURF RM_AA_ZB_OPA_SURF(1)
879#define G_RM_AA_ZB_OPA_SURF2 RM_AA_ZB_OPA_SURF(2)
880#define G_RM_AA_ZB_XLU_SURF RM_AA_ZB_XLU_SURF(1)
881#define G_RM_AA_ZB_XLU_SURF2 RM_AA_ZB_XLU_SURF(2)
882#define G_RM_AA_ZB_OPA_DECAL RM_AA_ZB_OPA_DECAL(1)
883#define G_RM_AA_ZB_OPA_DECAL2 RM_AA_ZB_OPA_DECAL(2)
884#define G_RM_AA_ZB_XLU_DECAL RM_AA_ZB_XLU_DECAL(1)
885#define G_RM_AA_ZB_XLU_DECAL2 RM_AA_ZB_XLU_DECAL(2)
886#define G_RM_AA_ZB_OPA_INTER RM_AA_ZB_OPA_INTER(1)
887#define G_RM_AA_ZB_OPA_INTER2 RM_AA_ZB_OPA_INTER(2)
888#define G_RM_AA_ZB_XLU_INTER RM_AA_ZB_XLU_INTER(1)
889#define G_RM_AA_ZB_XLU_INTER2 RM_AA_ZB_XLU_INTER(2)
890#define G_RM_AA_ZB_XLU_LINE RM_AA_ZB_XLU_LINE(1)
891#define G_RM_AA_ZB_XLU_LINE2 RM_AA_ZB_XLU_LINE(2)
892#define G_RM_AA_ZB_DEC_LINE RM_AA_ZB_DEC_LINE(1)
893#define G_RM_AA_ZB_DEC_LINE2 RM_AA_ZB_DEC_LINE(2)
894#define G_RM_AA_ZB_TEX_EDGE RM_AA_ZB_TEX_EDGE(1)
895#define G_RM_AA_ZB_TEX_EDGE2 RM_AA_ZB_TEX_EDGE(2)
896#define G_RM_AA_ZB_TEX_INTER RM_AA_ZB_TEX_INTER(1)
897#define G_RM_AA_ZB_TEX_INTER2 RM_AA_ZB_TEX_INTER(2)
898#define G_RM_AA_ZB_SUB_SURF RM_AA_ZB_SUB_SURF(1)
899#define G_RM_AA_ZB_SUB_SURF2 RM_AA_ZB_SUB_SURF(2)
900#define G_RM_AA_ZB_PCL_SURF RM_AA_ZB_PCL_SURF(1)
901#define G_RM_AA_ZB_PCL_SURF2 RM_AA_ZB_PCL_SURF(2)
902#define G_RM_AA_ZB_OPA_TERR RM_AA_ZB_OPA_TERR(1)
903#define G_RM_AA_ZB_OPA_TERR2 RM_AA_ZB_OPA_TERR(2)
904#define G_RM_AA_ZB_TEX_TERR RM_AA_ZB_TEX_TERR(1)
905#define G_RM_AA_ZB_TEX_TERR2 RM_AA_ZB_TEX_TERR(2)
906#define G_RM_AA_ZB_SUB_TERR RM_AA_ZB_SUB_TERR(1)
907#define G_RM_AA_ZB_SUB_TERR2 RM_AA_ZB_SUB_TERR(2)
908
909#define G_RM_RA_ZB_OPA_SURF RM_RA_ZB_OPA_SURF(1)
910#define G_RM_RA_ZB_OPA_SURF2 RM_RA_ZB_OPA_SURF(2)
911#define G_RM_RA_ZB_OPA_DECAL RM_RA_ZB_OPA_DECAL(1)
912#define G_RM_RA_ZB_OPA_DECAL2 RM_RA_ZB_OPA_DECAL(2)
913#define G_RM_RA_ZB_OPA_INTER RM_RA_ZB_OPA_INTER(1)
914#define G_RM_RA_ZB_OPA_INTER2 RM_RA_ZB_OPA_INTER(2)
915
916#define G_RM_AA_OPA_SURF RM_AA_OPA_SURF(1)
917#define G_RM_AA_OPA_SURF2 RM_AA_OPA_SURF(2)
918#define G_RM_AA_XLU_SURF RM_AA_XLU_SURF(1)
919#define G_RM_AA_XLU_SURF2 RM_AA_XLU_SURF(2)
920#define G_RM_AA_XLU_LINE RM_AA_XLU_LINE(1)
921#define G_RM_AA_XLU_LINE2 RM_AA_XLU_LINE(2)
922#define G_RM_AA_DEC_LINE RM_AA_DEC_LINE(1)
923#define G_RM_AA_DEC_LINE2 RM_AA_DEC_LINE(2)
924#define G_RM_AA_TEX_EDGE RM_AA_TEX_EDGE(1)
925#define G_RM_AA_TEX_EDGE2 RM_AA_TEX_EDGE(2)
926#define G_RM_AA_SUB_SURF RM_AA_SUB_SURF(1)
927#define G_RM_AA_SUB_SURF2 RM_AA_SUB_SURF(2)
928#define G_RM_AA_PCL_SURF RM_AA_PCL_SURF(1)
929#define G_RM_AA_PCL_SURF2 RM_AA_PCL_SURF(2)
930#define G_RM_AA_OPA_TERR RM_AA_OPA_TERR(1)
931#define G_RM_AA_OPA_TERR2 RM_AA_OPA_TERR(2)
932#define G_RM_AA_TEX_TERR RM_AA_TEX_TERR(1)
933#define G_RM_AA_TEX_TERR2 RM_AA_TEX_TERR(2)
934#define G_RM_AA_SUB_TERR RM_AA_SUB_TERR(1)
935#define G_RM_AA_SUB_TERR2 RM_AA_SUB_TERR(2)
936
937#define G_RM_RA_OPA_SURF RM_RA_OPA_SURF(1)
938#define G_RM_RA_OPA_SURF2 RM_RA_OPA_SURF(2)
939
940#define G_RM_ZB_OPA_SURF RM_ZB_OPA_SURF(1)
941#define G_RM_ZB_OPA_SURF2 RM_ZB_OPA_SURF(2)
942#define G_RM_ZB_XLU_SURF RM_ZB_XLU_SURF(1)
943#define G_RM_ZB_XLU_SURF2 RM_ZB_XLU_SURF(2)
944#define G_RM_ZB_OPA_DECAL RM_ZB_OPA_DECAL(1)
945#define G_RM_ZB_OPA_DECAL2 RM_ZB_OPA_DECAL(2)
946#define G_RM_ZB_XLU_DECAL RM_ZB_XLU_DECAL(1)
947#define G_RM_ZB_XLU_DECAL2 RM_ZB_XLU_DECAL(2)
948#define G_RM_ZB_CLD_SURF RM_ZB_CLD_SURF(1)
949#define G_RM_ZB_CLD_SURF2 RM_ZB_CLD_SURF(2)
950#define G_RM_ZB_OVL_SURF RM_ZB_OVL_SURF(1)
951#define G_RM_ZB_OVL_SURF2 RM_ZB_OVL_SURF(2)
952#define G_RM_ZB_PCL_SURF RM_ZB_PCL_SURF(1)
953#define G_RM_ZB_PCL_SURF2 RM_ZB_PCL_SURF(2)
954
955#define G_RM_OPA_SURF RM_OPA_SURF(1)
956#define G_RM_OPA_SURF2 RM_OPA_SURF(2)
957#define G_RM_XLU_SURF RM_XLU_SURF(1)
958#define G_RM_XLU_SURF2 RM_XLU_SURF(2)
959#define G_RM_CLD_SURF RM_CLD_SURF(1)
960#define G_RM_CLD_SURF2 RM_CLD_SURF(2)
961#define G_RM_TEX_EDGE RM_TEX_EDGE(1)
962#define G_RM_TEX_EDGE2 RM_TEX_EDGE(2)
963#define G_RM_PCL_SURF RM_PCL_SURF(1)
964#define G_RM_PCL_SURF2 RM_PCL_SURF(2)
965#define G_RM_ADD RM_ADD(1)
966#define G_RM_ADD2 RM_ADD(2)
967#define G_RM_NOOP RM_NOOP(1)
968#define G_RM_NOOP2 RM_NOOP(2)
969#define G_RM_VISCVG RM_VISCVG(1)
970#define G_RM_VISCVG2 RM_VISCVG(2)
971#define G_RM_OPA_CI RM_OPA_CI(1)
972#define G_RM_OPA_CI2 RM_OPA_CI(2)
973
974#define G_RM_CUSTOM_AA_ZB_XLU_SURF RM_CUSTOM_AA_ZB_XLU_SURF(1)
975#define G_RM_CUSTOM_AA_ZB_XLU_SURF2 RM_CUSTOM_AA_ZB_XLU_SURF(2)
976
977#define G_RM_FOG_SHADE_A GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA)
978#define G_RM_FOG_PRIM_A GBL_c1(G_BL_CLR_FOG, G_BL_A_FOG, G_BL_CLR_IN, G_BL_1MA)
979#define G_RM_PASS GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1)
980
981/*
982 * G_SETCONVERT: K0-5
983 */
984#define G_CV_K0 175
985#define G_CV_K1 -43
986#define G_CV_K2 -89
987#define G_CV_K3 222
988#define G_CV_K4 114
989#define G_CV_K5 42
990
991/*
992 * G_SETSCISSOR: interlace mode
993 */
994#define G_SC_NON_INTERLACE 0
995#define G_SC_ODD_INTERLACE 3
996#define G_SC_EVEN_INTERLACE 2
997
998/* flags to inhibit pushing of the display list (on branch) */
999#define G_DL_PUSH 0x00
1000#define G_DL_NOPUSH 0x01
1001
1002/*
1003 * BEGIN C-specific section: (typedef's)
1004 */
1005#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
1006
1007/*
1008 * Data Structures
1009 *
1010 * NOTE:
1011 * The DMA transfer hardware requires 64-bit aligned, 64-bit multiple-
1012 * sized transfers. This important hardware optimization is unfortunately
1013 * reflected in the programming interface, with some structures
1014 * padded and alignment enforced.
1015 *
1016 * Since structures are aligned to the boundary of the "worst-case"
1017 * element, we can't depend on the C compiler to align things
1018 * properly.
1019 *
1020 * 64-bit structure alignment is enforced by wrapping structures with
1021 * unions that contain a dummy "long long int". Why this works is
1022 * explained in the ANSI C Spec, or on page 186 of the second edition
1023 * of K&R, "The C Programming Language".
1024 *
1025 * The price we pay for this is a little awkwardness referencing the
1026 * structures through the union. There is no memory penalty, since
1027 * all the structures are at least 64-bits the dummy alignment field
1028 * does not increase the size of the union.
1029 *
1030 * Static initialization of these union structures works because
1031 * the ANSI C spec states that static initialization for unions
1032 * works by using the first union element. We put the dummy alignment
1033 * field last for this reason.
1034 *
1035 * (it's possible a newer 64-bit compiler from MIPS might make this
1036 * easier with a flag, but we can't wait for it...)
1037 *
1038 */
1039
1040/*
1041 * Vertex (set up for use with colors)
1042 */
1043typedef struct {
1044 short ob[3]; /* x, y, z */
1045 unsigned short flag;
1046 short tc[2]; /* texture coord */
1047 unsigned char cn[4]; /* color & alpha */
1048} Vtx_t;
1049
1050/*
1051 * Vertex (set up for use with normals)
1052 */
1053typedef struct {
1054 short ob[3]; /* x, y, z */
1055 unsigned short flag;
1056 short tc[2]; /* texture coord */
1057 signed char n[3]; /* normal */
1058 unsigned char a; /* alpha */
1059} Vtx_tn;
1060
1061typedef union {
1062 Vtx_t v; /* Use this one for colors */
1063 Vtx_tn n; /* Use this one for normals */
1064 long long int force_structure_alignment;
1065} Vtx;
1066
1067/*
1068 * Sprite structure
1069 */
1070
1071typedef struct {
1072 void* SourceImagePointer;
1073 void* TlutPointer;
1074 short Stride;
1075 short SubImageWidth;
1076 short SubImageHeight;
1077 char SourceImageType;
1078 char SourceImageBitSize;
1079 short SourceImageOffsetS;
1080 short SourceImageOffsetT;
1081 /* 20 bytes for above */
1082
1083 /* padding to bring structure size to 64 bit allignment */
1084 char dummy[4];
1085
1086} uSprite_t;
1087
1088typedef union {
1089 uSprite_t s;
1090
1091 /* Need to make sure this is 64 bit aligned */
1092 long long int force_structure_allignment[3];
1093} uSprite;
1094
1095/*
1096 * Triangle face
1097 */
1098typedef struct {
1099 unsigned char flag;
1100 unsigned char v[3];
1101} Tri;
1102
1103/*
1104 * 4x4 matrix, fixed point s15.16 format.
1105 * First 8 words are integer portion of the 4x4 matrix
1106 * Last 8 words are the fraction portion of the 4x4 matrix
1107 */
1108typedef s32 Mtx_t[4][4];
1109
1110typedef union {
1111 Mtx_t m;
1112 long long int force_structure_alignment;
1113} Mtx;
1114
1115/*
1116 * Viewport
1117 */
1118
1119/*
1120 *
1121 * This magic value is the maximum INTEGER z-range of the hardware
1122 * (there are also 16-bits of fraction, which are introduced during
1123 * any transformations). This is not just a good idea, it's the law.
1124 * Feeding the hardware eventual z-coordinates (after any transforms
1125 * or scaling) bigger than this, will not work.
1126 *
1127 * This number is DIFFERENT than G_MAXFBZ, which is the maximum value
1128 * you want to use to initialize the z-buffer.
1129 *
1130 * The reason these are different is mildly interesting, but too long
1131 * to explain here. It is basically the result of optimizations in the
1132 * hardware. A more generic API might hide this detail from the users,
1133 * but we don't have the ucode to do that...
1134 *
1135 */
1136#define G_MAXZ 0x03ff /* 10 bits of integer screen-Z precision */
1137
1138/*
1139 * The viewport structure elements have 2 bits of fraction, necessary
1140 * to accomodate the sub-pixel positioning scaling for the hardware.
1141 * This can also be exploited to handle odd-sized viewports.
1142 *
1143 * Accounting for these fractional bits, using the default projection
1144 * and viewing matrices, the viewport structure is initialized thusly:
1145 *
1146 * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, G_MAXZ, 0,
1147 * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, 0, 0,
1148 */
1149typedef struct {
1150 short vscale[4]; /* scale, 2 bits fraction */
1151 short vtrans[4]; /* translate, 2 bits fraction */
1152 /* both the above arrays are padded to 64-bit boundary */
1153} Vp_t;
1154
1155typedef union {
1156 Vp_t vp;
1157 long long int force_structure_alignment;
1158} Vp;
1159
1160/*
1161 * MOVEMEM indices
1162 *
1163 * Each of these indexes an entry in a dmem table
1164 * which points to a 1-4 word block of dmem in
1165 * which to store a 1-4 word DMA.
1166 *
1167 */
1168#ifdef F3DEX_GBI_2
1169/* 0,4 are reserved by G_MTX */
1170#define G_MV_MMTX 2
1171#define G_MV_PMTX 6
1172#define G_MV_VIEWPORT 8
1173#define G_MV_LIGHT 10
1174#define G_MV_POINT 12
1175#define G_MV_MATRIX 14 /* NOTE: this is in moveword table */
1176#define G_MVO_LOOKATX (0 * 24)
1177#define G_MVO_LOOKATY (1 * 24)
1178#define G_MVO_L0 (2 * 24)
1179#define G_MVO_L1 (3 * 24)
1180#define G_MVO_L2 (4 * 24)
1181#define G_MVO_L3 (5 * 24)
1182#define G_MVO_L4 (6 * 24)
1183#define G_MVO_L5 (7 * 24)
1184#define G_MVO_L6 (8 * 24)
1185#define G_MVO_L7 (9 * 24)
1186#else /* F3DEX_GBI_2 */
1187#define G_MV_VIEWPORT 0x80
1188#define G_MV_LOOKATY 0x82
1189#define G_MV_LOOKATX 0x84
1190#define G_MV_L0 0x86
1191#define G_MV_L1 0x88
1192#define G_MV_L2 0x8a
1193#define G_MV_L3 0x8c
1194#define G_MV_L4 0x8e
1195#define G_MV_L5 0x90
1196#define G_MV_L6 0x92
1197#define G_MV_L7 0x94
1198#define G_MV_TXTATT 0x96
1199#define G_MV_MATRIX_1 0x9e /* NOTE: this is in moveword table */
1200#define G_MV_MATRIX_2 0x98
1201#define G_MV_MATRIX_3 0x9a
1202#define G_MV_MATRIX_4 0x9c
1203#endif /* F3DEX_GBI_2 */
1204
1205/*
1206 * MOVEWORD indices
1207 *
1208 * Each of these indexes an entry in a dmem table
1209 * which points to a word in dmem in dmem where
1210 * an immediate word will be stored.
1211 *
1212 */
1213#define G_MW_MATRIX 0x00 /* NOTE: also used by movemem */
1214#define G_MW_NUMLIGHT 0x02
1215#define G_MW_CLIP 0x04
1216#define G_MW_SEGMENT 0x06
1217#define G_MW_FOG 0x08
1218#define G_MW_LIGHTCOL 0x0a
1219#ifdef F3DEX_GBI_2
1220#define G_MW_FORCEMTX 0x0c
1221#else /* F3DEX_GBI_2 */
1222#define G_MW_POINTS 0x0c
1223#endif /* F3DEX_GBI_2 */
1224#define G_MW_PERSPNORM 0x0e
1225
1226/*
1227 * These are offsets from the address in the dmem table
1228 */
1229#define G_MWO_NUMLIGHT 0x00
1230#define G_MWO_CLIP_RNX 0x04
1231#define G_MWO_CLIP_RNY 0x0c
1232#define G_MWO_CLIP_RPX 0x14
1233#define G_MWO_CLIP_RPY 0x1c
1234#define G_MWO_SEGMENT_0 0x00
1235#define G_MWO_SEGMENT_1 0x01
1236#define G_MWO_SEGMENT_2 0x02
1237#define G_MWO_SEGMENT_3 0x03
1238#define G_MWO_SEGMENT_4 0x04
1239#define G_MWO_SEGMENT_5 0x05
1240#define G_MWO_SEGMENT_6 0x06
1241#define G_MWO_SEGMENT_7 0x07
1242#define G_MWO_SEGMENT_8 0x08
1243#define G_MWO_SEGMENT_9 0x09
1244#define G_MWO_SEGMENT_A 0x0a
1245#define G_MWO_SEGMENT_B 0x0b
1246#define G_MWO_SEGMENT_C 0x0c
1247#define G_MWO_SEGMENT_D 0x0d
1248#define G_MWO_SEGMENT_E 0x0e
1249#define G_MWO_SEGMENT_F 0x0f
1250#define G_MWO_FOG 0x00
1251#define G_MWO_aLIGHT_1 0x00
1252#define G_MWO_bLIGHT_1 0x04
1253#ifdef F3DEX_GBI_2
1254#define G_MWO_aLIGHT_2 0x18
1255#define G_MWO_bLIGHT_2 0x1c
1256#define G_MWO_aLIGHT_3 0x30
1257#define G_MWO_bLIGHT_3 0x34
1258#define G_MWO_aLIGHT_4 0x48
1259#define G_MWO_bLIGHT_4 0x4c
1260#define G_MWO_aLIGHT_5 0x60
1261#define G_MWO_bLIGHT_5 0x64
1262#define G_MWO_aLIGHT_6 0x78
1263#define G_MWO_bLIGHT_6 0x7c
1264#define G_MWO_aLIGHT_7 0x90
1265#define G_MWO_bLIGHT_7 0x94
1266#define G_MWO_aLIGHT_8 0xa8
1267#define G_MWO_bLIGHT_8 0xac
1268#else
1269#define G_MWO_aLIGHT_2 0x20
1270#define G_MWO_bLIGHT_2 0x24
1271#define G_MWO_aLIGHT_3 0x40
1272#define G_MWO_bLIGHT_3 0x44
1273#define G_MWO_aLIGHT_4 0x60
1274#define G_MWO_bLIGHT_4 0x64
1275#define G_MWO_aLIGHT_5 0x80
1276#define G_MWO_bLIGHT_5 0x84
1277#define G_MWO_aLIGHT_6 0xa0
1278#define G_MWO_bLIGHT_6 0xa4
1279#define G_MWO_aLIGHT_7 0xc0
1280#define G_MWO_bLIGHT_7 0xc4
1281#define G_MWO_aLIGHT_8 0xe0
1282#define G_MWO_bLIGHT_8 0xe4
1283#endif
1284#define G_MWO_MATRIX_XX_XY_I 0x00
1285#define G_MWO_MATRIX_XZ_XW_I 0x04
1286#define G_MWO_MATRIX_YX_YY_I 0x08
1287#define G_MWO_MATRIX_YZ_YW_I 0x0c
1288#define G_MWO_MATRIX_ZX_ZY_I 0x10
1289#define G_MWO_MATRIX_ZZ_ZW_I 0x14
1290#define G_MWO_MATRIX_WX_WY_I 0x18
1291#define G_MWO_MATRIX_WZ_WW_I 0x1c
1292#define G_MWO_MATRIX_XX_XY_F 0x20
1293#define G_MWO_MATRIX_XZ_XW_F 0x24
1294#define G_MWO_MATRIX_YX_YY_F 0x28
1295#define G_MWO_MATRIX_YZ_YW_F 0x2c
1296#define G_MWO_MATRIX_ZX_ZY_F 0x30
1297#define G_MWO_MATRIX_ZZ_ZW_F 0x34
1298#define G_MWO_MATRIX_WX_WY_F 0x38
1299#define G_MWO_MATRIX_WZ_WW_F 0x3c
1300#define G_MWO_POINT_RGBA 0x10
1301#define G_MWO_POINT_ST 0x14
1302#define G_MWO_POINT_XYSCREEN 0x18
1303#define G_MWO_POINT_ZSCREEN 0x1c
1304
1305/*
1306 * Light structure.
1307 *
1308 * Note: only directional (infinite) lights are currently supported.
1309 *
1310 * Note: the weird order is for the DMEM alignment benefit of
1311 * the microcode.
1312 *
1313 */
1314
1315typedef struct {
1316 unsigned char col[3]; /* diffuse light value (rgba) */
1317 char pad1;
1318 unsigned char colc[3]; /* copy of diffuse light value (rgba) */
1319 char pad2;
1320 signed char dir[3]; /* direction of light (normalized) */
1321 char pad3;
1322} Light_t;
1323
1324typedef struct {
1325 unsigned char col[3]; /* ambient light value (rgba) */
1326 char pad1;
1327 unsigned char colc[3]; /* copy of ambient light value (rgba) */
1328 char pad2;
1329} Ambient_t;
1330
1331typedef struct {
1332 int x1, y1, x2, y2; /* texture offsets for highlight 1/2 */
1333} Hilite_t;
1334
1335typedef union {
1336 Light_t l;
1337 long long int force_structure_alignment[2];
1338} Light;
1339
1340typedef union {
1341 Ambient_t l;
1342 long long int force_structure_alignment[1];
1343} Ambient;
1344
1345typedef struct {
1346 Ambient a;
1347 Light l[7];
1348} Lightsn;
1349
1350typedef struct {
1351 Ambient a;
1352 Light l[1];
1353} Lights0;
1354
1355typedef struct {
1356 Ambient a;
1357 Light l[1];
1358} Lights1;
1359
1360typedef struct {
1361 Ambient a;
1362 Light l[2];
1363} Lights2;
1364
1365typedef struct {
1366 Ambient a;
1367 Light l[3];
1368} Lights3;
1369
1370typedef struct {
1371 Ambient a;
1372 Light l[4];
1373} Lights4;
1374
1375typedef struct {
1376 Ambient a;
1377 Light l[5];
1378} Lights5;
1379
1380typedef struct {
1381 Ambient a;
1382 Light l[6];
1383} Lights6;
1384
1385typedef struct {
1386 Ambient a;
1387 Light l[7];
1388} Lights7;
1389
1390typedef struct {
1391 Light l[2];
1392} LookAt;
1393
1394typedef union {
1395 Hilite_t h;
1396 long int force_structure_alignment[4];
1397} Hilite;
1398
1399#define gdSPDefLights0(ar, ag, ab) \
1400 { \
1401 { { { ar, ag, ab }, 0, { ar, ag, ab }, 0 } }, { \
1402 { \
1403 { { 0, 0, 0 }, 0, { 0, 0, 0 }, 0, { 0, 0, 0 }, 0 } \
1404 } \
1405 } \
1406 }
1407#define gdSPDefLights1(ar, ag, ab, r1, g1, b1, x1, y1, z1) \
1408 { \
1409 { { { ar, ag, ab }, 0, { ar, ag, ab }, 0 } }, { \
1410 { \
1411 { { r1, g1, b1 }, 0, { r1, g1, b1 }, 0, { x1, y1, z1 }, 0 } \
1412 } \
1413 } \
1414 }
1415#define gdSPDefLights2(ar, ag, ab, r1, g1, b1, x1, y1, z1, r2, g2, b2, x2, y2, z2) \
1416 { \
1417 { { { ar, ag, ab }, 0, { ar, ag, ab }, 0 } }, { \
1418 { { { r1, g1, b1 }, 0, { r1, g1, b1 }, 0, { x1, y1, z1 }, 0 } }, { \
1419 { { r2, g2, b2 }, 0, { r2, g2, b2 }, 0, { x2, y2, z2 }, 0 } \
1420 } \
1421 } \
1422 }
1423#define gdSPDefLights3(ar, ag, ab, r1, g1, b1, x1, y1, z1, r2, g2, b2, x2, y2, z2, r3, g3, b3, x3, y3, z3) \
1424 { \
1425 { { { ar, ag, ab }, 0, { ar, ag, ab }, 0 } }, { \
1426 { { { r1, g1, b1 }, 0, { r1, g1, b1 }, 0, { x1, y1, z1 }, 0 } }, \
1427 { { { r2, g2, b2 }, 0, { r2, g2, b2 }, 0, { x2, y2, z2 }, 0 } }, { \
1428 { { r3, g3, b3 }, 0, { r3, g3, b3 }, 0, { x3, y3, z3 }, 0 } \
1429 } \
1430 } \
1431 }
1432#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, \
1433 x4, y4, z4) \
1434 { \
1435 { { { ar, ag, ab }, 0, { ar, ag, ab }, 0 } }, { \
1436 { { { r1, g1, b1 }, 0, { r1, g1, b1 }, 0, { x1, y1, z1 }, 0 } }, \
1437 { { { r2, g2, b2 }, 0, { r2, g2, b2 }, 0, { x2, y2, z2 }, 0 } }, \
1438 { { { r3, g3, b3 }, 0, { r3, g3, b3 }, 0, { x3, y3, z3 }, 0 } }, { \
1439 { { r4, g4, b4 }, 0, { r4, g4, b4 }, 0, { x4, y4, z4 }, 0 } \
1440 } \
1441 } \
1442 }
1443#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, \
1444 x4, y4, z4, r5, g5, b5, x5, y5, z5) \
1445 { \
1446 { { { ar, ag, ab }, 0, { ar, ag, ab }, 0 } }, { \
1447 { { { r1, g1, b1 }, 0, { r1, g1, b1 }, 0, { x1, y1, z1 }, 0 } }, \
1448 { { { r2, g2, b2 }, 0, { r2, g2, b2 }, 0, { x2, y2, z2 }, 0 } }, \
1449 { { { r3, g3, b3 }, 0, { r3, g3, b3 }, 0, { x3, y3, z3 }, 0 } }, \
1450 { { { r4, g4, b4 }, 0, { r4, g4, b4 }, 0, { x4, y4, z4 }, 0 } }, { \
1451 { { r5, g5, b5 }, 0, { r5, g5, b5 }, 0, { x5, y5, z5 }, 0 } \
1452 } \
1453 } \
1454 }
1455
1456#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, \
1457 x4, y4, z4, r5, g5, b5, x5, y5, z5, r6, g6, b6, x6, y6, z6) \
1458 { \
1459 { { { ar, ag, ab }, 0, { ar, ag, ab }, 0 } }, { \
1460 { { { r1, g1, b1 }, 0, { r1, g1, b1 }, 0, { x1, y1, z1 }, 0 } }, \
1461 { { { r2, g2, b2 }, 0, { r2, g2, b2 }, 0, { x2, y2, z2 }, 0 } }, \
1462 { { { r3, g3, b3 }, 0, { r3, g3, b3 }, 0, { x3, y3, z3 }, 0 } }, \
1463 { { { r4, g4, b4 }, 0, { r4, g4, b4 }, 0, { x4, y4, z4 }, 0 } }, \
1464 { { { r5, g5, b5 }, 0, { r5, g5, b5 }, 0, { x5, y5, z5 }, 0 } }, { \
1465 { { r6, g6, b6 }, 0, { r6, g6, b6 }, 0, { x6, y6, z6 }, 0 } \
1466 } \
1467 } \
1468 }
1469
1470#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, \
1471 x4, y4, z4, r5, g5, b5, x5, y5, z5, r6, g6, b6, x6, y6, z6, r7, g7, b7, x7, y7, z7) \
1472 { \
1473 { { { ar, ag, ab }, 0, { ar, ag, ab }, 0 } }, { \
1474 { { { r1, g1, b1 }, 0, { r1, g1, b1 }, 0, { x1, y1, z1 }, 0 } }, \
1475 { { { r2, g2, b2 }, 0, { r2, g2, b2 }, 0, { x2, y2, z2 }, 0 } }, \
1476 { { { r3, g3, b3 }, 0, { r3, g3, b3 }, 0, { x3, y3, z3 }, 0 } }, \
1477 { { { r4, g4, b4 }, 0, { r4, g4, b4 }, 0, { x4, y4, z4 }, 0 } }, \
1478 { { { r5, g5, b5 }, 0, { r5, g5, b5 }, 0, { x5, y5, z5 }, 0 } }, \
1479 { { { r6, g6, b6 }, 0, { r6, g6, b6 }, 0, { x6, y6, z6 }, 0 } }, { \
1480 { { r7, g7, b7 }, 0, { r7, g7, b7 }, 0, { x7, y7, z7 }, 0 } \
1481 } \
1482 } \
1483 }
1484
1485#define gdSPDefLookAt(rightx, righty, rightz, upx, upy, upz) \
1486 { \
1487 { \
1488 { { { 0, 0, 0 }, 0, { 0, 0, 0 }, 0, { rightx, righty, rightz }, 0 } }, { \
1489 { { 0, 0x80, 0 }, 0, { 0, 0x80, 0 }, 0, { upx, upy, upz }, 0 } \
1490 } \
1491 } \
1492 }
1493
1494/* Don't declare these for F3D_OLD to avoid bss reordering */
1495#ifndef F3D_OLD
1496/*
1497 * Graphics DMA Packet
1498 */
1499typedef struct {
1500 int cmd : 8;
1501 unsigned int par : 8;
1502 unsigned int len : 16;
1503 uintptr_t addr;
1504} Gdma;
1505
1506/*
1507 * Graphics Immediate Mode Packet types
1508 */
1509typedef struct {
1510 int cmd : 8;
1511 int pad : 24;
1512 Tri tri;
1513} Gtri;
1514
1515typedef struct {
1516 int cmd : 8;
1517 int pad1 : 24;
1518 int pad2 : 24;
1519 unsigned char param : 8;
1520} Gpopmtx;
1521
1522/*
1523 * typedef struct {
1524 * int cmd:8;
1525 * int pad0:24;
1526 * int pad1:4;
1527 * int number:4;
1528 * int base:24;
1529 * } Gsegment;
1530 */
1531typedef struct {
1532 int cmd : 8;
1533 int pad0 : 8;
1534 int mw_index : 8;
1535 int number : 8;
1536 int pad1 : 8;
1537 int base : 24;
1538} Gsegment;
1539
1540typedef struct {
1541 int cmd : 8;
1542 int pad0 : 8;
1543 int sft : 8;
1544 int len : 8;
1545 unsigned int data : 32;
1546} GsetothermodeL;
1547
1548typedef struct {
1549 int cmd : 8;
1550 int pad0 : 8;
1551 int sft : 8;
1552 int len : 8;
1553 unsigned int data : 32;
1554} GsetothermodeH;
1555
1556typedef struct {
1557 unsigned char cmd;
1558 unsigned char lodscale;
1559 unsigned char tile;
1560 unsigned char on;
1561 unsigned short s;
1562 unsigned short t;
1563} Gtexture;
1564
1565typedef struct {
1566 int cmd : 8;
1567 int pad : 24;
1568 Tri line;
1569} Gline3D;
1570
1571typedef struct {
1572 int cmd : 8;
1573 int pad1 : 24;
1574 short int pad2;
1575 short int scale;
1576} Gperspnorm;
1577
1578/*
1579 * RDP Packet types
1580 */
1581typedef struct {
1582 int cmd : 8;
1583 unsigned int fmt : 3;
1584 unsigned int siz : 2;
1585 unsigned int pad : 7;
1586 unsigned int wd : 12; /* really only 10 bits, extra */
1587 uintptr_t dram; /* to account for 1024 */
1588} Gsetimg;
1589
1590typedef struct {
1591 int cmd : 8;
1592 unsigned int muxs0 : 24;
1593 unsigned int muxs1 : 32;
1594} Gsetcombine;
1595
1596typedef struct {
1597 int cmd : 8;
1598 unsigned char pad;
1599 unsigned char prim_min_level;
1600 unsigned char prim_level;
1601 unsigned long color;
1602} Gsetcolor;
1603
1604typedef struct {
1605 int cmd : 8;
1606 int x0 : 10;
1607 int x0frac : 2;
1608 int y0 : 10;
1609 int y0frac : 2;
1610 unsigned int pad : 8;
1611 int x1 : 10;
1612 int x1frac : 2;
1613 int y1 : 10;
1614 int y1frac : 2;
1615} Gfillrect;
1616
1617typedef struct {
1618 int cmd : 8;
1619 unsigned int fmt : 3;
1620 unsigned int siz : 2;
1621 unsigned int pad0 : 1;
1622 unsigned int line : 9;
1623 unsigned int tmem : 9;
1624 unsigned int pad1 : 5;
1625 unsigned int tile : 3;
1626 unsigned int palette : 4;
1627 unsigned int ct : 1;
1628 unsigned int mt : 1;
1629 unsigned int maskt : 4;
1630 unsigned int shiftt : 4;
1631 unsigned int cs : 1;
1632 unsigned int ms : 1;
1633 unsigned int masks : 4;
1634 unsigned int shifts : 4;
1635} Gsettile;
1636
1637typedef struct {
1638 int cmd : 8;
1639 unsigned int sl : 12;
1640 unsigned int tl : 12;
1641 int pad : 5;
1642 unsigned int tile : 3;
1643 unsigned int sh : 12;
1644 unsigned int th : 12;
1645} Gloadtile;
1646
1647typedef Gloadtile Gloadblock;
1648
1649typedef Gloadtile Gsettilesize;
1650
1651typedef Gloadtile Gloadtlut;
1652
1653typedef struct {
1654 unsigned int cmd : 8; /* command */
1655 unsigned int xl : 12; /* X coordinate of upper left */
1656 unsigned int yl : 12; /* Y coordinate of upper left */
1657 unsigned int pad1 : 5; /* Padding */
1658 unsigned int tile : 3; /* Tile descriptor index */
1659 unsigned int xh : 12; /* X coordinate of lower right */
1660 unsigned int yh : 12; /* Y coordinate of lower right */
1661 unsigned int s : 16; /* S texture coord at top left */
1662 unsigned int t : 16; /* T texture coord at top left */
1663 unsigned int dsdx : 16; /* Change in S per change in X */
1664 unsigned int dtdy : 16; /* Change in T per change in Y */
1665} Gtexrect;
1666
1667/*
1668 * Textured rectangles are 128 bits not 64 bits
1669 */
1670typedef struct {
1671 unsigned long w0;
1672 unsigned long w1;
1673 unsigned long w2;
1674 unsigned long w3;
1675} TexRect;
1676#endif
1677
1678#define MakeTexRect(xh, yh, flip, tile, xl, yl, s, t, dsdx, dtdy) \
1679 G_TEXRECT, xh, yh, 0, flip, 0, tile, xl, yl, s, t, dsdx, dtdy
1680
1681/*
1682 * Generic Gfx Packet
1683 */
1684typedef struct {
1685 uintptr_t w0;
1686 uintptr_t w1;
1687} Gwords;
1688
1689/*
1690 * This union is the fundamental type of the display list.
1691 * It is, by law, exactly 64 bits in size.
1692 *
1693 * (Edit: except on 64-bit, where it is exactly 128 bit. On little-endian or
1694 * 64-bit systems, only the 'words' member may be accessed; the rest of the
1695 * structs don't have matching layouts for now.)
1696 */
1697
1698typedef union {
1699 Gwords words;
1700#if !defined(F3D_OLD) && IS_BIG_ENDIAN && !IS_64_BIT
1701 Gdma dma;
1702 Gtri tri;
1703 Gline3D line;
1704 Gpopmtx popmtx;
1705 Gsegment segment;
1706 GsetothermodeH setothermodeH;
1707 GsetothermodeL setothermodeL;
1708 Gtexture texture;
1709 Gperspnorm perspnorm;
1710 Gsetimg setimg;
1711 Gsetcombine setcombine;
1712 Gsetcolor setcolor;
1713 Gfillrect fillrect; /* use for setscissor also */
1714 Gsettile settile;
1715 Gloadtile loadtile; /* use for loadblock also, th is dxt */
1716 Gsettilesize settilesize;
1717 Gloadtlut loadtlut;
1718#endif
1719 long long int force_structure_alignment;
1720} Gfx;
1721
1722/*
1723 * Macros to assemble the graphics display list
1724 */
1725
1726/*
1727 * DMA macros
1728 */
1729#define gDma0p(pkt, c, s, l) \
1730 { \
1731 Gfx* _g = (Gfx*) (pkt); \
1732 \
1733 _g->words.w0 = _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24); \
1734 _g->words.w1 = (uintptr_t) (s); \
1735 }
1736
1737#define gsDma0p(c, s, l) \
1738 { \
1739 { _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24), (uintptr_t) (s) } \
1740 }
1741
1742#define gDma1p(pkt, c, s, l, p) \
1743 { \
1744 Gfx* _g = (Gfx*) (pkt); \
1745 \
1746 _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | _SHIFTL((l), 0, 16)); \
1747 _g->words.w1 = (uintptr_t) (s); \
1748 }
1749
1750#define gsDma1p(c, s, l, p) \
1751 { \
1752 { (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | _SHIFTL((l), 0, 16)), (uintptr_t) (s) } \
1753 }
1754
1755#define gDma2p(pkt, c, adrs, len, idx, ofs) \
1756 { \
1757 Gfx* _g = (Gfx*) (pkt); \
1758 _g->words.w0 = \
1759 (_SHIFTL((c), 24, 8) | _SHIFTL(((len) - 1) / 8, 19, 5) | _SHIFTL((ofs) / 8, 8, 8) | _SHIFTL((idx), 0, 8)); \
1760 _g->words.w1 = (uintptr_t) (adrs); \
1761 }
1762#define gsDma2p(c, adrs, len, idx, ofs) \
1763 { \
1764 { \
1765 (_SHIFTL((c), 24, 8) | _SHIFTL(((len) - 1) / 8, 19, 5) | _SHIFTL((ofs) / 8, 8, 8) | _SHIFTL((idx), 0, 8)), \
1766 (uintptr_t) (adrs) \
1767 } \
1768 }
1769
1770#define gSPNoOp(pkt) gDma0p(pkt, G_SPNOOP, 0, 0)
1771#define gsSPNoOp() gsDma0p(G_SPNOOP, 0, 0)
1772
1773#ifdef F3DEX_GBI_2
1774#define gSPMatrix(pkt, m, p) gDma2p((pkt), G_MTX, (m), sizeof(Mtx), (p) ^ G_MTX_PUSH, 0)
1775#define gsSPMatrix(m, p) gsDma2p(G_MTX, (m), sizeof(Mtx), (p) ^ G_MTX_PUSH, 0)
1776#else /* F3DEX_GBI_2 */
1777#define gSPMatrix(pkt, m, p) gDma1p(pkt, G_MTX, m, sizeof(Mtx), p)
1778#define gsSPMatrix(m, p) gsDma1p(G_MTX, m, sizeof(Mtx), p)
1779#endif /* F3DEX_GBI_2 */
1780
1781#if defined(F3DEX_GBI_2)
1782/*
1783 * F3DEX_GBI_2: G_VTX GBI format was changed.
1784 *
1785 * +--------+----+---+---+----+------+-+
1786 * G_VTX | cmd:8 |0000| n:8 |0000|v0+n:7|0|
1787 * +-+---+--+----+---+---+----+------+-+
1788 * | |seg| address |
1789 * +-+---+-----------------------------+
1790 */
1791#define gSPVertex(pkt, v, n, v0) \
1792 { \
1793 Gfx* _g = (Gfx*) (pkt); \
1794 _g->words.w0 = _SHIFTL(G_VTX, 24, 8) | _SHIFTL((n), 12, 8) | _SHIFTL((v0) + (n), 1, 7); \
1795 _g->words.w1 = (uintptr_t) (v); \
1796 }
1797#define gsSPVertex(v, n, v0) \
1798 { \
1799 { (_SHIFTL(G_VTX, 24, 8) | _SHIFTL((n), 12, 8) | _SHIFTL((v0) + (n), 1, 7)), (uintptr_t) (v) } \
1800 }
1801#elif (defined(F3DEX_GBI) || defined(F3DLP_GBI))
1802/*
1803 * F3DEX_GBI: G_VTX GBI format was changed to support 64 vertice.
1804 *
1805 * +--------+--------+------+----------+
1806 * G_VTX | cmd:8 | v0:8 | n:6 |length:10 |
1807 * +-+---+--+--------+------+----------+
1808 * | |seg| address |
1809 * +-+---+-----------------------------+
1810 */
1811#define gSPVertex(pkt, v, n, v0) gDma1p((pkt), G_VTX, (v), ((n) << 10) | (sizeof(Vtx) * (n) - 1), (v0) * 2)
1812#define gsSPVertex(v, n, v0) gsDma1p(G_VTX, (v), ((n) << 10) | (sizeof(Vtx) * (n) - 1), (v0) * 2)
1813#else
1814#define gSPVertex(pkt, v, n, v0) gDma1p(pkt, G_VTX, v, sizeof(Vtx) * (n), ((n) - 1) << 4 | (v0))
1815#define gsSPVertex(v, n, v0) gsDma1p(G_VTX, v, sizeof(Vtx) * (n), ((n) - 1) << 4 | (v0))
1816#endif
1817
1818#ifdef F3DEX_GBI_2
1819#define gSPViewport(pkt, v) gDma2p((pkt), G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0)
1820#define gsSPViewport(v) gsDma2p(G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0)
1821#else /* F3DEX_GBI_2 */
1822#define gSPViewport(pkt, v) gDma1p((pkt), G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT)
1823#define gsSPViewport(v) gsDma1p(G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT)
1824#endif /* F3DEX_GBI_2 */
1825
1826#define gSPDisplayList(pkt, dl) gDma1p(pkt, G_DL, dl, 0, G_DL_PUSH)
1827#define gsSPDisplayList(dl) gsDma1p(G_DL, dl, 0, G_DL_PUSH)
1828
1829#define gSPBranchList(pkt, dl) gDma1p(pkt, G_DL, dl, 0, G_DL_NOPUSH)
1830#define gsSPBranchList(dl) gsDma1p(G_DL, dl, 0, G_DL_NOPUSH)
1831
1832#define gSPSprite2DBase(pkt, s) gDma1p(pkt, G_SPRITE2D_BASE, s, sizeof(uSprite), 0)
1833#define gsSPSprite2DBase(s) gsDma1p(G_SPRITE2D_BASE, s, sizeof(uSprite), 0)
1834
1835/*
1836 * RSP short command (no DMA required) macros
1837 */
1838#define gImmp0(pkt, c) \
1839 { \
1840 Gfx* _g = (Gfx*) (pkt); \
1841 \
1842 _g->words.w0 = _SHIFTL((c), 24, 8); \
1843 }
1844
1845#define gsImmp0(c) \
1846 { \
1847 { _SHIFTL((c), 24, 8) } \
1848 }
1849
1850#define gImmp1(pkt, c, p0) \
1851 { \
1852 Gfx* _g = (Gfx*) (pkt); \
1853 \
1854 _g->words.w0 = _SHIFTL((c), 24, 8); \
1855 _g->words.w1 = (uintptr_t) (p0); \
1856 }
1857
1858#define gsImmp1(c, p0) \
1859 { \
1860 { _SHIFTL((c), 24, 8), (uintptr_t) (p0) } \
1861 }
1862
1863#define gImmp2(pkt, c, p0, p1) \
1864 { \
1865 Gfx* _g = (Gfx*) (pkt); \
1866 \
1867 _g->words.w0 = _SHIFTL((c), 24, 8); \
1868 _g->words.w1 = _SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8); \
1869 }
1870
1871#define gsImmp2(c, p0, p1) \
1872 { \
1873 { _SHIFTL((c), 24, 8), _SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8) } \
1874 }
1875
1876#define gImmp3(pkt, c, p0, p1, p2) \
1877 { \
1878 Gfx* _g = (Gfx*) (pkt); \
1879 \
1880 _g->words.w0 = _SHIFTL((c), 24, 8); \
1881 _g->words.w1 = (_SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8) | _SHIFTL((p2), 0, 8)); \
1882 }
1883
1884#define gsImmp3(c, p0, p1, p2) \
1885 { \
1886 { _SHIFTL((c), 24, 8), (_SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8) | _SHIFTL((p2), 0, 8)) } \
1887 }
1888
1889#define gImmp21(pkt, c, p0, p1, dat) \
1890 { \
1891 Gfx* _g = (Gfx*) (pkt); \
1892 \
1893 _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | _SHIFTL((p1), 0, 8)); \
1894 _g->words.w1 = (uintptr_t) (dat); \
1895 }
1896
1897#define gsImmp21(c, p0, p1, dat) \
1898 { \
1899 { _SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | _SHIFTL((p1), 0, 8), (uintptr_t) (dat) } \
1900 }
1901
1902#ifdef F3DEX_GBI_2
1903#define gMoveWd(pkt, index, offset, data) gDma1p((pkt), G_MOVEWORD, data, offset, index)
1904#define gsMoveWd(index, offset, data) gsDma1p(G_MOVEWORD, data, offset, index)
1905#else /* F3DEX_GBI_2 */
1906#define gMoveWd(pkt, index, offset, data) gImmp21((pkt), G_MOVEWORD, offset, index, data)
1907#define gsMoveWd(index, offset, data) gsImmp21(G_MOVEWORD, offset, index, data)
1908#endif /* F3DEX_GBI_2 */
1909
1910/* Sprite immediate macros, there is also a sprite dma macro above */
1911
1912#define gSPSprite2DScaleFlip(pkt, sx, sy, fx, fy) \
1913 { \
1914 Gfx* _g = (Gfx*) (pkt); \
1915 \
1916 _g->words.w0 = (_SHIFTL(G_SPRITE2D_SCALEFLIP, 24, 8) | _SHIFTL((fx), 8, 8) | _SHIFTL((fy), 0, 8)); \
1917 _g->words.w1 = (_SHIFTL((sx), 16, 16) | _SHIFTL((sy), 0, 16)); \
1918 }
1919
1920#define gsSPSprite2DScaleFlip(sx, sy, fx, fy) \
1921 { \
1922 { \
1923 (_SHIFTL(G_SPRITE2D_SCALEFLIP, 24, 8) | _SHIFTL((fx), 8, 8) | _SHIFTL((fy), 0, 8)), \
1924 (_SHIFTL((sx), 16, 16) | _SHIFTL((sy), 0, 16)) \
1925 } \
1926 }
1927
1928#define gSPSprite2DDraw(pkt, px, py) \
1929 { \
1930 Gfx* _g = (Gfx*) (pkt); \
1931 \
1932 _g->words.w0 = (_SHIFTL(G_SPRITE2D_DRAW, 24, 8)); \
1933 _g->words.w1 = (_SHIFTL((px), 16, 16) | _SHIFTL((py), 0, 16)); \
1934 }
1935
1936#define gsSPSprite2DDraw(px, py) \
1937 { \
1938 { (_SHIFTL(G_SPRITE2D_DRAW, 24, 8)), (_SHIFTL((px), 16, 16) | _SHIFTL((py), 0, 16)) } \
1939 }
1940
1941/*
1942 * Note: the SP1Triangle() and line macros multiply the vertex indices
1943 * by 10, this is an optimization for the microcode.
1944 */
1945#if (defined(F3DLP_GBI) || defined(F3DEX_GBI))
1946#define __gsSP1Triangle_w1(v0, v1, v2) (_SHIFTL((v0) * 2, 16, 8) | _SHIFTL((v1) * 2, 8, 8) | _SHIFTL((v2) * 2, 0, 8))
1947#define __gsSP1Triangle_w1f(v0, v1, v2, flag) \
1948 (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2) \
1949 : ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v0) \
1950 : __gsSP1Triangle_w1(v2, v0, v1))
1951#define __gsSPLine3D_w1(v0, v1, wd) (_SHIFTL((v0) * 2, 16, 8) | _SHIFT((v1) * 2, 8, 8) | _SHIFT((wd), 0, 8))
1952#define __gsSPLine3D_w1f(v0, v1, wd, flag) (((flag) == 0) ? __gsSPLine3D_w1(v0, v1, wd) : __gsSPLine3D_w1(v1, v0, wd))
1953
1954// Only used on old F3DEX revisions, removed on latest revisions.
1955#define __gsSP1Quadrangle_w1(v0, v1, v2, v3) \
1956 (_SHIFTL((v3) * 2, 24, 8) | _SHIFTL((v0) * 2, 16, 8) | _SHIFTL((v1) * 2, 8, 8) | _SHIFTL((v2) * 2, 0, 8))
1957
1958#define __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag) \
1959 (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2) \
1960 : ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v3) \
1961 : ((flag) == 2) ? __gsSP1Triangle_w1(v2, v3, v0) \
1962 : __gsSP1Triangle_w1(v3, v0, v1))
1963#define __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \
1964 (((flag) == 0) ? __gsSP1Triangle_w1(v0, v2, v3) \
1965 : ((flag) == 1) ? __gsSP1Triangle_w1(v1, v3, v0) \
1966 : ((flag) == 2) ? __gsSP1Triangle_w1(v2, v0, v1) \
1967 : __gsSP1Triangle_w1(v3, v1, v2))
1968#else
1969#define __gsSP1Triangle_w1f(v0, v1, v2, flag) \
1970 (_SHIFTL((flag), 24, 8) | _SHIFTL((v0) * 10, 16, 8) | _SHIFTL((v1) * 10, 8, 8) | _SHIFTL((v2) * 10, 0, 8))
1971#define __gsSPLine3D_w1f(v0, v1, wd, flag) \
1972 (_SHIFTL((flag), 24, 8) | _SHIFTL((v0) * 10, 16, 8) | _SHIFTL((v1) * 10, 8, 8) | _SHIFTL((wd), 0, 8))
1973#endif
1974
1975#ifdef F3DEX_GBI_2
1976/***
1977 *** 1 Triangle
1978 ***/
1979#define gSP1Triangle(pkt, v0, v1, v2, flag) \
1980 { \
1981 Gfx* _g = (Gfx*) (pkt); \
1982 \
1983 _g->words.w0 = _SHIFTL(G_TRI1, 24, 8) | __gsSP1Triangle_w1f(v0, v1, v2, flag); \
1984 _g->words.w1 = 0; \
1985 }
1986#define gsSP1Triangle(v0, v1, v2, flag) \
1987 { \
1988 { _SHIFTL(G_TRI1, 24, 8) | __gsSP1Triangle_w1f(v0, v1, v2, flag), 0 } \
1989 }
1990
1991/***
1992 *** Line
1993 ***/
1994#define gSPLine3D(pkt, v0, v1, flag) \
1995 { \
1996 Gfx* _g = (Gfx*) (pkt); \
1997 \
1998 _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8) | __gsSPLine3D_w1f(v0, v1, 0, flag); \
1999 _g->words.w1 = 0; \
2000 }
2001#define gsSPLine3D(v0, v1, flag) \
2002 { \
2003 { _SHIFTL(G_LINE3D, 24, 8) | __gsSPLine3D_w1f(v0, v1, 0, flag), 0 } \
2004 }
2005
2006/***
2007 *** LineW
2008 ***/
2009/* these macros are the same as SPLine3D, except they have an
2010 * additional parameter for width. The width is added to the "minimum"
2011 * thickness, which is 1.5 pixels. The units for width are in
2012 * half-pixel units, so a width of 1 translates to (.5 + 1.5) or
2013 * a 2.0 pixels wide line.
2014 */
2015#define gSPLineW3D(pkt, v0, v1, wd, flag) \
2016 { \
2017 Gfx* _g = (Gfx*) (pkt); \
2018 \
2019 _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8) | __gsSPLine3D_w1f(v0, v1, wd, flag); \
2020 _g->words.w1 = 0; \
2021 }
2022#define gsSPLineW3D(v0, v1, wd, flag) \
2023 { \
2024 { _SHIFTL(G_LINE3D, 24, 8) | __gsSPLine3D_w1f(v0, v1, wd, flag), 0 } \
2025 }
2026
2027/***
2028 *** 1 Quadrangle
2029 ***/
2030#define gSP1Quadrangle(pkt, v0, v1, v2, v3, flag) \
2031 { \
2032 Gfx* _g = (Gfx*) (pkt); \
2033 \
2034 _g->words.w0 = (_SHIFTL(G_QUAD, 24, 8) | __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)); \
2035 _g->words.w1 = __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag); \
2036 }
2037
2038#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \
2039 { \
2040 { \
2041 (_SHIFTL(G_QUAD, 24, 8) | __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)), \
2042 __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \
2043 } \
2044 }
2045#else /* F3DEX_GBI_2 */
2046
2047/***
2048 *** 1 Triangle
2049 ***/
2050#define gSP1Triangle(pkt, v0, v1, v2, flag) \
2051 { \
2052 Gfx* _g = (Gfx*) (pkt); \
2053 \
2054 _g->words.w0 = _SHIFTL(G_TRI1, 24, 8); \
2055 _g->words.w1 = __gsSP1Triangle_w1f(v0, v1, v2, flag); \
2056 }
2057#define gsSP1Triangle(v0, v1, v2, flag) \
2058 { \
2059 { _SHIFTL(G_TRI1, 24, 8), __gsSP1Triangle_w1f(v0, v1, v2, flag) } \
2060 }
2061
2062/***
2063 *** Line
2064 ***/
2065#define gSPLine3D(pkt, v0, v1, flag) \
2066 { \
2067 Gfx* _g = (Gfx*) (pkt); \
2068 \
2069 _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8); \
2070 _g->words.w1 = __gsSPLine3D_w1f(v0, v1, 0, flag); \
2071 }
2072#define gsSPLine3D(v0, v1, flag) \
2073 { \
2074 { _SHIFTL(G_LINE3D, 24, 8), __gsSPLine3D_w1f(v0, v1, 0, flag) } \
2075 }
2076
2077/***
2078 *** LineW
2079 ***/
2080/* these macros are the same as SPLine3D, except they have an
2081 * additional parameter for width. The width is added to the "minimum"
2082 * thickness, which is 1.5 pixels. The units for width are in
2083 * half-pixel units, so a width of 1 translates to (.5 + 1.5) or
2084 * a 2.0 pixels wide line.
2085 */
2086#define gSPLineW3D(pkt, v0, v1, wd, flag) \
2087 { \
2088 Gfx* _g = (Gfx*) (pkt); \
2089 \
2090 _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8); \
2091 _g->words.w1 = __gsSPLine3D_w1f(v0, v1, wd, flag); \
2092 }
2093#define gsSPLineW3D(v0, v1, wd, flag) \
2094 { \
2095 { _SHIFTL(G_LINE3D, 24, 8), __gsSPLine3D_w1f(v0, v1, wd, flag) } \
2096 }
2097
2098// Early revision of quadrangle command uses G_QUAD instead of G_TRI2.
2099// It does not have a flag argument, this was added for compatibility.
2100// MK64: Appears to only be used in startup_logo.c
2101#ifdef F3D_OLD
2102/***
2103 *** 1 Quadrangle
2104 ***/
2105#define gSP1Quadrangle(v0, v1, v2, v3, flag) \
2106 { { Gfx* _g = (Gfx*) (pkt); \
2107 \
2108 _g->words.w0 = _SHIFTL(G_QUAD, 24, 8); \
2109 _g->words.w1 = __gsSP1Quadrangle_w1(v0, v1, v2, v3); \
2110 } \
2111 }
2112
2113#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \
2114 { \
2115 { _SHIFTL(G_QUAD, 24, 8), __gsSP1Quadrangle_w1(v0, v1, v2, v3) } \
2116 }
2117#else
2118/***
2119 *** 1 Quadrangle
2120 ***/
2121#define gSP1Quadrangle(pkt, v0, v1, v2, v3, flag) \
2122 { \
2123 Gfx* _g = (Gfx*) (pkt); \
2124 \
2125 _g->words.w0 = (_SHIFTL(G_TRI2, 24, 8) | __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)); \
2126 _g->words.w1 = __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag); \
2127 }
2128
2129#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \
2130 { \
2131 { \
2132 (_SHIFTL(G_TRI2, 24, 8) | __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)), \
2133 __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \
2134 } \
2135 }
2136#endif
2137#endif /* F3DEX_GBI_2 */
2138
2139#if (defined(F3DLP_GBI) || defined(F3DEX_GBI))
2140/***
2141 *** 2 Triangles
2142 ***/
2143#define gSP2Triangles(pkt, v00, v01, v02, flag0, v10, v11, v12, flag1) \
2144 { \
2145 Gfx* _g = (Gfx*) (pkt); \
2146 \
2147 _g->words.w0 = (_SHIFTL(G_TRI2, 24, 8) | __gsSP1Triangle_w1f(v00, v01, v02, flag0)); \
2148 _g->words.w1 = __gsSP1Triangle_w1f(v10, v11, v12, flag1); \
2149 }
2150
2151#define gsSP2Triangles(v00, v01, v02, flag0, v10, v11, v12, flag1) \
2152 { \
2153 { \
2154 (_SHIFTL(G_TRI2, 24, 8) | __gsSP1Triangle_w1f(v00, v01, v02, flag0)), \
2155 __gsSP1Triangle_w1f(v10, v11, v12, flag1) \
2156 } \
2157 }
2158#else
2159#define gSP2Triangles(pkt, v00, v01, v02, flag0, v10, v11, v12, flag1) \
2160 { \
2161 gSP1Triangle(pkt, v00, v01, v02, flag0); \
2162 gSP1Triangle(pkt, v10, v11, v12, flag1); \
2163 }
2164#define gsSP2Triangles(v00, v01, v02, flag0, v10, v11, v12, flag1) \
2165 gsSP1Triangle(v00, v01, v02, flag0), gsSP1Triangle(v10, v11, v12, flag1)
2166#endif /* F3DEX_GBI/F3DLP_GBI */
2167
2168#ifndef F3D_OLD
2169#if (defined(F3DEX_GBI) || defined(F3DLP_GBI))
2170#define gSPCullDisplayList(pkt, vstart, vend) \
2171 { \
2172 Gfx* _g = (Gfx*) (pkt); \
2173 \
2174 _g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | _SHIFTL((vstart) * 2, 0, 16); \
2175 _g->words.w1 = _SHIFTL((vend) * 2, 0, 16); \
2176 }
2177
2178#define gsSPCullDisplayList(vstart, vend) \
2179 { \
2180 { _SHIFTL(G_CULLDL, 24, 8) | _SHIFTL((vstart) * 2, 0, 16), _SHIFTL((vend) * 2, 0, 16) } \
2181 }
2182#endif
2183#else /* F3D_OLD */
2184#define gSPCullDisplayList(pkt, vstart, vend) \
2185 { \
2186 Gfx* _g = (Gfx*) (pkt); \
2187 \
2188 _g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | ((0x0f & (vstart)) * 40); \
2189 _g->words.w1 = (unsigned int) ((0x0f & ((vend) + 1)) * 40); \
2190 }
2191
2192#define gsSPCullDisplayList(vstart, vend) \
2193 { \
2194 { _SHIFTL(G_CULLDL, 24, 8) | ((0x0f & (vstart)) * 40), ((0x0f & ((vend) + 1)) * 40) } \
2195 }
2196#endif
2197
2198#define gSPSegment(pkt, segment, base) gMoveWd(pkt, G_MW_SEGMENT, (segment) * 4, base)
2199#define gsSPSegment(segment, base) gsMoveWd(G_MW_SEGMENT, (segment) * 4, base)
2200
2201/*
2202 * Clipping Macros
2203 */
2204#define FR_NEG_FRUSTRATIO_1 0x00000001
2205#define FR_POS_FRUSTRATIO_1 0x0000ffff
2206#define FR_NEG_FRUSTRATIO_2 0x00000002
2207#define FR_POS_FRUSTRATIO_2 0x0000fffe
2208#define FR_NEG_FRUSTRATIO_3 0x00000003
2209#define FR_POS_FRUSTRATIO_3 0x0000fffd
2210#define FR_NEG_FRUSTRATIO_4 0x00000004
2211#define FR_POS_FRUSTRATIO_4 0x0000fffc
2212#define FR_NEG_FRUSTRATIO_5 0x00000005
2213#define FR_POS_FRUSTRATIO_5 0x0000fffb
2214#define FR_NEG_FRUSTRATIO_6 0x00000006
2215#define FR_POS_FRUSTRATIO_6 0x0000fffa
2216/*
2217 * r should be one of: FRUSTRATIO_1, FRUSTRATIO_2, FRUSTRATIO_3, ... FRUSTRATIO_6
2218 */
2219#define gSPClipRatio(pkt, r) \
2220 { \
2221 gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RNX, FR_NEG_##r); \
2222 gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RNY, FR_NEG_##r); \
2223 gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RPX, FR_POS_##r); \
2224 gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RPY, FR_POS_##r); \
2225 }
2226
2227#define gsSPClipRatio(r) \
2228 gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RNX, FR_NEG_##r), gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RNY, FR_NEG_##r), \
2229 gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RPX, FR_POS_##r), gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RPY, FR_POS_##r)
2230
2231/*
2232 * Insert values into Matrix
2233 *
2234 * where = element of matrix (byte offset)
2235 * num = new element (32 bit value replacing 2 int or 2 frac matrix
2236 * componants
2237 */
2238#ifdef F3DEX_GBI_2
2239#define gSPInsertMatrix(pkt, where, num) ERROR !!gSPInsertMatrix is no longer supported.
2240#define gsSPInsertMatrix(where, num) ERROR !!gsSPInsertMatrix is no longer supported.
2241#else
2242#define gSPInsertMatrix(pkt, where, num) gMoveWd(pkt, G_MW_MATRIX, where, num)
2243#define gsSPInsertMatrix(where, num) gsMoveWd(G_MW_MATRIX, where, num)
2244#endif
2245
2246/*
2247 * Load new matrix directly
2248 *
2249 * mptr = pointer to matrix
2250 */
2251#ifdef F3DEX_GBI_2
2252#define gSPForceMatrix(pkt, mptr) \
2253 { \
2254 gDma2p((pkt), G_MOVEMEM, (mptr), sizeof(Mtx), G_MV_MATRIX, 0); \
2255 gMoveWd((pkt), G_MW_FORCEMTX, 0, 0x00010000); \
2256 }
2257#define gsSPForceMatrix(mptr) \
2258 gsDma2p(G_MOVEMEM, (mptr), sizeof(Mtx), G_MV_MATRIX, 0), gsMoveWd(G_MW_FORCEMTX, 0, 0x00010000)
2259
2260#else /* F3DEX_GBI_2 */
2261#define gSPForceMatrix(pkt, mptr) \
2262 { \
2263 gDma1p(pkt, G_MOVEMEM, mptr, 16, G_MV_MATRIX_1); \
2264 gDma1p(pkt, G_MOVEMEM, (char*) (mptr) + 16, 16, G_MV_MATRIX_2); \
2265 gDma1p(pkt, G_MOVEMEM, (char*) (mptr) + 32, 16, G_MV_MATRIX_3); \
2266 gDma1p(pkt, G_MOVEMEM, (char*) (mptr) + 48, 16, G_MV_MATRIX_4); \
2267 }
2268#define gsSPForceMatrix(mptr) \
2269 gsDma1p(G_MOVEMEM, mptr, 16, G_MV_MATRIX_1), gsDma1p(G_MOVEMEM, (char*) (mptr) + 16, 16, G_MV_MATRIX_2), \
2270 gsDma1p(G_MOVEMEM, (char*) (mptr) + 32, 16, G_MV_MATRIX_3), \
2271 gsDma1p(G_MOVEMEM, (char*) (mptr) + 48, 16, G_MV_MATRIX_4)
2272#endif /* F3DEX_GBI_2 */
2273
2274/*
2275 * Insert values into Points
2276 *
2277 * point = point number 0-15
2278 * where = which element of point to modify (byte offset into point)
2279 * num = new value (32 bit)
2280 */
2281#if (defined(F3DEX_GBI) || defined(F3DLP_GBI))
2282#define gSPModifyVertex(pkt, vtx, where, val) \
2283 { \
2284 Gfx* _g = (Gfx*) (pkt); \
2285 _g->words.w0 = (_SHIFTL(G_MODIFYVTX, 24, 8) | _SHIFTL((where), 16, 8) | _SHIFTL((vtx) * 2, 0, 16)); \
2286 _g->words.w1 = (unsigned int) (val); \
2287 }
2288#define gsSPModifyVertex(vtx, where, val) \
2289 { \
2290 { _SHIFTL(G_MODIFYVTX, 24, 8) | _SHIFTL((where), 16, 8) | _SHIFTL((vtx) * 2, 0, 16), (unsigned int) (val) } \
2291 }
2292#else
2293#define gSPModifyVertex(pkt, vtx, where, val) gMoveWd(pkt, G_MW_POINTS, (vtx) * 40 + (where), val)
2294#define gsSPModifyVertex(vtx, where, val) gsMoveWd(G_MW_POINTS, (vtx) * 40 + (where), val)
2295#endif
2296
2297#if (defined(F3DEX_GBI) || defined(F3DLP_GBI))
2298/*
2299 * gSPBranchLessZ Branch DL if (vtx.z) less than or equal (zval).
2300 *
2301 * dl = DL branch to
2302 * vtx = Vertex
2303 * zval = Screen depth
2304 * near = Near plane
2305 * far = Far plane
2306 * flag = G_BZ_PERSP or G_BZ_ORTHO
2307 */
2308
2309#define G_BZ_PERSP 0
2310#define G_BZ_ORTHO 1
2311
2312#define G_DEPTOZSrg(zval, near, far, flag, zmin, zmax) \
2313 (((unsigned int) FTOFIX32( \
2314 ((flag) == G_BZ_PERSP ? (1.0f - (float) (near) / (float) (zval)) / (1.0f - (float) (near) / (float) (far)) \
2315 : ((float) (zval) - (float) (near)) / ((float) (far) - (float) (near))))) * \
2316 (((int) ((zmax) - (zmin))) & ~1) + \
2317 (int) FTOFIX32(zmin))
2318
2319#define G_DEPTOZS(zval, near, far, flag) G_DEPTOZSrg(zval, near, far, flag, 0, G_MAXZ)
2320
2321#define gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, zmin, zmax) \
2322 { \
2323 Gfx* _g = (Gfx*) (pkt); \
2324 _g->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8); \
2325 _g->words.w1 = (uintptr_t) (dl); \
2326 _g = (Gfx*) (pkt); \
2327 _g->words.w0 = (_SHIFTL(G_BRANCH_Z, 24, 8) | _SHIFTL((vtx) * 5, 12, 12) | _SHIFTL((vtx) * 2, 0, 12)); \
2328 _g->words.w1 = G_DEPTOZSrg(zval, near, far, flag, zmin, zmax); \
2329 }
2330
2331#define gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, zmin, zmax) \
2332 { { \
2333 _SHIFTL(G_RDPHALF_1, 24, 8), \
2334 (uintptr_t) (dl), \
2335 } }, \
2336 { \
2337 { \
2338 _SHIFTL(G_BRANCH_Z, 24, 8) | _SHIFTL((vtx) * 5, 12, 12) | _SHIFTL((vtx) * 2, 0, 12), \
2339 G_DEPTOZSrg(zval, near, far, flag, zmin, zmax), \
2340 } \
2341 }
2342
2343#define gSPBranchLessZ(pkt, dl, vtx, zval, near, far, flag) \
2344 gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, 0, G_MAXZ)
2345#define gsSPBranchLessZ(dl, vtx, zval, near, far, flag) gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, 0, G_MAXZ)
2346
2347/*
2348 * gSPBranchLessZraw Branch DL if (vtx.z) less than or equal (raw zval).
2349 *
2350 * dl = DL branch to
2351 * vtx = Vertex
2352 * zval = Raw value of screen depth
2353 */
2354#define gSPBranchLessZraw(pkt, dl, vtx, zval) \
2355 { \
2356 Gfx* _g = (Gfx*) (pkt); \
2357 _g->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8); \
2358 _g->words.w1 = (uintptr_t) (dl); \
2359 _g = (Gfx*) (pkt); \
2360 _g->words.w0 = (_SHIFTL(G_BRANCH_Z, 24, 8) | _SHIFTL((vtx) * 5, 12, 12) | _SHIFTL((vtx) * 2, 0, 12)); \
2361 _g->words.w1 = (unsigned int) (zval); \
2362 }
2363
2364#define gsSPBranchLessZraw(dl, vtx, zval) \
2365 { { \
2366 _SHIFTL(G_RDPHALF_1, 24, 8), \
2367 (uintptr_t) (dl), \
2368 } }, \
2369 { \
2370 { \
2371 _SHIFTL(G_BRANCH_Z, 24, 8) | _SHIFTL((vtx) * 5, 12, 12) | _SHIFTL((vtx) * 2, 0, 12), \
2372 (unsigned int) (zval), \
2373 } \
2374 }
2375
2376/*
2377 * gSPLoadUcode RSP loads specified ucode.
2378 *
2379 * uc_start = ucode text section start
2380 * uc_dstart = ucode data section start
2381 */
2382#define gSPLoadUcodeEx(pkt, uc_start, uc_dstart, uc_dsize) \
2383 { \
2384 Gfx* _g = (Gfx*) (pkt); \
2385 _g->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8); \
2386 _g->words.w1 = (uintptr_t) (uc_dstart); \
2387 _g = (Gfx*) (pkt); \
2388 _g->words.w0 = (_SHIFTL(G_LOAD_UCODE, 24, 8) | _SHIFTL((int) (uc_dsize) - 1, 0, 16)); \
2389 _g->words.w1 = (uintptr_t) (uc_start); \
2390 }
2391
2392#define gsSPLoadUcodeEx(uc_start, uc_dstart, uc_dsize) \
2393 { { \
2394 _SHIFTL(G_RDPHALF_1, 24, 8), \
2395 (uintptr_t) (uc_dstart), \
2396 } }, \
2397 { \
2398 { _SHIFTL(G_LOAD_UCODE, 24, 8) | _SHIFTL((int) (uc_dsize) - 1, 0, 16), (uintptr_t) (uc_start), } \
2399 }
2400
2401#define gSPLoadUcode(pkt, uc_start, uc_dstart) gSPLoadUcodeEx((pkt), (uc_start), (uc_dstart), SP_UCODE_DATA_SIZE)
2402#define gsSPLoadUcode(uc_start, uc_dstart) gsSPLoadUcodeEx((uc_start), (uc_dstart), SP_UCODE_DATA_SIZE)
2403
2404#define gSPLoadUcodeL(pkt, ucode) \
2405 gSPLoadUcode((pkt), OS_K0_TO_PHYSICAL(&##ucode##TextStart), OS_K0_TO_PHYSICAL(&##ucode##DataStart))
2406#define gsSPLoadUcodeL(ucode) \
2407 gsSPLoadUcode(OS_K0_TO_PHYSICAL(&##ucode##TextStart), OS_K0_TO_PHYSICAL(&##ucode##DataStart))
2408#endif
2409
2410#ifdef F3DEX_GBI_2
2411/*
2412 * gSPDma_io DMA to/from DMEM/IMEM for DEBUG.
2413 */
2414#define gSPDma_io(pkt, flag, dmem, dram, size) \
2415 { \
2416 Gfx* _g = (Gfx*) (pkt); \
2417 _g->words.w0 = _SHIFTL(G_DMA_IO, 24, 8) | _SHIFTL((flag), 23, 1) | _SHIFTL((dmem) / 8, 13, 10) | \
2418 _SHIFTL((size) - 1, 0, 12); \
2419 _g->words.w1 = (uintptr_t) (dram); \
2420 }
2421
2422#define gsSPDma_io(flag, dmem, dram, size) \
2423 { \
2424 { \
2425 _SHIFTL(G_DMA_IO, 24, 8) | _SHIFTL((flag), 23, 1) | _SHIFTL((dmem) / 8, 13, 10) | \
2426 _SHIFTL((size) - 1, 0, 12), \
2427 (uintptr_t) (dram) \
2428 } \
2429 }
2430
2431#define gSPDmaRead(pkt, dmem, dram, size) gSPDma_io((pkt), 0, (dmem), (dram), (size))
2432#define gsSPDmaRead(dmem, dram, size) gsSPDma_io(0, (dmem), (dram), (size))
2433#define gSPDmaWrite(pkt, dmem, dram, size) gSPDma_io((pkt), 1, (dmem), (dram), (size))
2434#define gsSPDmaWrite(dmem, dram, size) gsSPDma_io(1, (dmem), (dram), (size))
2435#endif
2436
2437/*
2438 * Lighting Macros
2439 */
2440#ifdef F3DEX_GBI_2
2441#define NUML(n) ((n) * 24)
2442#else
2443#define NUML(n) (((n) + 1) * 32 + 0x80000000)
2444#endif
2445#define NUMLIGHTS_0 1
2446#define NUMLIGHTS_1 1
2447#define NUMLIGHTS_2 2
2448#define NUMLIGHTS_3 3
2449#define NUMLIGHTS_4 4
2450#define NUMLIGHTS_5 5
2451#define NUMLIGHTS_6 6
2452#define NUMLIGHTS_7 7
2453/*
2454 * n should be one of: NUMLIGHTS_0, NUMLIGHTS_1, ..., NUMLIGHTS_7
2455 * NOTE: in addition to the number of directional lights specified,
2456 * there is always 1 ambient light
2457 */
2458#define gSPNumLights(pkt, n) gMoveWd(pkt, G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n))
2459#define gsSPNumLights(n) gsMoveWd(G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n))
2460
2461#define LIGHT_1 1
2462#define LIGHT_2 2
2463#define LIGHT_3 3
2464#define LIGHT_4 4
2465#define LIGHT_5 5
2466#define LIGHT_6 6
2467#define LIGHT_7 7
2468#define LIGHT_8 8
2469/*
2470 * l should point to a Light struct
2471 * n should be one of: LIGHT_1, LIGHT_2, ..., LIGHT_8
2472 * NOTE: the highest numbered light is always the ambient light (eg if there are
2473 * 3 directional lights defined: gsSPNumLights(NUMLIGHTS_3), then lights
2474 * LIGHT_1 through LIGHT_3 will be the directional lights and light
2475 * LIGHT_4 will be the ambient light.
2476 */
2477#ifdef F3DEX_GBI_2
2478#define gSPLight(pkt, l, n) gDma2p((pkt), G_MOVEMEM, (l), sizeof(Light), G_MV_LIGHT, (n) * 24 + 24)
2479#define gsSPLight(l, n) gsDma2p(G_MOVEMEM, (l), sizeof(Light), G_MV_LIGHT, (n) * 24 + 24)
2480#else /* F3DEX_GBI_2 */
2481#define gSPLight(pkt, l, n) gDma1p(pkt, G_MOVEMEM, l, sizeof(Light), ((n) - 1) * 2 + G_MV_L0)
2482#define gsSPLight(l, n) gsDma1p(G_MOVEMEM, l, sizeof(Light), ((n) - 1) * 2 + G_MV_L0)
2483#endif /* F3DEX_GBI_2 */
2484
2485/*
2486 * gSPLightColor changes color of light without recalculating light direction
2487 * col is a 32 bit word with r,g,b,a (alpha is ignored)
2488 * n should be one of LIGHT_1, LIGHT_2, ..., LIGHT_8
2489 */
2490#define gSPLightColor(pkt, n, col) \
2491 { \
2492 gMoveWd(pkt, G_MW_LIGHTCOL, G_MWO_a##n, col); \
2493 gMoveWd(pkt, G_MW_LIGHTCOL, G_MWO_b##n, col); \
2494 }
2495#define gsSPLightColor(n, col) gsMoveWd(G_MW_LIGHTCOL, G_MWO_a##n, col), gsMoveWd(G_MW_LIGHTCOL, G_MWO_b##n, col)
2496
2497/* These macros use a structure "name" which is init'd with the gdSPDefLights macros*/
2498
2499#define gSPSetLights0(pkt, name) \
2500 { \
2501 gSPNumLights(pkt, NUMLIGHTS_0); \
2502 gSPLight(pkt, &name.l[0], 1); \
2503 gSPLight(pkt, &name.a, 2); \
2504 }
2505#define gsSPSetLights0(name) gsSPNumLights(NUMLIGHTS_0), gsSPLight(&name.l[0], 1), gsSPLight(&name.a, 2)
2506
2507#define gSPSetLights1(pkt, name) \
2508 { \
2509 gSPNumLights(pkt, NUMLIGHTS_1); \
2510 gSPLight(pkt, &name.l[0], 1); \
2511 gSPLight(pkt, &name.a, 2); \
2512 }
2513#define gsSPSetLights1(name) gsSPNumLights(NUMLIGHTS_1), gsSPLight(&name.l[0], 1), gsSPLight(&name.a, 2)
2514
2515#define gSPSetLights2(pkt, name) \
2516 { \
2517 gSPNumLights(pkt, NUMLIGHTS_2); \
2518 gSPLight(pkt, &name.l[0], 1); \
2519 gSPLight(pkt, &name.l[1], 2); \
2520 gSPLight(pkt, &name.a, 3); \
2521 }
2522#define gsSPSetLights2(name) \
2523 gsSPNumLights(NUMLIGHTS_2), gsSPLight(&name.l[0], 1), gsSPLight(&name.l[1], 2), gsSPLight(&name.a, 3)
2524
2525#define gSPSetLights3(pkt, name) \
2526 { \
2527 gSPNumLights(pkt, NUMLIGHTS_3); \
2528 gSPLight(pkt, &name.l[0], 1); \
2529 gSPLight(pkt, &name.l[1], 2); \
2530 gSPLight(pkt, &name.l[2], 3); \
2531 gSPLight(pkt, &name.a, 4); \
2532 }
2533#define gsSPSetLights3(name) \
2534 gsSPNumLights(NUMLIGHTS_3), gsSPLight(&name.l[0], 1), gsSPLight(&name.l[1], 2), gsSPLight(&name.l[2], 3), \
2535 gsSPLight(&name.a, 4)
2536
2537#define gSPSetLights4(pkt, name) \
2538 { \
2539 gSPNumLights(pkt, NUMLIGHTS_4); \
2540 gSPLight(pkt, &name.l[0], 1); \
2541 gSPLight(pkt, &name.l[1], 2); \
2542 gSPLight(pkt, &name.l[2], 3); \
2543 gSPLight(pkt, &name.l[3], 4); \
2544 gSPLight(pkt, &name.a, 5); \
2545 }
2546#define gsSPSetLights4(name) \
2547 gsSPNumLights(NUMLIGHTS_4), gsSPLight(&name.l[0], 1), gsSPLight(&name.l[1], 2), gsSPLight(&name.l[2], 3), \
2548 gsSPLight(&name.l[3], 4), gsSPLight(&name.a, 5)
2549
2550#define gSPSetLights5(pkt, name) \
2551 { \
2552 gSPNumLights(pkt, NUMLIGHTS_5); \
2553 gSPLight(pkt, &name.l[0], 1); \
2554 gSPLight(pkt, &name.l[1], 2); \
2555 gSPLight(pkt, &name.l[2], 3); \
2556 gSPLight(pkt, &name.l[3], 4); \
2557 gSPLight(pkt, &name.l[4], 5); \
2558 gSPLight(pkt, &name.a, 6); \
2559 }
2560
2561#define gsSPSetLights5(name) \
2562 gsSPNumLights(NUMLIGHTS_5), gsSPLight(&name.l[0], 1), gsSPLight(&name.l[1], 2), gsSPLight(&name.l[2], 3), \
2563 gsSPLight(&name.l[3], 4), gsSPLight(&name.l[4], 5), gsSPLight(&name.a, 6)
2564
2565#define gSPSetLights6(pkt, name) \
2566 { \
2567 gSPNumLights(pkt, NUMLIGHTS_6); \
2568 gSPLight(pkt, &name.l[0], 1); \
2569 gSPLight(pkt, &name.l[1], 2); \
2570 gSPLight(pkt, &name.l[2], 3); \
2571 gSPLight(pkt, &name.l[3], 4); \
2572 gSPLight(pkt, &name.l[4], 5); \
2573 gSPLight(pkt, &name.l[5], 6); \
2574 gSPLight(pkt, &name.a, 7); \
2575 }
2576
2577#define gsSPSetLights6(name) \
2578 gsSPNumLights(NUMLIGHTS_6), gsSPLight(&name.l[0], 1), gsSPLight(&name.l[1], 2), gsSPLight(&name.l[2], 3), \
2579 gsSPLight(&name.l[3], 4), gsSPLight(&name.l[4], 5), gsSPLight(&name.l[5], 6), gsSPLight(&name.a, 7)
2580
2581#define gSPSetLights7(pkt, name) \
2582 { \
2583 gSPNumLights(pkt, NUMLIGHTS_7); \
2584 gSPLight(pkt, &name.l[0], 1); \
2585 gSPLight(pkt, &name.l[1], 2); \
2586 gSPLight(pkt, &name.l[2], 3); \
2587 gSPLight(pkt, &name.l[3], 4); \
2588 gSPLight(pkt, &name.l[4], 5); \
2589 gSPLight(pkt, &name.l[5], 6); \
2590 gSPLight(pkt, &name.l[6], 7); \
2591 gSPLight(pkt, &name.a, 8); \
2592 }
2593
2594#define gsSPSetLights7(name) \
2595 gsSPNumLights(NUMLIGHTS_7), gsSPLight(&name.l[0], 1), gsSPLight(&name.l[1], 2), gsSPLight(&name.l[2], 3), \
2596 gsSPLight(&name.l[3], 4), gsSPLight(&name.l[4], 5), gsSPLight(&name.l[5], 6), gsSPLight(&name.l[6], 7), \
2597 gsSPLight(&name.a, 8)
2598
2599/*
2600 * Reflection/Hiliting Macros
2601 */
2602#ifdef F3DEX_GBI_2
2603#define gSPLookAtX(pkt, l) gDma2p((pkt), G_MOVEMEM, (l), sizeof(Light), G_MV_LIGHT, G_MVO_LOOKATX)
2604#define gsSPLookAtX(l) gsDma2p(G_MOVEMEM, (l), sizeof(Light), G_MV_LIGHT, G_MVO_LOOKATX)
2605#define gSPLookAtY(pkt, l) gDma2p((pkt), G_MOVEMEM, (l), sizeof(Light), G_MV_LIGHT, G_MVO_LOOKATY)
2606#define gsSPLookAtY(l) gsDma2p(G_MOVEMEM, (l), sizeof(Light), G_MV_LIGHT, G_MVO_LOOKATY)
2607#else /* F3DEX_GBI_2 */
2608#define gSPLookAtX(pkt, l) gDma1p(pkt, G_MOVEMEM, l, sizeof(Light), G_MV_LOOKATX)
2609#define gsSPLookAtX(l) gsDma1p(G_MOVEMEM, l, sizeof(Light), G_MV_LOOKATX)
2610#define gSPLookAtY(pkt, l) gDma1p(pkt, G_MOVEMEM, l, sizeof(Light), G_MV_LOOKATY)
2611#define gsSPLookAtY(l) gsDma1p(G_MOVEMEM, l, sizeof(Light), G_MV_LOOKATY)
2612#endif /* F3DEX_GBI_2 */
2613
2614#define gSPLookAt(pkt, la) { gSPLookAtX(pkt, la) gSPLookAtY(pkt, (char*) (la) + 16) }
2615#define gsSPLookAt(la) gsSPLookAtX(la), gsSPLookAtY((char*) (la) + 16)
2616
2617#define gDPSetHilite1Tile(pkt, tile, hilite, width, height) \
2618 gDPSetTileSize(pkt, tile, (hilite)->h.x1 & 0xfff, (hilite)->h.y1 & 0xfff, \
2619 ((((width) - 1) * 4) + (hilite)->h.x1) & 0xfff, ((((height) - 1) * 4) + (hilite)->h.y1) & 0xfff)
2620
2621#define gDPSetHilite2Tile(pkt, tile, hilite, width, height) \
2622 gDPSetTileSize(pkt, tile, (hilite)->h.x2 & 0xfff, (hilite)->h.y2 & 0xfff, \
2623 ((((width) - 1) * 4) + (hilite)->h.x2) & 0xfff, ((((height) - 1) * 4) + (hilite)->h.y2) & 0xfff)
2624
2625/*
2626 * FOG macros
2627 * fm = z multiplier
2628 * fo = z offset
2629 * FOG FORMULA: alpha(fog) = (eyespace z) * fm + fo CLAMPED 0 to 255
2630 * note: (eyespace z) ranges -1 to 1
2631 *
2632 * Alternate method of setting fog:
2633 * min, max: range 0 to 1000: 0=nearplane, 1000=farplane
2634 * min is where fog begins (usually less than max and often 0)
2635 * max is where fog is thickest (usually 1000)
2636 *
2637 */
2638#define gSPFogFactor(pkt, fm, fo) gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, (_SHIFTL(fm, 16, 16) | _SHIFTL(fo, 0, 16)))
2639
2640#define gsSPFogFactor(fm, fo) gsMoveWd(G_MW_FOG, G_MWO_FOG, (_SHIFTL(fm, 16, 16) | _SHIFTL(fo, 0, 16)))
2641
2642#define gSPFogPosition(pkt, min, max) \
2643 gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, \
2644 (_SHIFTL((128000 / ((max) - (min))), 16, 16) | _SHIFTL(((500 - (min)) * 256 / ((max) - (min))), 0, 16)))
2645
2646#define gsSPFogPosition(min, max) \
2647 gsMoveWd(G_MW_FOG, G_MWO_FOG, \
2648 (_SHIFTL((128000 / ((max) - (min))), 16, 16) | _SHIFTL(((500 - (min)) * 256 / ((max) - (min))), 0, 16)))
2649
2650#ifdef F3DEX_GBI_2
2651/*
2652 * Macros to turn texture on/off
2653 */
2654#define gSPTexture(pkt, s, t, level, tile, on) \
2655 { \
2656 Gfx* _g = (Gfx*) (pkt); \
2657 \
2658 _g->words.w0 = (_SHIFTL(G_TEXTURE, 24, 8) | _SHIFTL(BOWTIE_VAL, 16, 8) | _SHIFTL((level), 11, 3) | \
2659 _SHIFTL((tile), 8, 3) | _SHIFTL((on), 1, 7)); \
2660 _g->words.w1 = (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16)); \
2661 }
2662#define gsSPTexture(s, t, level, tile, on) \
2663 { \
2664 { \
2665 (_SHIFTL(G_TEXTURE, 24, 8) | _SHIFTL(BOWTIE_VAL, 16, 8) | _SHIFTL((level), 11, 3) | \
2666 _SHIFTL((tile), 8, 3) | _SHIFTL((on), 1, 7)), \
2667 (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16)) \
2668 } \
2669 }
2670/*
2671 * Different version of SPTexture macro, has an additional parameter
2672 * which is currently reserved in the microcode.
2673 */
2674#define gSPTextureL(pkt, s, t, level, xparam, tile, on) \
2675 { \
2676 Gfx* _g = (Gfx*) (pkt); \
2677 \
2678 _g->words.w0 = (_SHIFTL(G_TEXTURE, 24, 8) | _SHIFTL((xparam), 16, 8) | _SHIFTL((level), 11, 3) | \
2679 _SHIFTL((tile), 8, 3) | _SHIFTL((on), 1, 7)); \
2680 _g->words.w1 = (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16)); \
2681 }
2682#define gsSPTextureL(s, t, level, xparam, tile, on) \
2683 { \
2684 { \
2685 (_SHIFTL(G_TEXTURE, 24, 8) | _SHIFTL((xparam), 16, 8) | _SHIFTL((level), 11, 3) | _SHIFTL((tile), 8, 3) | \
2686 _SHIFTL((on), 1, 7)), \
2687 (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16)) \
2688 } \
2689 }
2690#else
2691/*
2692 * Macros to turn texture on/off
2693 */
2694#define gSPTexture(pkt, s, t, level, tile, on) \
2695 { \
2696 Gfx* _g = (Gfx*) (pkt); \
2697 \
2698 _g->words.w0 = (_SHIFTL(G_TEXTURE, 24, 8) | _SHIFTL(BOWTIE_VAL, 16, 8) | _SHIFTL((level), 11, 3) | \
2699 _SHIFTL((tile), 8, 3) | _SHIFTL((on), 0, 8)); \
2700 _g->words.w1 = (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16)); \
2701 }
2702#define gsSPTexture(s, t, level, tile, on) \
2703 { \
2704 { \
2705 (_SHIFTL(G_TEXTURE, 24, 8) | _SHIFTL(BOWTIE_VAL, 16, 8) | _SHIFTL((level), 11, 3) | \
2706 _SHIFTL((tile), 8, 3) | _SHIFTL((on), 0, 8)), \
2707 (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16)) \
2708 } \
2709 }
2710/*
2711 * Different version of SPTexture macro, has an additional parameter
2712 * which is currently reserved in the microcode.
2713 */
2714#define gSPTextureL(pkt, s, t, level, xparam, tile, on) \
2715 { \
2716 Gfx* _g = (Gfx*) (pkt); \
2717 \
2718 _g->words.w0 = (_SHIFTL(G_TEXTURE, 24, 8) | _SHIFTL((xparam), 16, 8) | _SHIFTL((level), 11, 3) | \
2719 _SHIFTL((tile), 8, 3) | _SHIFTL((on), 0, 8)); \
2720 _g->words.w1 = (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16)); \
2721 }
2722#define gsSPTextureL(s, t, level, xparam, tile, on) \
2723 { \
2724 { \
2725 (_SHIFTL(G_TEXTURE, 24, 8) | _SHIFTL((xparam), 16, 8) | _SHIFTL((level), 11, 3) | _SHIFTL((tile), 8, 3) | \
2726 _SHIFTL((on), 0, 8)), \
2727 (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16)) \
2728 } \
2729 }
2730#endif
2731
2732#ifndef F3D_OLD
2733#define gSPPerspNormalize(pkt, s) gMoveWd(pkt, G_MW_PERSPNORM, 0, (s))
2734#define gsSPPerspNormalize(s) gsMoveWd(G_MW_PERSPNORM, 0, (s))
2735#else
2736#define gSPPerspNormalize(pkt, s) \
2737 { \
2738 Gfx* _g = (Gfx*) (pkt); \
2739 \
2740 _g->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8); \
2741 _g->words.w1 = (s); \
2742 }
2743#define gsSPPerspNormalize(s) \
2744 { \
2745 { _SHIFTL(G_RDPHALF_1, 24, 8), (s) } \
2746 }
2747#endif
2748
2749#ifdef F3DEX_GBI_2
2750#define gSPPopMatrixN(pkt, n, num) gDma2p((pkt), G_POPMTX, (num) * 64, 64, 2, 0)
2751#define gsSPPopMatrixN(n, num) gsDma2p(G_POPMTX, (num) * 64, 64, 2, 0)
2752#define gSPPopMatrix(pkt, n) gSPPopMatrixN((pkt), (n), 1)
2753#define gsSPPopMatrix(n) gsSPPopMatrixN((n), 1)
2754#else /* F3DEX_GBI_2 */
2755#define gSPPopMatrix(pkt, n) gImmp1(pkt, G_POPMTX, n)
2756#define gsSPPopMatrix(n) gsImmp1(G_POPMTX, n)
2757#endif /* F3DEX_GBI_2 */
2758
2759#define gSPEndDisplayList(pkt) \
2760 { \
2761 Gfx* _g = (Gfx*) (pkt); \
2762 \
2763 _g->words.w0 = _SHIFTL(G_ENDDL, 24, 8); \
2764 _g->words.w1 = 0; \
2765 }
2766
2767#define gsSPEndDisplayList() \
2768 { \
2769 { _SHIFTL(G_ENDDL, 24, 8), 0 } \
2770 }
2771
2772#ifdef F3DEX_GBI_2
2773/*
2774 * One gSPGeometryMode(pkt,c,s) GBI is equal to these two GBIs.
2775 *
2776 * gSPClearGeometryMode(pkt,c)
2777 * gSPSetGeometryMode(pkt,s)
2778 *
2779 * gSPLoadGeometryMode(pkt, word) sets GeometryMode directly.
2780 */
2781#define gSPGeometryMode(pkt, c, s) \
2782 { \
2783 Gfx* _g = (Gfx*) (pkt); \
2784 _g->words.w0 = _SHIFTL(G_GEOMETRYMODE, 24, 8) | _SHIFTL(~(u32) (c), 0, 24); \
2785 _g->words.w1 = (u32) (s); \
2786 }
2787
2788#define gsSPGeometryMode(c, s) \
2789 { \
2790 { (_SHIFTL(G_GEOMETRYMODE, 24, 8) | _SHIFTL(~(u32) (c), 0, 24)), (u32) (s) } \
2791 }
2792#define gSPSetGeometryMode(pkt, word) gSPGeometryMode((pkt), 0, (word))
2793#define gsSPSetGeometryMode(word) gsSPGeometryMode(0, (word))
2794#define gSPClearGeometryMode(pkt, word) gSPGeometryMode((pkt), (word), 0)
2795#define gsSPClearGeometryMode(word) gsSPGeometryMode((word), 0)
2796#define gSPLoadGeometryMode(pkt, word) gSPGeometryMode((pkt), -1, (word))
2797#define gsSPLoadGeometryMode(word) gsSPGeometryMode(-1, (word))
2798#define gsSPGeometryModeSetFirst(c, s) gsSPGeometryMode(c, s)
2799#else /* F3DEX_GBI_2 */
2800#define gSPSetGeometryMode(pkt, word) \
2801 { \
2802 Gfx* _g = (Gfx*) (pkt); \
2803 \
2804 _g->words.w0 = _SHIFTL(G_SETGEOMETRYMODE, 24, 8); \
2805 _g->words.w1 = (unsigned int) (word); \
2806 }
2807
2808#define gsSPSetGeometryMode(word) \
2809 { \
2810 { _SHIFTL(G_SETGEOMETRYMODE, 24, 8), (unsigned int) (word) } \
2811 }
2812
2813#define gSPClearGeometryMode(pkt, word) \
2814 { \
2815 Gfx* _g = (Gfx*) (pkt); \
2816 \
2817 _g->words.w0 = _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8); \
2818 _g->words.w1 = (unsigned int) (word); \
2819 }
2820
2821#define gsSPClearGeometryMode(word) \
2822 { \
2823 { _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8), (unsigned int) (word) } \
2824 }
2825
2826/*
2827 * gsSPGeometryMode
2828 * In Fast3DEX2 it is better to use this, as the RSP geometry mode
2829 * is able to be set and cleared in a single command.
2830 */
2831#define gsSPGeometryMode(c, s) gsSPClearGeometryMode(c), gsSPSetGeometryMode(s)
2832#define gsSPGeometryModeSetFirst(c, s) gsSPSetGeometryMode(s), gsSPClearGeometryMode(c)
2833#endif /* F3DEX_GBI_2 */
2834
2835#ifdef F3DEX_GBI_2
2836#define gSPSetOtherMode(pkt, cmd, sft, len, data) \
2837 { \
2838 Gfx* _g = (Gfx*) (pkt); \
2839 _g->words.w0 = (_SHIFTL(cmd, 24, 8) | _SHIFTL(32 - (sft) - (len), 8, 8) | _SHIFTL((len) - 1, 0, 8)); \
2840 _g->words.w1 = (unsigned int) (data); \
2841 }
2842
2843#define gsSPSetOtherMode(cmd, sft, len, data) \
2844 { \
2845 { _SHIFTL(cmd, 24, 8) | _SHIFTL(32 - (sft) - (len), 8, 8) | _SHIFTL((len) - 1, 0, 8), (unsigned int) (data) } \
2846 }
2847#else
2848#define gSPSetOtherMode(pkt, cmd, sft, len, data) \
2849 { \
2850 Gfx* _g = (Gfx*) (pkt); \
2851 \
2852 _g->words.w0 = (_SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | _SHIFTL(len, 0, 8)); \
2853 _g->words.w1 = (unsigned int) (data); \
2854 }
2855
2856#define gsSPSetOtherMode(cmd, sft, len, data) \
2857 { \
2858 { _SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | _SHIFTL(len, 0, 8), (unsigned int) (data) } \
2859 }
2860#endif
2861
2862/*
2863 * RDP setothermode register commands - register shadowed in RSP
2864 */
2865#define gDPPipelineMode(pkt, mode) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode)
2866#define gsDPPipelineMode(mode) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode)
2867
2868#define gDPSetCycleType(pkt, type) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type)
2869#define gsDPSetCycleType(type) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type)
2870
2871#define gDPSetTexturePersp(pkt, type) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type)
2872#define gsDPSetTexturePersp(type) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type)
2873
2874#define gDPSetTextureDetail(pkt, type) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type)
2875#define gsDPSetTextureDetail(type) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type)
2876
2877#define gDPSetTextureLOD(pkt, type) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type)
2878#define gsDPSetTextureLOD(type) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type)
2879
2880#define gDPSetTextureLUT(pkt, type) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type)
2881#define gsDPSetTextureLUT(type) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type)
2882
2883#define gDPSetTextureFilter(pkt, type) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type)
2884#define gsDPSetTextureFilter(type) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type)
2885
2886#define gDPSetTextureConvert(pkt, type) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type)
2887#define gsDPSetTextureConvert(type) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type)
2888
2889#define gDPSetCombineKey(pkt, type) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type)
2890#define gsDPSetCombineKey(type) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type)
2891
2892#ifndef _HW_VERSION_1
2893#define gDPSetColorDither(pkt, mode) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode)
2894#define gsDPSetColorDither(mode) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode)
2895#else
2896#define gDPSetColorDither(pkt, mode) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_COLORDITHER, 1, mode)
2897#define gsDPSetColorDither(mode) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_COLORDITHER, 1, mode)
2898#endif
2899
2900#ifndef _HW_VERSION_1
2901#define gDPSetAlphaDither(pkt, mode) gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode)
2902#define gsDPSetAlphaDither(mode) gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode)
2903#endif
2904
2905/* 'blendmask' is not supported anymore.
2906 * The bits are reserved for future use.
2907 * Fri May 26 13:45:55 PDT 1995
2908 */
2909#define gDPSetBlendMask(pkt, mask) gDPNoOp(pkt)
2910#define gsDPSetBlendMask(mask) gsDPNoOp()
2911
2912#define gDPSetAlphaCompare(pkt, type) gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type)
2913#define gsDPSetAlphaCompare(type) gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type)
2914
2915#define gDPSetDepthSource(pkt, src) gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src)
2916#define gsDPSetDepthSource(src) gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src)
2917
2918#define gDPSetRenderMode(pkt, c0, c1) gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, (c0) | (c1))
2919#define gsDPSetRenderMode(c0, c1) gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, (c0) | (c1))
2920
2921#define gSetImage(pkt, cmd, fmt, siz, width, i) \
2922 { \
2923 Gfx* _g = (Gfx*) (pkt); \
2924 \
2925 _g->words.w0 = _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | _SHIFTL(siz, 19, 2) | _SHIFTL((width) - 1, 0, 12); \
2926 _g->words.w1 = (uintptr_t) (i); \
2927 }
2928
2929#define gsSetImage(cmd, fmt, siz, width, i) \
2930 { \
2931 { \
2932 _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | _SHIFTL(siz, 19, 2) | _SHIFTL((width) - 1, 0, 12), \
2933 (uintptr_t) (i) \
2934 } \
2935 }
2936
2937#define gDPSetColorImage(pkt, f, s, w, i) gSetImage(pkt, G_SETCIMG, f, s, w, i)
2938#define gsDPSetColorImage(f, s, w, i) gsSetImage(G_SETCIMG, f, s, w, i)
2939
2940/* use these for new code */
2941#define gDPSetDepthImage(pkt, i) gSetImage(pkt, G_SETZIMG, 0, 0, 1, i)
2942#define gsDPSetDepthImage(i) gsSetImage(G_SETZIMG, 0, 0, 1, i)
2943/* kept for compatibility */
2944#define gDPSetMaskImage(pkt, i) gDPSetDepthImage(pkt, i)
2945#define gsDPSetMaskImage(i) gsDPSetDepthImage(i)
2946
2947#define gDPSetTextureImage(pkt, f, s, w, i) gSetImage(pkt, G_SETTIMG, f, s, w, i)
2948#define gsDPSetTextureImage(f, s, w, i) gsSetImage(G_SETTIMG, f, s, w, i)
2949
2950/*
2951 * RDP macros
2952 */
2953
2954#define gDPSetCombine(pkt, muxs0, muxs1) \
2955 { \
2956 Gfx* _g = (Gfx*) (pkt); \
2957 \
2958 _g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24); \
2959 _g->words.w1 = (unsigned int) (muxs1); \
2960 }
2961
2962#define gsDPSetCombine(muxs0, muxs1) \
2963 { \
2964 { _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24), (unsigned int) (muxs1) } \
2965 }
2966
2967#define GCCc0w0(saRGB0, mRGB0, saA0, mA0) \
2968 (_SHIFTL((saRGB0), 20, 4) | _SHIFTL((mRGB0), 15, 5) | _SHIFTL((saA0), 12, 3) | _SHIFTL((mA0), 9, 3))
2969
2970#define GCCc1w0(saRGB1, mRGB1) (_SHIFTL((saRGB1), 5, 4) | _SHIFTL((mRGB1), 0, 5))
2971
2972#define GCCc0w1(sbRGB0, aRGB0, sbA0, aA0) \
2973 (_SHIFTL((sbRGB0), 28, 4) | _SHIFTL((aRGB0), 15, 3) | _SHIFTL((sbA0), 12, 3) | _SHIFTL((aA0), 9, 3))
2974
2975#define GCCc1w1(sbRGB1, saA1, mA1, aRGB1, sbA1, aA1) \
2976 (_SHIFTL((sbRGB1), 24, 4) | _SHIFTL((saA1), 21, 3) | _SHIFTL((mA1), 18, 3) | _SHIFTL((aRGB1), 6, 3) | \
2977 _SHIFTL((sbA1), 3, 3) | _SHIFTL((aA1), 0, 3))
2978
2979#define gDPSetCombineLERP(pkt, a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \
2980 { \
2981 Gfx* _g = (Gfx*) (pkt); \
2982 \
2983 _g->words.w0 = \
2984 _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \
2985 GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), \
2986 0, 24); \
2987 _g->words.w1 = (unsigned int) (GCCc0w1(G_CCMUX_##b0, G_CCMUX_##d0, G_ACMUX_##Ab0, G_ACMUX_##Ad0) | \
2988 GCCc1w1(G_CCMUX_##b1, G_ACMUX_##Aa1, G_ACMUX_##Ac1, G_CCMUX_##d1, \
2989 G_ACMUX_##Ab1, G_ACMUX_##Ad1)); \
2990 }
2991
2992#define gsDPSetCombineLERP(a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \
2993 { \
2994 { \
2995 _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \
2996 GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), \
2997 0, 24), \
2998 (unsigned int) (GCCc0w1(G_CCMUX_##b0, G_CCMUX_##d0, G_ACMUX_##Ab0, G_ACMUX_##Ad0) | \
2999 GCCc1w1(G_CCMUX_##b1, G_ACMUX_##Aa1, G_ACMUX_##Ac1, G_CCMUX_##d1, G_ACMUX_##Ab1, \
3000 G_ACMUX_##Ad1)) \
3001 } \
3002 }
3003
3004/*
3005 * SetCombineMode macros are NOT redunant. It allow the C preprocessor
3006 * to substitute single parameter which includes commas in the token and
3007 * rescan for higher parameter count macro substitution.
3008 *
3009 * eg. gsDPSetCombineMode(G_CC_MODULATE, G_CC_MODULATE) turns into
3010 * gsDPSetCombineLERP(TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0,
3011 * TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0)
3012 */
3013
3014#define gDPSetCombineMode(pkt, a, b) gDPSetCombineLERP(pkt, a, b)
3015#define gsDPSetCombineMode(a, b) gsDPSetCombineLERP(a, b)
3016
3017#define gDPSetColor(pkt, c, d) \
3018 { \
3019 Gfx* _g = (Gfx*) (pkt); \
3020 \
3021 _g->words.w0 = _SHIFTL(c, 24, 8); \
3022 _g->words.w1 = (unsigned int) (d); \
3023 }
3024
3025#define gsDPSetColor(c, d) \
3026 { \
3027 { _SHIFTL(c, 24, 8), (unsigned int) (d) } \
3028 }
3029
3030#define DPRGBColor(pkt, cmd, r, g, b, a) \
3031 gDPSetColor(pkt, cmd, (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8)))
3032#define sDPRGBColor(cmd, r, g, b, a) \
3033 gsDPSetColor(cmd, (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8)))
3034
3035#define gDPSetEnvColor(pkt, r, g, b, a) DPRGBColor(pkt, G_SETENVCOLOR, r, g, b, a)
3036#define gsDPSetEnvColor(r, g, b, a) sDPRGBColor(G_SETENVCOLOR, r, g, b, a)
3037#define gDPSetBlendColor(pkt, r, g, b, a) DPRGBColor(pkt, G_SETBLENDCOLOR, r, g, b, a)
3038#define gsDPSetBlendColor(r, g, b, a) sDPRGBColor(G_SETBLENDCOLOR, r, g, b, a)
3039#define gDPSetFogColor(pkt, r, g, b, a) DPRGBColor(pkt, G_SETFOGCOLOR, r, g, b, a)
3040#define gsDPSetFogColor(r, g, b, a) sDPRGBColor(G_SETFOGCOLOR, r, g, b, a)
3041#define gDPSetFillColor(pkt, d) gDPSetColor(pkt, G_SETFILLCOLOR, (d))
3042#define gsDPSetFillColor(d) gsDPSetColor(G_SETFILLCOLOR, (d))
3043
3044#define gDPSetPrimDepth(pkt, z, dz) gDPSetColor(pkt, G_SETPRIMDEPTH, _SHIFTL(z, 16, 16) | _SHIFTL(dz, 0, 16))
3045#define gsDPSetPrimDepth(z, dz) gsDPSetColor(G_SETPRIMDEPTH, _SHIFTL(z, 16, 16) | _SHIFTL(dz, 0, 16))
3046
3047#define gDPSetPrimColor(pkt, m, l, r, g, b, a) \
3048 { \
3049 Gfx* _g = (Gfx*) (pkt); \
3050 \
3051 _g->words.w0 = (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | _SHIFTL(m, 8, 8) | _SHIFTL(l, 0, 8)); \
3052 _g->words.w1 = (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8)); \
3053 }
3054
3055#define gsDPSetPrimColor(m, l, r, g, b, a) \
3056 { \
3057 { \
3058 (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | _SHIFTL(m, 8, 8) | _SHIFTL(l, 0, 8)), \
3059 (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8)) \
3060 } \
3061 }
3062
3063/*
3064 * gDPSetOtherMode (This is for expert user.)
3065 *
3066 * This command makes all othermode parameters set.
3067 * Do not use this command in the same DL with another g*SPSetOtherMode DLs.
3068 *
3069 * [Usage]
3070 * gDPSetOtherMode(pkt, modeA, modeB)
3071 *
3072 * 'modeA' is described all parameters of GroupA GBI command.
3073 * 'modeB' is also described all parameters of GroupB GBI command.
3074 *
3075 * GroupA:
3076 * gDPPipelineMode, gDPSetCycleType, gSPSetTexturePersp,
3077 * gDPSetTextureDetail, gDPSetTextureLOD, gDPSetTextureLUT,
3078 * gDPSetTextureFilter, gDPSetTextureConvert, gDPSetCombineKey,
3079 * gDPSetColorDither, gDPSetAlphaDither
3080 *
3081 * GroupB:
3082 * gDPSetAlphaCompare, gDPSetDepthSource, gDPSetRenderMode
3083 *
3084 * Use 'OR' operation to get modeA and modeB.
3085 *
3086 * modeA = G_PM_* | G_CYC_* | G_TP_* | G_TD_* | G_TL_* | G_TT_* | G_TF_*
3087 * G_TC_* | G_CK_* | G_CD_* | G_AD_*;
3088 *
3089 * modeB = G_AC_* | G_ZS_* | G_RM_* | G_RM_*2;
3090 */
3091#define gDPSetOtherMode(pkt, mode0, mode1) \
3092 { \
3093 Gfx* _g = (Gfx*) (pkt); \
3094 \
3095 _g->words.w0 = _SHIFTL(G_RDPSETOTHERMODE, 24, 8) | _SHIFTL(mode0, 0, 24); \
3096 _g->words.w1 = (unsigned int) (mode1); \
3097 }
3098
3099#define gsDPSetOtherMode(mode0, mode1) \
3100 { \
3101 { _SHIFTL(G_RDPSETOTHERMODE, 24, 8) | _SHIFTL(mode0, 0, 24), (unsigned int) (mode1) } \
3102 }
3103
3104/*
3105 * Texturing macros
3106 */
3107
3108/* These are also defined defined above for Sprite Microcode */
3109
3110#define G_TX_LOADTILE 7
3111#define G_TX_RENDERTILE 0
3112
3113#define G_TX_NOMIRROR 0
3114#define G_TX_WRAP 0
3115#define G_TX_MIRROR 0x1
3116#define G_TX_CLAMP 0x2
3117#define G_TX_NOMASK 0
3118#define G_TX_NOLOD 0
3119
3120#ifndef MAX
3121#define MAX(a, b) ((a) > (b) ? (a) : (b))
3122#endif
3123
3124#ifndef MIN
3125#define MIN(a, b) ((a) < (b) ? (a) : (b))
3126#endif
3127/*
3128 * Dxt is the inverse of the number of 64-bit words in a line of
3129 * the texture being loaded using the load_block command. If
3130 * there are any 1's to the right of the 11th fractional bit,
3131 * dxt should be rounded up. The following macros accomplish
3132 * this. The 4b macros are a special case since 4-bit textures
3133 * are loaded as 8-bit textures. Dxt is fixed point 1.11. RJM
3134 */
3135#define G_TX_DXT_FRAC 11
3136
3137/*
3138 * For RCP 2.0, the maximum number of texels that can be loaded
3139 * using a load_block command is 2048. In order to load the total
3140 * 4kB of Tmem, change the texel size when loading to be G_IM_SIZ_16b,
3141 * then change the tile to the proper texel size after the load.
3142 * The g*DPLoadTextureBlock macros already do this, so this change
3143 * will be transparent if you use these macros. If you use
3144 * the g*DPLoadBlock macros directly, you will need to handle this
3145 * tile manipulation yourself. RJM.
3146 */
3147#ifdef _HW_VERSION_1
3148#define G_TX_LDBLK_MAX_TXL 4095
3149#else
3150#define G_TX_LDBLK_MAX_TXL 2047
3151#endif /* _HW_VERSION_1 */
3152
3153#define TXL2WORDS(txls, b_txl) MAX(1, ((txls) * (b_txl) / 8))
3154#define CALC_DXT(width, b_txl) (((1 << G_TX_DXT_FRAC) + TXL2WORDS(width, b_txl) - 1) / TXL2WORDS(width, b_txl))
3155
3156#define TXL2WORDS_4b(txls) MAX(1, ((txls) / 16))
3157#define CALC_DXT_4b(width) (((1 << G_TX_DXT_FRAC) + TXL2WORDS_4b(width) - 1) / TXL2WORDS_4b(width))
3158
3159#define gDPLoadTileGeneric(pkt, c, tile, uls, ult, lrs, lrt) \
3160 { \
3161 Gfx* _g = (Gfx*) (pkt); \
3162 \
3163 _g->words.w0 = _SHIFTL(c, 24, 8) | _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12); \
3164 _g->words.w1 = _SHIFTL(tile, 24, 3) | _SHIFTL(lrs, 12, 12) | _SHIFTL(lrt, 0, 12); \
3165 }
3166
3167#define gsDPLoadTileGeneric(c, tile, uls, ult, lrs, lrt) \
3168 { \
3169 { \
3170 _SHIFTL(c, 24, 8) | _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12), \
3171 _SHIFTL(tile, 24, 3) | _SHIFTL(lrs, 12, 12) | _SHIFTL(lrt, 0, 12) \
3172 } \
3173 }
3174
3175#define gDPSetTileSize(pkt, t, uls, ult, lrs, lrt) gDPLoadTileGeneric(pkt, G_SETTILESIZE, t, uls, ult, lrs, lrt)
3176#define gsDPSetTileSize(t, uls, ult, lrs, lrt) gsDPLoadTileGeneric(G_SETTILESIZE, t, uls, ult, lrs, lrt)
3177#define gDPLoadTile(pkt, t, uls, ult, lrs, lrt) gDPLoadTileGeneric(pkt, G_LOADTILE, t, uls, ult, lrs, lrt)
3178#define gsDPLoadTile(t, uls, ult, lrs, lrt) gsDPLoadTileGeneric(G_LOADTILE, t, uls, ult, lrs, lrt)
3179
3180#define gDPSetTile(pkt, fmt, siz, line, tmem, tile, palette, cmt, maskt, shiftt, cms, masks, shifts) \
3181 { \
3182 Gfx* _g = (Gfx*) (pkt); \
3183 \
3184 _g->words.w0 = _SHIFTL(G_SETTILE, 24, 8) | _SHIFTL(fmt, 21, 3) | _SHIFTL(siz, 19, 2) | _SHIFTL(line, 9, 9) | \
3185 _SHIFTL(tmem, 0, 9); \
3186 _g->words.w1 = _SHIFTL(tile, 24, 3) | _SHIFTL(palette, 20, 4) | _SHIFTL(cmt, 18, 2) | _SHIFTL(maskt, 14, 4) | \
3187 _SHIFTL(shiftt, 10, 4) | _SHIFTL(cms, 8, 2) | _SHIFTL(masks, 4, 4) | _SHIFTL(shifts, 0, 4); \
3188 }
3189
3190#define gsDPSetTile(fmt, siz, line, tmem, tile, palette, cmt, maskt, shiftt, cms, masks, shifts) \
3191 { \
3192 { \
3193 (_SHIFTL(G_SETTILE, 24, 8) | _SHIFTL(fmt, 21, 3) | _SHIFTL(siz, 19, 2) | _SHIFTL(line, 9, 9) | \
3194 _SHIFTL(tmem, 0, 9)), \
3195 (_SHIFTL(tile, 24, 3) | _SHIFTL(palette, 20, 4) | _SHIFTL(cmt, 18, 2) | _SHIFTL(maskt, 14, 4) | \
3196 _SHIFTL(shiftt, 10, 4) | _SHIFTL(cms, 8, 2) | _SHIFTL(masks, 4, 4) | _SHIFTL(shifts, 0, 4)) \
3197 } \
3198 }
3199
3200/*
3201 * For RCP 2.0, the maximum number of texels that can be loaded
3202 * using a load_block command is 2048. In order to load the total
3203 * 4kB of Tmem, change the texel size when loading to be G_IM_SIZ_16b,
3204 * then change the tile to the proper texel size after the load.
3205 * The g*DPLoadTextureBlock macros already do this, so this change
3206 * will be transparent if you use these macros. If you use
3207 * the g*DPLoadBlock macros directly, you will need to handle this
3208 * tile manipulation yourself. RJM.
3209 */
3210#define gDPLoadBlock(pkt, tile, uls, ult, lrs, dxt) \
3211 { \
3212 Gfx* _g = (Gfx*) (pkt); \
3213 \
3214 _g->words.w0 = (_SHIFTL(G_LOADBLOCK, 24, 8) | _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12)); \
3215 _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL((MIN(lrs, G_TX_LDBLK_MAX_TXL)), 12, 12) | _SHIFTL(dxt, 0, 12)); \
3216 }
3217
3218#define gsDPLoadBlock(tile, uls, ult, lrs, dxt) \
3219 { \
3220 { \
3221 (_SHIFTL(G_LOADBLOCK, 24, 8) | _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12)), \
3222 (_SHIFTL(tile, 24, 3) | _SHIFTL((MIN(lrs, G_TX_LDBLK_MAX_TXL)), 12, 12) | _SHIFTL(dxt, 0, 12)) \
3223 } \
3224 }
3225
3226#define gDPLoadTLUTCmd(pkt, tile, count) \
3227 { \
3228 Gfx* _g = (Gfx*) pkt; \
3229 \
3230 _g->words.w0 = _SHIFTL(G_LOADTLUT, 24, 8); \
3231 _g->words.w1 = _SHIFTL((tile), 24, 3) | _SHIFTL((count), 14, 10); \
3232 }
3233
3234#define gsDPLoadTLUTCmd(tile, count) \
3235 { \
3236 { _SHIFTL(G_LOADTLUT, 24, 8), _SHIFTL((tile), 24, 3) | _SHIFTL((count), 14, 10) } \
3237 }
3238
3239#define gDPLoadTextureBlock(pkt, timg, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3240 { \
3241 gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \
3242 gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3243 gDPLoadSync(pkt); \
3244 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \
3245 CALC_DXT(width, siz##_BYTES)); \
3246 gDPPipeSync(pkt); \
3247 gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES) + 7) >> 3, 0, G_TX_RENDERTILE, pal, cmt, maskt, \
3248 shiftt, cms, masks, shifts); \
3249 gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3250 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3251 }
3252
3253#define gDPLoadTextureBlockYuv(pkt, timg, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3254 { \
3255 gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \
3256 gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3257 gDPLoadSync(pkt); \
3258 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \
3259 CALC_DXT(width, siz##_BYTES)); \
3260 gDPPipeSync(pkt); \
3261 gDPSetTile(pkt, fmt, siz, (((width) * 1) + 7) >> 3, 0, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \
3262 shifts); \
3263 gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3264 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3265 }
3266
3267/* Load fix rww 27jun95 */
3268/* The S at the end means odd lines are already word Swapped */
3269
3270#define gDPLoadTextureBlockS(pkt, timg, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3271 { \
3272 gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \
3273 gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3274 gDPLoadSync(pkt); \
3275 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, 0); \
3276 gDPPipeSync(pkt); \
3277 gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES) + 7) >> 3, 0, G_TX_RENDERTILE, pal, cmt, maskt, \
3278 shiftt, cms, masks, shifts); \
3279 gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3280 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3281 }
3282
3283/*
3284 * Allow tmem address and render tile to be specified.
3285 * The S at the end means odd lines are already word Swapped
3286 */
3287#define gDPLoadMultiBlockS(pkt, timg, tmem, rtile, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, \
3288 shiftt) \
3289 { \
3290 gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \
3291 gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3292 gDPLoadSync(pkt); \
3293 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, 0); \
3294 gDPPipeSync(pkt); \
3295 gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES) + 7) >> 3, tmem, rtile, pal, cmt, maskt, shiftt, cms, \
3296 masks, shifts); \
3297 gDPSetTileSize(pkt, rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3298 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3299 }
3300
3301#define gDPLoadTextureBlockYuvS(pkt, timg, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3302 { \
3303 gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \
3304 gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3305 gDPLoadSync(pkt); \
3306 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, 0); \
3307 gDPPipeSync(pkt); \
3308 gDPSetTile(pkt, fmt, siz, (((width) * 1) + 7) >> 3, 0, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \
3309 shifts); \
3310 gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3311 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3312 }
3313
3314/*
3315 * allows tmem address to be specified
3316 */
3317#define _gDPLoadTextureBlock(pkt, timg, tmem, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3318 { \
3319 gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \
3320 gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3321 gDPLoadSync(pkt); \
3322 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \
3323 CALC_DXT(width, siz##_BYTES)); \
3324 gDPPipeSync(pkt); \
3325 gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES) + 7) >> 3, tmem, G_TX_RENDERTILE, pal, cmt, maskt, \
3326 shiftt, cms, masks, shifts); \
3327 gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3328 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3329 }
3330
3331/*
3332 * allows tmem address and render tile to be specified
3333 */
3334#define _gDPLoadTextureBlockTile(pkt, timg, tmem, rtile, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, \
3335 shiftt) \
3336 { \
3337 gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \
3338 gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3339 gDPLoadSync(pkt); \
3340 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \
3341 CALC_DXT(width, siz##_BYTES)); \
3342 gDPPipeSync(pkt); \
3343 gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES) + 7) >> 3, tmem, rtile, pal, cmt, maskt, shiftt, cms, \
3344 masks, shifts); \
3345 gDPSetTileSize(pkt, rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3346 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3347 }
3348
3349/*
3350 * allows tmem address and render tile to be specified
3351 */
3352#define gDPLoadMultiBlock(pkt, timg, tmem, rtile, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, \
3353 shiftt) \
3354 { \
3355 gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \
3356 gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3357 gDPLoadSync(pkt); \
3358 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \
3359 CALC_DXT(width, siz##_BYTES)); \
3360 gDPPipeSync(pkt); \
3361 gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES) + 7) >> 3, tmem, rtile, pal, cmt, maskt, shiftt, cms, \
3362 masks, shifts); \
3363 gDPSetTileSize(pkt, rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3364 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3365 }
3366
3367#define gsDPLoadTextureBlock(timg, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3368 \
3369 gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \
3370 gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3371 gsDPLoadSync(), \
3372 gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \
3373 CALC_DXT(width, siz##_BYTES)), \
3374 gsDPPipeSync(), \
3375 gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, \
3376 cms, masks, shifts), \
3377 gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3378 ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3379
3380/* Here is the static form of the pre-swapped texture block loading */
3381/* See gDPLoadTextureBlockS() for reference. Basically, just don't
3382 calculate DxT, use 0 */
3383
3384#define gsDPLoadTextureBlockS(timg, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3385 \
3386 gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \
3387 gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3388 gsDPLoadSync(), gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, 0), \
3389 gsDPPipeSync(), \
3390 gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, \
3391 cms, masks, shifts), \
3392 gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3393 ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3394
3395/*
3396 * Allow tmem address to be specified
3397 */
3398#define _gsDPLoadTextureBlock(timg, tmem, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3399 \
3400 gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \
3401 gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3402 gsDPLoadSync(), \
3403 gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \
3404 CALC_DXT(width, siz##_BYTES)), \
3405 gsDPPipeSync(), \
3406 gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES) + 7) >> 3), tmem, G_TX_RENDERTILE, pal, cmt, maskt, \
3407 shiftt, cms, masks, shifts), \
3408 gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3409 ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3410
3411/*
3412 * Allow tmem address and render_tile to be specified
3413 */
3414#define _gsDPLoadTextureBlockTile(timg, tmem, rtile, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, \
3415 shiftt) \
3416 \
3417 gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \
3418 gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3419 gsDPLoadSync(), \
3420 gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \
3421 CALC_DXT(width, siz##_BYTES)), \
3422 gsDPPipeSync(), \
3423 gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES) + 7) >> 3), tmem, rtile, pal, cmt, maskt, shiftt, cms, \
3424 masks, shifts), \
3425 gsDPSetTileSize(rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3426
3427/*
3428 * Allow tmem address and render_tile to be specified, useful when loading
3429 * mutilple tiles at a time.
3430 */
3431#define gsDPLoadMultiBlock(timg, tmem, rtile, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3432 \
3433 gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \
3434 gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3435 gsDPLoadSync(), \
3436 gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \
3437 CALC_DXT(width, siz##_BYTES)), \
3438 gsDPPipeSync(), \
3439 gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES) + 7) >> 3), tmem, rtile, pal, cmt, maskt, shiftt, cms, \
3440 masks, shifts), \
3441 gsDPSetTileSize(rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3442
3443/*
3444 * Allows tmem and render tile to be specified. Useful when loading
3445 * several tiles at a time.
3446 *
3447 * Here is the static form of the pre-swapped texture block loading
3448 * See gDPLoadTextureBlockS() for reference. Basically, just don't
3449 * calculate DxT, use 0
3450 */
3451
3452#define gsDPLoadMultiBlockS(timg, tmem, rtile, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3453 \
3454 gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \
3455 gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3456 gsDPLoadSync(), gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, 0), \
3457 gsDPPipeSync(), \
3458 gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES) + 7) >> 3), tmem, rtile, pal, cmt, maskt, shiftt, cms, \
3459 masks, shifts), \
3460 gsDPSetTileSize(rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3461
3462#define gDPLoadTextureBlock_4b(pkt, timg, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3463 { \
3464 gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \
3465 gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3466 gDPLoadSync(pkt); \
3467 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, CALC_DXT_4b(width)); \
3468 gDPPipeSync(pkt); \
3469 gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, \
3470 cms, masks, shifts); \
3471 gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3472 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3473 }
3474
3475/* Load fix rww 27jun95 */
3476/* The S at the end means odd lines are already word Swapped */
3477
3478#define gDPLoadTextureBlock_4bS(pkt, timg, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3479 { \
3480 gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \
3481 gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3482 gDPLoadSync(pkt); \
3483 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, 0); \
3484 gDPPipeSync(pkt); \
3485 gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, \
3486 cms, masks, shifts); \
3487 gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3488 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3489 }
3490
3491/*
3492 * 4-bit load block. Useful when loading multiple tiles
3493 */
3494#define gDPLoadMultiBlock_4b(pkt, timg, tmem, rtile, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3495 { \
3496 gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \
3497 gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3498 gDPLoadSync(pkt); \
3499 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, CALC_DXT_4b(width)); \
3500 gDPPipeSync(pkt); \
3501 gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), tmem, rtile, pal, cmt, maskt, shiftt, cms, \
3502 masks, shifts); \
3503 gDPSetTileSize(pkt, rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3504 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3505 }
3506
3507/*
3508 * 4-bit load block. Allows tmem and render tile to be specified. Useful when
3509 * loading multiple tiles. The S means odd lines are already word swapped.
3510 */
3511#define gDPLoadMultiBlock_4bS(pkt, timg, tmem, rtile, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3512 { \
3513 gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \
3514 gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3515 gDPLoadSync(pkt); \
3516 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, 0); \
3517 gDPPipeSync(pkt); \
3518 gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), tmem, rtile, pal, cmt, maskt, shiftt, cms, \
3519 masks, shifts); \
3520 gDPSetTileSize(pkt, rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3521 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3522 }
3523
3524#define _gDPLoadTextureBlock_4b(pkt, timg, tmem, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3525 { \
3526 gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \
3527 gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \
3528 gDPLoadSync(pkt); \
3529 gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, CALC_DXT_4b(width)); \
3530 gDPPipeSync(pkt); \
3531 gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), tmem, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, \
3532 cms, masks, shifts); \
3533 gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3534 ((height) - 1) << G_TEXTURE_IMAGE_FRAC) \
3535 }
3536
3537#define gsDPLoadTextureBlock_4b(timg, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3538 \
3539 gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \
3540 gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3541 gsDPLoadSync(), gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, CALC_DXT_4b(width)), \
3542 gsDPPipeSync(), \
3543 gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, \
3544 masks, shifts), \
3545 gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3546 ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3547
3548#define gsDPLoadTextureBlock_4bS(timg, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3549 \
3550 gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \
3551 gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3552 gsDPLoadSync(), gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, 0), gsDPPipeSync(), \
3553 gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, \
3554 masks, shifts), \
3555 gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3556 ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3557
3558/*
3559 * 4-bit load block. Allows tmem address and render tile to be specified.
3560 * Useful when loading multiple tiles.
3561 */
3562#define gsDPLoadMultiBlock_4b(timg, tmem, rtile, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3563 \
3564 gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \
3565 gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3566 gsDPLoadSync(), gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, CALC_DXT_4b(width)), \
3567 gsDPPipeSync(), \
3568 gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), tmem, rtile, pal, cmt, maskt, shiftt, cms, masks, \
3569 shifts), \
3570 gsDPSetTileSize(rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3571
3572/*
3573 * 4-bit load block. Allows tmem address and render tile to be specified.
3574 * Useful when loading multiple tiles. S means odd lines are already swapped.
3575 */
3576#define gsDPLoadMultiBlock_4bS(timg, tmem, rtile, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3577 \
3578 gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \
3579 gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3580 gsDPLoadSync(), gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, 0), gsDPPipeSync(), \
3581 gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), tmem, rtile, pal, cmt, maskt, shiftt, cms, masks, \
3582 shifts), \
3583 gsDPSetTileSize(rtile, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3584
3585/*
3586 * Allows tmem address to be specified
3587 */
3588#define _gsDPLoadTextureBlock_4b(timg, tmem, fmt, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
3589 \
3590 gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \
3591 gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \
3592 gsDPLoadSync(), gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width) * (height) + 3) >> 2) - 1, CALC_DXT_4b(width)), \
3593 gsDPPipeSync(), \
3594 gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width) >> 1) + 7) >> 3), tmem, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, \
3595 cms, masks, shifts), \
3596 gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \
3597 ((height) - 1) << G_TEXTURE_IMAGE_FRAC)
3598
3599#ifndef _HW_VERSION_1
3600
3601#define gDPLoadTextureTile(pkt, timg, fmt, siz, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, maskt, \
3602 shifts, shiftt) \
3603 { \
3604 gDPSetTextureImage(pkt, fmt, siz, width, timg); \
3605 gDPSetTile(pkt, fmt, siz, (((((lrs) - (uls) + 1) * siz##_TILE_BYTES) + 7) >> 3), 0, G_TX_LOADTILE, 0, cmt, \
3606 maskt, shiftt, cms, masks, shifts); \
3607 gDPLoadSync(pkt); \
3608 gDPLoadTile(pkt, G_TX_LOADTILE, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3609 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC); \
3610 gDPPipeSync(pkt); \
3611 gDPSetTile(pkt, fmt, siz, (((((lrs) - (uls) + 1) * siz##_LINE_BYTES) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, \
3612 maskt, shiftt, cms, masks, shifts); \
3613 gDPSetTileSize(pkt, G_TX_RENDERTILE, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3614 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC) \
3615 }
3616
3617#else /******** WORKAROUND hw 1 load tile bug ********/
3618
3619#define gDPLoadTextureTile(pkt, timg, fmt, siz, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, maskt, \
3620 shifts, shiftt) \
3621 \
3622 { \
3623 int _loadtile_i, _loadtile_nw; \
3624 Gfx* _loadtile_temp = pkt; \
3625 guDPLoadTextureTile(_loadtile_temp, timg, fmt, siz, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, \
3626 maskt, shifts, shiftt); \
3627 _loadtile_nw = guGetDPLoadTextureTileSz(ult, lrt) - 1; \
3628 for (_loadtile_i = 0; _loadtile_i < _loadtile_nw; _loadtile_i++) \
3629 pkt; \
3630 }
3631
3632#endif /* HW_VERSION_1 */
3633
3634/*
3635 * Load texture tile. Allows tmem address and render tile to be specified.
3636 * Useful for loading multiple tiles.
3637 */
3638#define gDPLoadMultiTile(pkt, timg, tmem, rtile, fmt, siz, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, \
3639 maskt, shifts, shiftt) \
3640 { \
3641 gDPSetTextureImage(pkt, fmt, siz, width, timg); \
3642 gDPSetTile(pkt, fmt, siz, (((((lrs) - (uls) + 1) * siz##_TILE_BYTES) + 7) >> 3), tmem, G_TX_LOADTILE, 0, cmt, \
3643 maskt, shiftt, cms, masks, shifts); \
3644 gDPLoadSync(pkt); \
3645 gDPLoadTile(pkt, G_TX_LOADTILE, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3646 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC); \
3647 gDPPipeSync(pkt); \
3648 gDPSetTile(pkt, fmt, siz, (((((lrs) - (uls) + 1) * siz##_LINE_BYTES) + 7) >> 3), tmem, rtile, pal, cmt, maskt, \
3649 shiftt, cms, masks, shifts); \
3650 gDPSetTileSize(pkt, rtile, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3651 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC) \
3652 }
3653
3654#define gsDPLoadTextureTile(timg, fmt, siz, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, maskt, shifts, \
3655 shiftt) \
3656 \
3657 gsDPSetTextureImage(fmt, siz, width, timg), \
3658 gsDPSetTile(fmt, siz, (((((lrs) - (uls) + 1) * siz##_TILE_BYTES) + 7) >> 3), 0, G_TX_LOADTILE, 0, cmt, maskt, \
3659 shiftt, cms, masks, shifts), \
3660 gsDPLoadSync(), \
3661 gsDPLoadTile(G_TX_LOADTILE, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3662 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC), \
3663 gsDPPipeSync(), \
3664 gsDPSetTile(fmt, siz, (((((lrs) - (uls) + 1) * siz##_LINE_BYTES) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, \
3665 maskt, shiftt, cms, masks, shifts), \
3666 gsDPSetTileSize(G_TX_RENDERTILE, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3667 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC)
3668
3669/*
3670 * Load texture tile. Allows tmem address and render tile to be specified.
3671 * Useful for loading multiple tiles.
3672 */
3673#define gsDPLoadMultiTile(timg, tmem, rtile, fmt, siz, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, maskt, \
3674 shifts, shiftt) \
3675 \
3676 gsDPSetTextureImage(fmt, siz, width, timg), \
3677 gsDPSetTile(fmt, siz, (((((lrs) - (uls) + 1) * siz##_TILE_BYTES) + 7) >> 3), tmem, G_TX_LOADTILE, 0, cmt, \
3678 maskt, shiftt, cms, masks, shifts), \
3679 gsDPLoadSync(), \
3680 gsDPLoadTile(G_TX_LOADTILE, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3681 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC), \
3682 gsDPPipeSync(), \
3683 gsDPSetTile(fmt, siz, (((((lrs) - (uls) + 1) * siz##_LINE_BYTES) + 7) >> 3), tmem, rtile, pal, cmt, maskt, \
3684 shiftt, cms, masks, shifts), \
3685 gsDPSetTileSize(rtile, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3686 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC)
3687
3688#define gDPLoadTextureTile_4b(pkt, timg, fmt, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, maskt, shifts, \
3689 shiftt) \
3690 { \
3691 gDPSetTextureImage(pkt, fmt, G_IM_SIZ_8b, ((width) >> 1), timg); \
3692 gDPSetTile(pkt, fmt, G_IM_SIZ_8b, (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), 0, G_TX_LOADTILE, 0, cmt, maskt, \
3693 shiftt, cms, masks, shifts); \
3694 gDPLoadSync(pkt); \
3695 gDPLoadTile(pkt, G_TX_LOADTILE, (uls) << (G_TEXTURE_IMAGE_FRAC - 1), (ult) << (G_TEXTURE_IMAGE_FRAC), \
3696 (lrs) << (G_TEXTURE_IMAGE_FRAC - 1), (lrt) << (G_TEXTURE_IMAGE_FRAC)); \
3697 gDPPipeSync(pkt); \
3698 gDPSetTile(pkt, fmt, G_IM_SIZ_4b, (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, \
3699 maskt, shiftt, cms, masks, shifts); \
3700 gDPSetTileSize(pkt, G_TX_RENDERTILE, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3701 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC) \
3702 }
3703
3704/*
3705 * Load texture tile. Allows tmem address and render tile to be specified.
3706 * Useful for loading multiple tiles.
3707 */
3708#define gDPLoadMultiTile_4b(pkt, timg, tmem, rtile, fmt, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, \
3709 maskt, shifts, shiftt) \
3710 { \
3711 gDPSetTextureImage(pkt, fmt, G_IM_SIZ_8b, ((width) >> 1), timg); \
3712 gDPSetTile(pkt, fmt, G_IM_SIZ_8b, (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), tmem, G_TX_LOADTILE, 0, cmt, maskt, \
3713 shiftt, cms, masks, shifts); \
3714 gDPLoadSync(pkt); \
3715 gDPLoadTile(pkt, G_TX_LOADTILE, (uls) << (G_TEXTURE_IMAGE_FRAC - 1), (ult) << (G_TEXTURE_IMAGE_FRAC), \
3716 (lrs) << (G_TEXTURE_IMAGE_FRAC - 1), (lrt) << (G_TEXTURE_IMAGE_FRAC)); \
3717 gDPPipeSync(pkt); \
3718 gDPSetTile(pkt, fmt, G_IM_SIZ_4b, (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), tmem, rtile, pal, cmt, maskt, \
3719 shiftt, cms, masks, shifts); \
3720 gDPSetTileSize(pkt, rtile, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3721 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC) \
3722 }
3723
3724#define gsDPLoadTextureTile_4b(timg, fmt, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, maskt, shifts, \
3725 shiftt) \
3726 \
3727 gsDPSetTextureImage(fmt, G_IM_SIZ_8b, ((width) >> 1), timg), \
3728 gsDPSetTile(fmt, G_IM_SIZ_8b, (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), 0, G_TX_LOADTILE, 0, cmt, maskt, \
3729 shiftt, cms, masks, shifts), \
3730 gsDPLoadSync(), \
3731 gsDPLoadTile(G_TX_LOADTILE, (uls) << (G_TEXTURE_IMAGE_FRAC - 1), (ult) << (G_TEXTURE_IMAGE_FRAC), \
3732 (lrs) << (G_TEXTURE_IMAGE_FRAC - 1), (lrt) << (G_TEXTURE_IMAGE_FRAC)), \
3733 gsDPPipeSync(), \
3734 gsDPSetTile(fmt, G_IM_SIZ_4b, (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), 0, G_TX_RENDERTILE, pal, cmt, maskt, \
3735 shiftt, cms, masks, shifts), \
3736 gsDPSetTileSize(G_TX_RENDERTILE, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3737 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC)
3738
3739/*
3740 * Load texture tile. Allows tmem address and render tile to be specified.
3741 * Useful for loading multiple tiles.
3742 */
3743#define gsDPLoadMultiTile_4b(timg, tmem, rtile, fmt, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, maskt, \
3744 shifts, shiftt) \
3745 \
3746 gsDPSetTextureImage(fmt, G_IM_SIZ_8b, ((width) >> 1), timg), \
3747 gsDPSetTile(fmt, G_IM_SIZ_8b, (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), tmem, G_TX_LOADTILE, 0, cmt, maskt, \
3748 shiftt, cms, masks, shifts), \
3749 gsDPLoadSync(), \
3750 gsDPLoadTile(G_TX_LOADTILE, (uls) << (G_TEXTURE_IMAGE_FRAC - 1), (ult) << (G_TEXTURE_IMAGE_FRAC), \
3751 (lrs) << (G_TEXTURE_IMAGE_FRAC - 1), (lrt) << (G_TEXTURE_IMAGE_FRAC)), \
3752 gsDPPipeSync(), \
3753 gsDPSetTile(fmt, G_IM_SIZ_4b, (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), tmem, rtile, pal, cmt, maskt, shiftt, \
3754 cms, masks, shifts), \
3755 gsDPSetTileSize(rtile, (uls) << G_TEXTURE_IMAGE_FRAC, (ult) << G_TEXTURE_IMAGE_FRAC, \
3756 (lrs) << G_TEXTURE_IMAGE_FRAC, (lrt) << G_TEXTURE_IMAGE_FRAC)
3757
3758/*
3759 * Load a 16-entry palette (for 4-bit CI textures)
3760 * Assumes a 16 entry tlut is being loaded, palette # is 0-15
3761 */
3762#ifndef _HW_VERSION_1
3763
3764#define gDPLoadTLUT_pal16(pkt, pal, dram) \
3765 { \
3766 gDPSetTextureImage(pkt, G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram); \
3767 gDPTileSync(pkt); \
3768 gDPSetTile(pkt, 0, 0, 0, (256 + (((pal) & 0xf) * 16)), G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); \
3769 gDPLoadSync(pkt); \
3770 gDPLoadTLUTCmd(pkt, G_TX_LOADTILE, 15); \
3771 gDPPipeSync(pkt) \
3772 }
3773
3774#else /* **** WORKAROUND hardware 1 load_tlut bug ****** */
3775
3776#define gDPLoadTLUT_pal16(pkt, pal, dram) \
3777 \
3778 _gDPLoadTextureBlock(pkt, dram, (256 + (((pal) & 0xf) * 16)), G_IM_FMT_RGBA, G_IM_SIZ_16b, 4 * 16, 1, pal, 0, 0, \
3779 0, 0, 0, 0)
3780
3781#endif /* _HW_VERSION_1 */
3782
3783/*
3784 * Load a 16-entry palette (for 4-bit CI textures)
3785 * Assumes a 16 entry tlut is being loaded, palette # is 0-15
3786 */
3787#ifndef _HW_VERSION_1
3788
3789#define gsDPLoadTLUT_pal16(pal, dram) \
3790 \
3791 gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram), gsDPTileSync(), \
3792 gsDPSetTile(0, 0, 0, (256 + (((pal) & 0xf) * 16)), G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0), gsDPLoadSync(), \
3793 gsDPLoadTLUTCmd(G_TX_LOADTILE, 15), gsDPPipeSync()
3794
3795#else /* **** WORKAROUND hardware 1 load_tlut bug ****** */
3796
3797#define gsDPLoadTLUT_pal16(pal, dram) \
3798 \
3799 _gsDPLoadTextureBlock(dram, (256 + (((pal) & 0xf) * 16)), G_IM_FMT_RGBA, G_IM_SIZ_16b, 4 * 16, 1, pal, 0, 0, 0, 0, \
3800 0, 0)
3801
3802#endif /* _HW_VERSION_1 */
3803
3804/*
3805 * Load a 256-entry palette (for 8-bit CI textures)
3806 * Assumes a 256 entry tlut is being loaded, palette # is not used
3807 */
3808#ifndef _HW_VERSION_1
3809
3810#define gDPLoadTLUT_pal256(pkt, dram) \
3811 { \
3812 gDPSetTextureImage(pkt, G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram); \
3813 gDPTileSync(pkt); \
3814 gDPSetTile(pkt, 0, 0, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); \
3815 gDPLoadSync(pkt); \
3816 gDPLoadTLUTCmd(pkt, G_TX_LOADTILE, 255); \
3817 gDPPipeSync(pkt) \
3818 }
3819
3820#else /* **** WORKAROUND hardware 1 load_tlut bug ****** */
3821
3822#define gDPLoadTLUT_pal256(pkt, dram) \
3823 \
3824 _gDPLoadTextureBlock(pkt, dram, 256, G_IM_FMT_RGBA, G_IM_SIZ_16b, 4 * 256, 1, 0, 0, 0, 0, 0, 0, 0)
3825
3826#endif /* _HW_VERSION_1 */
3827
3828#ifndef _HW_VERSION_1
3829
3830#define gsDPLoadTLUT_pal256(dram) \
3831 \
3832 gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram), gsDPTileSync(), \
3833 gsDPSetTile(0, 0, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0), gsDPLoadSync(), \
3834 gsDPLoadTLUTCmd(G_TX_LOADTILE, 255), gsDPPipeSync()
3835
3836#else /* **** WORKAROUND hardware 1 load_tlut bug ****** */
3837
3838#define gsDPLoadTLUT_pal256(dram) \
3839 \
3840 _gsDPLoadTextureBlock(dram, 256, G_IM_FMT_RGBA, G_IM_SIZ_16b, 4 * 256, 1, 0, 0, 0, 0, 0, 0, 0)
3841
3842#endif /* _HW_VERSION_1 */
3843
3844#ifndef _HW_VERSION_1
3845
3846#define gDPLoadTLUT(pkt, count, tmemaddr, dram) \
3847 { \
3848 gDPSetTextureImage(pkt, G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram); \
3849 gDPTileSync(pkt); \
3850 gDPSetTile(pkt, 0, 0, 0, tmemaddr, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); \
3851 gDPLoadSync(pkt); \
3852 gDPLoadTLUTCmd(pkt, G_TX_LOADTILE, ((count) - 1)); \
3853 gDPPipeSync(pkt); \
3854 }
3855
3856#else /* **** WORKAROUND hardware 1 load_tlut bug ****** */
3857
3858#define gDPLoadTLUT(pkt, count, tmemaddr, dram) \
3859 \
3860 _gDPLoadTextureBlock(pkt, dram, tmemaddr, G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, count, 0, 0, 0, 0, 0, 0, 0)
3861
3862#endif /* _HW_VERSION_1 */
3863
3864#ifndef _HW_VERSION_1
3865
3866#define gsDPLoadTLUT(count, tmemaddr, dram) \
3867 \
3868 gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram), gsDPTileSync(), \
3869 gsDPSetTile(0, 0, 0, tmemaddr, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0), gsDPLoadSync(), \
3870 gsDPLoadTLUTCmd(G_TX_LOADTILE, ((count) - 1)), gsDPPipeSync()
3871
3872#else /* **** WORKAROUND hardware 1 load_tlut bug ****** */
3873#define gsDPLoadTLUT(count, tmemaddr, dram) \
3874 \
3875 _gsDPLoadTextureBlock(dram, tmemaddr, G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, count, 0, 0, 0, 0, 0, 0, 0)
3876
3877#endif /* _HW_VERSION_1 */
3878
3879#define gDPSetScissor(pkt, mode, ulx, uly, lrx, lry) \
3880 { \
3881 Gfx* _g = (Gfx*) pkt; \
3882 \
3883 _g->words.w0 = _SHIFTL(G_SETSCISSOR, 24, 8) | _SHIFTL((int) ((float) (ulx) * 4.0F), 12, 12) | \
3884 _SHIFTL((int) ((float) (uly) * 4.0F), 0, 12); \
3885 _g->words.w1 = _SHIFTL(mode, 24, 2) | _SHIFTL((int) ((float) (lrx) * 4.0F), 12, 12) | \
3886 _SHIFTL((int) ((float) (lry) * 4.0F), 0, 12); \
3887 }
3888
3889#define gDPSetScissorFrac(pkt, mode, ulx, uly, lrx, lry) \
3890 { \
3891 Gfx* _g = (Gfx*) pkt; \
3892 \
3893 _g->words.w0 = _SHIFTL(G_SETSCISSOR, 24, 8) | _SHIFTL((int) ((ulx)), 12, 12) | _SHIFTL((int) ((uly)), 0, 12); \
3894 _g->words.w1 = _SHIFTL(mode, 24, 2) | _SHIFTL((int) ((lrx)), 12, 12) | _SHIFTL((int) ((lry)), 0, 12); \
3895 }
3896
3897#define gsDPSetScissor(mode, ulx, uly, lrx, lry) \
3898 { \
3899 { \
3900 _SHIFTL(G_SETSCISSOR, 24, 8) | _SHIFTL((int) ((float) (ulx) * 4.0F), 12, 12) | \
3901 _SHIFTL((int) ((float) (uly) * 4.0F), 0, 12), \
3902 _SHIFTL(mode, 24, 2) | _SHIFTL((int) ((float) (lrx) * 4.0F), 12, 12) | \
3903 _SHIFTL((int) ((float) (lry) * 4.0F), 0, 12) \
3904 } \
3905 }
3906
3907#define gsDPSetScissorFrac(mode, ulx, uly, lrx, lry) \
3908 { \
3909 { \
3910 _SHIFTL(G_SETSCISSOR, 24, 8) | _SHIFTL((int) ((ulx)), 12, 12) | _SHIFTL((int) ((uly)), 0, 12), \
3911 _SHIFTL(mode, 24, 2) | _SHIFTL((int) (lrx), 12, 12) | _SHIFTL((int) (lry), 0, 12) \
3912 } \
3913 }
3914
3915/* Fraction never used in fill */
3916#define gDPFillRectangle(pkt, ulx, uly, lrx, lry) \
3917 { \
3918 Gfx* _g = (Gfx*) (pkt); \
3919 \
3920 _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL((lrx), 14, 10) | _SHIFTL((lry), 2, 10)); \
3921 _g->words.w1 = (_SHIFTL((ulx), 14, 10) | _SHIFTL((uly), 2, 10)); \
3922 }
3923
3924#define gsDPFillRectangle(ulx, uly, lrx, lry) \
3925 { \
3926 { \
3927 (_SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL((lrx), 14, 10) | _SHIFTL((lry), 2, 10)), \
3928 (_SHIFTL((ulx), 14, 10) | _SHIFTL((uly), 2, 10)) \
3929 } \
3930 }
3931
3932/* like gDPFillRectangle but accepts negative arguments */
3933#define gDPScisFillRectangle(pkt, ulx, uly, lrx, lry) \
3934 { \
3935 Gfx* _g = (Gfx*) (pkt); \
3936 \
3937 _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL(MAX((lrx), 0), 14, 10) | _SHIFTL(MAX((lry), 0), 2, 10)); \
3938 _g->words.w1 = (_SHIFTL(MAX((ulx), 0), 14, 10) | _SHIFTL(MAX((uly), 0), 2, 10)); \
3939 }
3940
3941#define gDPSetConvert(pkt, k0, k1, k2, k3, k4, k5) \
3942 { \
3943 Gfx* _g = (Gfx*) (pkt); \
3944 \
3945 _g->words.w0 = (_SHIFTL(G_SETCONVERT, 24, 8) | _SHIFTL(k0, 13, 9) | _SHIFTL(k1, 4, 9) | _SHIFTR(k2, 5, 4)); \
3946 _g->words.w1 = (_SHIFTL(k2, 27, 5) | _SHIFTL(k3, 18, 9) | _SHIFTL(k4, 9, 9) | _SHIFTL(k5, 0, 9)); \
3947 }
3948
3949#define gsDPSetConvert(k0, k1, k2, k3, k4, k5) \
3950 { \
3951 { \
3952 (_SHIFTL(G_SETCONVERT, 24, 8) | _SHIFTL(k0, 13, 9) | _SHIFTL(k1, 4, 9) | _SHIFTR(k2, 5, 4)), \
3953 (_SHIFTL(k2, 27, 5) | _SHIFTL(k3, 18, 9) | _SHIFTL(k4, 9, 9) | _SHIFTL(k5, 0, 9)) \
3954 } \
3955 }
3956
3957#define gDPSetKeyR(pkt, cR, sR, wR) \
3958 { \
3959 Gfx* _g = (Gfx*) (pkt); \
3960 \
3961 _g->words.w0 = _SHIFTL(G_SETKEYR, 24, 8); \
3962 _g->words.w1 = (_SHIFTL(wR, 16, 12) | _SHIFTL(cR, 8, 8) | _SHIFTL(sR, 0, 8)); \
3963 }
3964
3965#define gsDPSetKeyR(cR, sR, wR) \
3966 { \
3967 { _SHIFTL(G_SETKEYR, 24, 8), _SHIFTL(wR, 16, 12) | _SHIFTL(cR, 8, 8) | _SHIFTL(sR, 0, 8) } \
3968 }
3969
3970#define gDPSetKeyGB(pkt, cG, sG, wG, cB, sB, wB) \
3971 { \
3972 Gfx* _g = (Gfx*) (pkt); \
3973 \
3974 _g->words.w0 = (_SHIFTL(G_SETKEYGB, 24, 8) | _SHIFTL(wG, 12, 12) | _SHIFTL(wB, 0, 12)); \
3975 _g->words.w1 = (_SHIFTL(cG, 24, 8) | _SHIFTL(sG, 16, 8) | _SHIFTL(cB, 8, 8) | _SHIFTL(sB, 0, 8)); \
3976 }
3977
3978#define gsDPSetKeyGB(cG, sG, wG, cB, sB, wB) \
3979 { \
3980 { \
3981 (_SHIFTL(G_SETKEYGB, 24, 8) | _SHIFTL(wG, 12, 12) | _SHIFTL(wB, 0, 12)), \
3982 (_SHIFTL(cG, 24, 8) | _SHIFTL(sG, 16, 8) | _SHIFTL(cB, 8, 8) | _SHIFTL(sB, 0, 8)) \
3983 } \
3984 }
3985
3986#define gDPNoParam(pkt, cmd) \
3987 { \
3988 Gfx* _g = (Gfx*) (pkt); \
3989 \
3990 _g->words.w0 = _SHIFTL(cmd, 24, 8); \
3991 _g->words.w1 = 0; \
3992 }
3993
3994#define gsDPNoParam(cmd) \
3995 { \
3996 { _SHIFTL(cmd, 24, 8), 0 } \
3997 }
3998
3999#define gDPParam(pkt, cmd, param) \
4000 { \
4001 Gfx* _g = (Gfx*) (pkt); \
4002 \
4003 _g->words.w0 = _SHIFTL(cmd, 24, 8); \
4004 _g->words.w1 = (param); \
4005 }
4006
4007#define gsDPParam(cmd, param) \
4008 { \
4009 { _SHIFTL(cmd, 24, 8), (param) } \
4010 }
4011
4012/* Notice that textured rectangles are 128-bit commands, therefore
4013 * gsDPTextureRectangle() should not be used in display lists
4014 * under normal circumstances (use gsSPTextureRectangle()).
4015 * That is also why there is no gDPTextureRectangle() macros.
4016 */
4017#define gsDPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4018 { { \
4019 (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)), \
4020 (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \
4021 } }, \
4022 { \
4023 { _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) } \
4024 }
4025
4026#define gDPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4027 { \
4028 Gfx* _g = (Gfx*) (pkt); \
4029 if (pkt) \
4030 ; \
4031 _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)); \
4032 _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)); \
4033 _g++; \
4034 _g->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \
4035 _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \
4036 }
4037
4038#define gsDPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4039 { { \
4040 (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)), \
4041 (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \
4042 } }, \
4043 { \
4044 { _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) } \
4045 }
4046
4047#define gDPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4048 { \
4049 Gfx* _g = (Gfx*) (pkt); \
4050 if (pkt) \
4051 ; \
4052 _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)); \
4053 _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)); \
4054 _g++; \
4055 _g->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \
4056 _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \
4057 }
4058
4059#ifdef F3D_OLD
4060#define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4061 { \
4062 Gfx* _g = (Gfx*) (pkt); \
4063 \
4064 _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)); \
4065 _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)); \
4066 gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \
4067 gImmp1(pkt, G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \
4068 }
4069
4070#define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4071 { { (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)), \
4072 (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)) } }, \
4073 gsImmp1(G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \
4074 gsImmp1(G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)))
4075
4076/* like gSPTextureRectangle but accepts negative position arguments */
4077#define gSPScisTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4078 { \
4079 Gfx* _g = (Gfx*) (pkt); \
4080 \
4081 _g->words.w0 = \
4082 (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(MAX((s16) (xh), 0), 12, 12) | _SHIFTL(MAX((s16) (yh), 0), 0, 12)); \
4083 _g->words.w1 = \
4084 (_SHIFTL((tile), 24, 3) | _SHIFTL(MAX((s16) (xl), 0), 12, 12) | _SHIFTL(MAX((s16) (yl), 0), 0, 12)); \
4085 gImmp1(pkt, G_RDPHALF_2, \
4086 (_SHIFTL(((s) - (((s16) (xl) < 0) ? (((s16) (dsdx) < 0) ? (MAX((((s16) (xl) * (s16) (dsdx)) >> 7), 0)) \
4087 : (MIN((((s16) (xl) * (s16) (dsdx)) >> 7), 0))) \
4088 : 0)), \
4089 16, 16) | \
4090 _SHIFTL(((t) - (((yl) < 0) ? (((s16) (dtdy) < 0) ? (MAX((((s16) (yl) * (s16) (dtdy)) >> 7), 0)) \
4091 : (MIN((((s16) (yl) * (s16) (dtdy)) >> 7), 0))) \
4092 : 0)), \
4093 0, 16))); \
4094 gImmp1(pkt, G_RDPHALF_CONT, (_SHIFTL((dsdx), 16, 16) | _SHIFTL((dtdy), 0, 16))); \
4095 }
4096
4097#define gsSPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4098 { { (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)), \
4099 (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)) } }, \
4100 gsImmp1(G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \
4101 gsImmp1(G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)))
4102
4103#define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4104 { \
4105 Gfx* _g = (Gfx*) (pkt); \
4106 \
4107 _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)); \
4108 _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)); \
4109 gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \
4110 gImmp1(pkt, G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \
4111 }
4112#else
4113#define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4114 { \
4115 Gfx* _g = (Gfx*) (pkt); \
4116 \
4117 _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)); \
4118 _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)); \
4119 gImmp1(pkt, G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \
4120 gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \
4121 }
4122
4123#define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4124 { { (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)), \
4125 (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)) } }, \
4126 gsImmp1(G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \
4127 gsImmp1(G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)))
4128
4129/* like gSPTextureRectangle but accepts negative position arguments */
4130#define gSPScisTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4131 { \
4132 Gfx* _g = (Gfx*) (pkt); \
4133 \
4134 _g->words.w0 = \
4135 (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(MAX((s16) (xh), 0), 12, 12) | _SHIFTL(MAX((s16) (yh), 0), 0, 12)); \
4136 _g->words.w1 = \
4137 (_SHIFTL((tile), 24, 3) | _SHIFTL(MAX((s16) (xl), 0), 12, 12) | _SHIFTL(MAX((s16) (yl), 0), 0, 12)); \
4138 gImmp1(pkt, G_RDPHALF_1, \
4139 (_SHIFTL(((s) - (((s16) (xl) < 0) ? (((s16) (dsdx) < 0) ? (MAX((((s16) (xl) * (s16) (dsdx)) >> 7), 0)) \
4140 : (MIN((((s16) (xl) * (s16) (dsdx)) >> 7), 0))) \
4141 : 0)), \
4142 16, 16) | \
4143 _SHIFTL(((t) - (((yl) < 0) ? (((s16) (dtdy) < 0) ? (MAX((((s16) (yl) * (s16) (dtdy)) >> 7), 0)) \
4144 : (MIN((((s16) (yl) * (s16) (dtdy)) >> 7), 0))) \
4145 : 0)), \
4146 0, 16))); \
4147 gImmp1(pkt, G_RDPHALF_2, (_SHIFTL((dsdx), 16, 16) | _SHIFTL((dtdy), 0, 16))); \
4148 }
4149
4150#define gsSPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4151 { { (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)), \
4152 (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)) } }, \
4153 gsImmp1(G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \
4154 gsImmp1(G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)))
4155
4156#define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
4157 { \
4158 Gfx* _g = (Gfx*) (pkt); \
4159 \
4160 _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)); \
4161 _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)); \
4162 gImmp1(pkt, G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \
4163 gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \
4164 }
4165#endif
4166
4167#define gsDPWord(wordhi, wordlo) gsImmp1(G_RDPHALF_1, (uintptr_t) (wordhi)), gsImmp1(G_RDPHALF_2, (uintptr_t) (wordlo))
4168
4169#define gDPWord(pkt, wordhi, wordlo) \
4170 { \
4171 Gfx* _g = (Gfx*) (pkt); \
4172 \
4173 gImmp1(pkt, G_RDPHALF_1, (uintptr_t) (wordhi)); \
4174 gImmp1(pkt, G_RDPHALF_2, (uintptr_t) (wordlo)); \
4175 }
4176
4177#define gDPFullSync(pkt) gDPNoParam(pkt, G_RDPFULLSYNC)
4178#define gsDPFullSync() gsDPNoParam(G_RDPFULLSYNC)
4179#define gDPTileSync(pkt) gDPNoParam(pkt, G_RDPTILESYNC)
4180#define gsDPTileSync() gsDPNoParam(G_RDPTILESYNC)
4181#define gDPPipeSync(pkt) gDPNoParam(pkt, G_RDPPIPESYNC)
4182#define gsDPPipeSync() gsDPNoParam(G_RDPPIPESYNC)
4183#define gDPLoadSync(pkt) gDPNoParam(pkt, G_RDPLOADSYNC)
4184#define gsDPLoadSync() gsDPNoParam(G_RDPLOADSYNC)
4185#define gDPNoOp(pkt) gDPNoParam(pkt, G_NOOP)
4186#define gsDPNoOp() gsDPNoParam(G_NOOP)
4187#define gDPNoOpTag(pkt, tag) gDPParam(pkt, G_NOOP, tag)
4188#define gsDPNoOpTag(tag) gsDPParam(G_NOOP, tag)
4189
4190#endif /* _LANGUAGE_C */
4191
4192#endif /* _GBI_H_ */
signed int s32
Definition ultratypes.h:15