1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution GD library
3   File:     GDGeometry.c
4 
5   Copyright 2001- 2006 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: GDGeometry.c,v $
14   Revision 1.4  2007/05/24 17:33:21  carlmu
15   Fixed ASSERT issue in GDSetVtxAttrFmtv.
16 
17   Revision 1.3  2006/02/20 04:24:39  mitu
18   Changed include path from dolphin/ to revolution/.
19 
20   Revision 1.2  2006/02/03 08:54:44  hirose
21   Avoided use of EPPC and use WIN32.
22 
23   Revision 1.1.1.1  2005/05/12 02:15:49  yasuh-to
24   Ported from dolphin source tree.
25 
26 
27     7     2002/08/05 19:53 Hirose
28     Const type specifier support.
29 
30     6     2001/10/13 2:25a Hirose
31     Added GDSetCullMode().
32 
33     5     2001/09/29 3:36p Hirose
34     Fixed emboss texgen bug.
35 
36     4     2001/09/24 3:19p Carl
37     Fixed problem with cull mode conversion.
38 
39     3     2001/09/19 6:34p Carl
40     Added GDSetLPSize.
41 
42     2     2001/09/14 6:42p Carl
43     Fixed bug with GDSetVtxAttrFmtv.
44     Made OSCachedToPhysical a macro for non-EPPC.
45 
46     1     2001/09/12 1:52p Carl
47     Initial revision of GD: Graphics Display List Library.
48 
49   $NoKeywords: $
50  *---------------------------------------------------------------------------*/
51 
52 #include <revolution/gd.h>
53 #include <revolution/os.h>
54 
55 #if defined(WIN32) && !defined(OSCachedToPhysical)
56 #define OSCachedToPhysical(caddr) ((u32)((u8*)(caddr) - (0x80000000)))
57 #endif
58 
59 /*---------------------------------------------------------------------------*/
60 
61 /*---------------------------------------------------------------------------*/
62 //  Name:         GDSetVtxDescv
63 //
64 //  Description:  Sets vertex description registers.
65 //
66 //  Arguments:    attrPtr:   pointer to an (attr, type) array.
67 //                           End of the array is indicated by GX_VA_NULL
68 //                           attribute.
69 //
70 //  Returns:      None
71 //
72 /*---------------------------------------------------------------------------*/
73 
GDSetVtxDescv(const GXVtxDescList * attrPtr)74 void GDSetVtxDescv ( const GXVtxDescList *attrPtr )
75 {
76     // These are default values for all the VCD fields.
77     // You cannot change most of these defaults without adjusting
78     // the code below as well.  The code assumes GX_NONE defaults
79     // (for normals, colors, and texture coordinates).
80 
81     u32 nnorms = 0;
82     u32 ncols  = 0;
83     u32 ntexs  = 0;
84 
85     u32 pnMtxIdx = GX_NONE;
86     u32 txMtxIdxMask = 0;
87     u32 posn = GX_DIRECT;
88     u32 norm = GX_NONE;
89     u32 col0 = GX_NONE;
90     u32 col1 = GX_NONE;
91     u32 tex0 = GX_NONE;
92     u32 tex1 = GX_NONE;
93     u32 tex2 = GX_NONE;
94     u32 tex3 = GX_NONE;
95     u32 tex4 = GX_NONE;
96     u32 tex5 = GX_NONE;
97     u32 tex6 = GX_NONE;
98     u32 tex7 = GX_NONE;
99 
100     while (attrPtr->attr != GX_VA_NULL) {
101         ASSERTMSG(((attrPtr->attr >= GX_VA_PNMTXIDX) &&
102                    (attrPtr->attr <= GX_VA_MAX_ATTR)),
103                   "GDSetVtxDescv: invalid attribute");
104 
105         ASSERTMSG(((attrPtr->type >= GX_NONE) &&
106                    (attrPtr->type <= GX_INDEX16)),
107                   "GDSetVtxDescv: invalid type");
108 
109         ASSERTMSG(((attrPtr->attr >= GX_VA_PNMTXIDX) &&
110                    (attrPtr->attr <= GX_VA_TEX7MTXIDX)) ?
111                   ((attrPtr->type == GX_NONE) ||
112                    (attrPtr->type == GX_DIRECT)) : 1,
113                   "GDSetVtxDescv: invalid type for given attribute");
114 
115         switch (attrPtr->attr) {
116 
117           case GX_VA_PNMTXIDX: pnMtxIdx = attrPtr->type; break;
118 
119           case GX_VA_TEX0MTXIDX:
120             txMtxIdxMask = (txMtxIdxMask &   ~1) | (attrPtr->type << 0); break;
121           case GX_VA_TEX1MTXIDX:
122             txMtxIdxMask = (txMtxIdxMask &   ~2) | (attrPtr->type << 1); break;
123           case GX_VA_TEX2MTXIDX:
124             txMtxIdxMask = (txMtxIdxMask &   ~4) | (attrPtr->type << 2); break;
125           case GX_VA_TEX3MTXIDX:
126             txMtxIdxMask = (txMtxIdxMask &   ~8) | (attrPtr->type << 3); break;
127           case GX_VA_TEX4MTXIDX:
128             txMtxIdxMask = (txMtxIdxMask &  ~16) | (attrPtr->type << 4); break;
129           case GX_VA_TEX5MTXIDX:
130             txMtxIdxMask = (txMtxIdxMask &  ~32) | (attrPtr->type << 5); break;
131           case GX_VA_TEX6MTXIDX:
132             txMtxIdxMask = (txMtxIdxMask &  ~64) | (attrPtr->type << 6); break;
133           case GX_VA_TEX7MTXIDX:
134             txMtxIdxMask = (txMtxIdxMask & ~128) | (attrPtr->type << 7); break;
135 
136           case GX_VA_POS: posn = attrPtr->type; break;
137 
138           case GX_VA_NRM:
139             if (attrPtr->type != GX_NONE)
140                 { norm = attrPtr->type; nnorms = 1; }
141             break;
142           case GX_VA_NBT:
143             if (attrPtr->type != GX_NONE)
144                 { norm = attrPtr->type; nnorms = 2; }
145             break;
146 
147           case GX_VA_CLR0: col0=attrPtr->type; ncols+=(col0 != GX_NONE); break;
148           case GX_VA_CLR1: col1=attrPtr->type; ncols+=(col1 != GX_NONE); break;
149 
150           case GX_VA_TEX0: tex0=attrPtr->type; ntexs+=(tex0 != GX_NONE); break;
151           case GX_VA_TEX1: tex1=attrPtr->type; ntexs+=(tex1 != GX_NONE); break;
152           case GX_VA_TEX2: tex2=attrPtr->type; ntexs+=(tex2 != GX_NONE); break;
153           case GX_VA_TEX3: tex3=attrPtr->type; ntexs+=(tex3 != GX_NONE); break;
154           case GX_VA_TEX4: tex4=attrPtr->type; ntexs+=(tex4 != GX_NONE); break;
155           case GX_VA_TEX5: tex5=attrPtr->type; ntexs+=(tex5 != GX_NONE); break;
156           case GX_VA_TEX6: tex6=attrPtr->type; ntexs+=(tex6 != GX_NONE); break;
157           case GX_VA_TEX7: tex7=attrPtr->type; ntexs+=(tex7 != GX_NONE); break;
158           default: break;
159         }
160         attrPtr++;
161     }
162 
163     GDWriteCPCmd( CP_VCD_LO_ID, CP_VCD_REG_LO_PS( pnMtxIdx, txMtxIdxMask,
164                                                   posn, norm, col0, col1 ));
165 
166     GDWriteCPCmd( CP_VCD_HI_ID, CP_VCD_REG_HI( tex0, tex1, tex2, tex3,
167                                                tex4, tex5, tex6, tex7 ));
168 
169     GDWriteXFCmd( XF_INVTXSPEC_ID, XF_INVTXSPEC( ncols, nnorms, ntexs ));
170 }
171 
172 /*---------------------------------------------------------------------------*/
173 //  Name:         GDSetVtxAttrFmt
174 //
175 //  Description:  Sets format of a given attribute in the vertex format array.
176 //
177 //  Arguments:    vtxFmt:	Name of the format array register.
178 //                list:      	pointer to an array of attribute format structures.
179 //
180 //  list structure elements:
181 //                attr:      	Name of the attribute.
182 //                cnt:       	Number of components for the attribute.
183 //                type:      	Data type of the attribute.
184 //                frac:      	number of fraction bits for int data types.
185 //
186 //  Returns:      None
187 //
188 /*---------------------------------------------------------------------------*/
189 
GDSetVtxAttrFmtv(GXVtxFmt vtxfmt,const GXVtxAttrFmtList * list)190 void GDSetVtxAttrFmtv ( GXVtxFmt vtxfmt, const GXVtxAttrFmtList *list )
191 {
192     // These are default values for all the VAT fields.
193     // You may change them as you wish.
194 
195     u32 posCnt  = GX_POS_XYZ;
196     u32 posType = GX_F32;
197     u32 posFrac = 0;
198 
199     u32 nrmCnt  = GX_NRM_XYZ;
200     u32 nrmType = GX_F32;
201     u32 nrmIdx3 = 0;
202 
203     u32 c0Cnt   = GX_CLR_RGBA;
204     u32 c0Type  = GX_RGBA8;
205     u32 c1Cnt   = GX_CLR_RGBA;
206     u32 c1Type  = GX_RGBA8;
207 
208     u32 tx0Cnt  = GX_TEX_ST;
209     u32 tx0Type = GX_F32;
210     u32 tx0Frac = 0;
211     u32 tx1Cnt  = GX_TEX_ST;
212     u32 tx1Type = GX_F32;
213     u32 tx1Frac = 0;
214     u32 tx2Cnt  = GX_TEX_ST;
215     u32 tx2Type = GX_F32;
216     u32 tx2Frac = 0;
217     u32 tx3Cnt  = GX_TEX_ST;
218     u32 tx3Type = GX_F32;
219     u32 tx3Frac = 0;
220     u32 tx4Cnt  = GX_TEX_ST;
221     u32 tx4Type = GX_F32;
222     u32 tx4Frac = 0;
223     u32 tx5Cnt  = GX_TEX_ST;
224     u32 tx5Type = GX_F32;
225     u32 tx5Frac = 0;
226     u32 tx6Cnt  = GX_TEX_ST;
227     u32 tx6Type = GX_F32;
228     u32 tx6Frac = 0;
229     u32 tx7Cnt  = GX_TEX_ST;
230     u32 tx7Type = GX_F32;
231     u32 tx7Frac = 0;
232 
233     ASSERTMSG((vtxfmt < GX_MAX_VTXFMT), "GDSetVtxAttrFmtv: invalid vtx fmt");
234 
235     while (list->attr != GX_VA_NULL) {
236         ASSERTMSG((((list->attr >= GX_VA_POS) &&
237                    (list->attr <= GX_VA_TEX7)) ||
238                    (list->attr == GX_VA_NBT)),
239                    "GDSetVtxAttrFmtv: invalid attribute");
240         ASSERTMSG((list->frac < 32), "GDSetVtxAttrFmtv: invalid frac value");
241 
242         switch (list->attr) {
243           case GX_VA_POS:
244             posCnt  = list->cnt;
245             posType = list->type;
246             posFrac = list->frac;
247             break;
248           case GX_VA_NRM:
249           case GX_VA_NBT:
250             nrmType = list->type;
251             if (list->cnt == GX_NRM_NBT3)
252             {
253                 nrmCnt = GX_NRM_NBT;
254                 nrmIdx3 = 1;
255             } else {
256                 nrmCnt = list->cnt;
257                 nrmIdx3 = 0;
258             }
259             break;
260           case GX_VA_CLR0:
261             c0Cnt  = list->cnt;
262             c0Type = list->type;
263             break;
264           case GX_VA_CLR1:
265             c1Cnt  = list->cnt;
266             c1Type = list->type;
267             break;
268           case GX_VA_TEX0:
269             tx0Cnt  = list->cnt;
270             tx0Type = list->type;
271             tx0Frac = list->frac;
272             break;
273           case GX_VA_TEX1:
274             tx1Cnt  = list->cnt;
275             tx1Type = list->type;
276             tx1Frac = list->frac;
277             break;
278           case GX_VA_TEX2:
279             tx2Cnt  = list->cnt;
280             tx2Type = list->type;
281             tx2Frac = list->frac;
282             break;
283           case GX_VA_TEX3:
284             tx3Cnt  = list->cnt;
285             tx3Type = list->type;
286             tx3Frac = list->frac;
287             break;
288           case GX_VA_TEX4:
289             tx4Cnt  = list->cnt;
290             tx4Type = list->type;
291             tx4Frac = list->frac;
292             break;
293           case GX_VA_TEX5:
294             tx5Cnt  = list->cnt;
295             tx5Type = list->type;
296             tx5Frac = list->frac;
297             break;
298           case GX_VA_TEX6:
299             tx6Cnt  = list->cnt;
300             tx6Type = list->type;
301             tx6Frac = list->frac;
302             break;
303           case GX_VA_TEX7:
304             tx7Cnt  = list->cnt;
305             tx7Type = list->type;
306             tx7Frac = list->frac;
307             break;
308           default:
309             break;
310         }
311         list++;
312     }
313 
314     GDWriteCPCmd( (u8)(CP_VAT_A_ID + vtxfmt),
315                   CP_VAT_REG_A(posCnt, posType, posFrac,
316                                nrmCnt, nrmType,
317                                c0Cnt,  c0Type, c1Cnt, c1Type,
318                                tx0Cnt, tx0Type, tx0Frac,
319                                nrmIdx3 ));
320 
321     GDWriteCPCmd( (u8)(CP_VAT_B_ID + vtxfmt),
322                   CP_VAT_REG_B(tx1Cnt, tx1Type, tx1Frac,
323                                tx2Cnt, tx2Type, tx2Frac,
324                                tx3Cnt, tx3Type, tx3Frac,
325                                tx4Cnt, tx4Type ));
326 
327     GDWriteCPCmd( (u8)(CP_VAT_C_ID + vtxfmt),
328                   CP_VAT_REG_C(tx4Frac,
329                                tx5Cnt, tx5Type, tx5Frac,
330                                tx6Cnt, tx6Type, tx6Frac,
331                                tx7Cnt, tx7Type, tx7Frac ));
332 }
333 
334 /*---------------------------------------------------------------------------*/
335 //  Name:         GDSetArray
336 //
337 //  Description:  Sets the base address and stride of data array for the given
338 //                attribute. This will be used by indexed vertex data.
339 //                The base address should be an EPPC cached memory address.
340 //
341 //  Arguments:    attr:        	Name of the attribute.
342 //                base_ptr:    	pointer to an array of data in cached memory.
343 //                stride:      	number of bytes between each attribute unit.
344 //
345 //  Returns:      None
346 //
347 /*---------------------------------------------------------------------------*/
348 
GDSetArray(GXAttr attr,const void * base_ptr,u8 stride)349 void GDSetArray ( GXAttr attr, const void *base_ptr, u8 stride )
350 {
351     s32 cpAttr;
352 
353     cpAttr = (attr == GX_VA_NBT) ? (GX_VA_NRM - GX_VA_POS) : (attr - GX_VA_POS);
354 
355     GDWriteCPCmd( (u8) (CP_ARRAY_BASE_ID + cpAttr),
356                   CP_ARRAY_BASE_REG( OSCachedToPhysical( base_ptr ) ));
357 
358     GDWriteCPCmd( (u8) (CP_ARRAY_STRIDE_ID + cpAttr),
359                   CP_ARRAY_STRIDE_REG( stride ));
360 }
361 
362 /*---------------------------------------------------------------------------*/
363 //  Name:         GDSetArrayRaw
364 //
365 //  Description:  Sets the base address and stride of data array for the given
366 //                attribute. This will be used by indexed vertex data.
367 //                The base address is just a raw u32 number in this case.
368 //
369 //  Arguments:    attr:	          Name of the attribute.
370 //                base_ptr_raw:	  raw number to be inserted for base address.
371 //                stride:         number of bytes between each attribute unit.
372 //
373 //  Returns:      None
374 //
375 /*---------------------------------------------------------------------------*/
376 
GDSetArrayRaw(GXAttr attr,u32 base_ptr_raw,u8 stride)377 void GDSetArrayRaw ( GXAttr attr, u32 base_ptr_raw, u8 stride )
378 {
379     s32 cpAttr;
380 
381     cpAttr = (attr == GX_VA_NBT) ? (GX_VA_NRM - GX_VA_POS) : (attr - GX_VA_POS);
382 
383     GDWriteCPCmd( (u8) (CP_ARRAY_BASE_ID + cpAttr),
384                   CP_ARRAY_BASE_REG( base_ptr_raw ));
385 
386     GDWriteCPCmd( (u8) (CP_ARRAY_STRIDE_ID + cpAttr),
387                   CP_ARRAY_STRIDE_REG( stride ));
388 }
389 
390 /*---------------------------------------------------------------------------*/
391 //  Name:         GDPatchArrayPtr
392 //
393 //  Description:  Alters array base memory address for a GDSetArray command.
394 //                We assume that the DL offset has been moved to the point
395 //                CP_DATA_OFFSET bytes after where the GDSetArray command
396 //                was inserted.  Only the array base address is changed.
397 //
398 //  Arguments:    base_ptr:    		pointer to an array of data in cached memory.
399 //
400 //  Returns:      None
401 //
402 /*---------------------------------------------------------------------------*/
403 
GDPatchArrayPtr(const void * base_ptr)404 void GDPatchArrayPtr ( const void *base_ptr )
405 {
406     GDWrite_u32(CP_ARRAY_BASE_REG( OSCachedToPhysical( base_ptr ) ));
407 }
408 
409 /*---------------------------------------------------------------------------*/
410 //  Name:         GDSetTexCoordGen
411 //
412 //  Description:  Sets the texture coordinate control state in XF block.
413 //
414 //  Arguments:    dst_coord:   	Texture Coordinate Name.
415 //                func:        	Texture Generation Function.
416 //                src_param:   	Texture Generation Source coordinates.
417 //                mtx:         	Default texture matrix index.
418 //                normalize:   	Normalize results between transforms?
419 //                pt_texmtx:   	Post-transform matrix index.
420 //
421 //  Returns:      None
422 //
423 /*---------------------------------------------------------------------------*/
424 
GDSetTexCoordGen(GXTexCoordID dst_coord,GXTexGenType func,GXTexGenSrc src_param,GXBool normalize,u32 postmtx)425 void GDSetTexCoordGen ( GXTexCoordID  dst_coord,
426                         GXTexGenType  func,
427                         GXTexGenSrc   src_param,
428                         GXBool        normalize,
429                         u32           postmtx )
430 {
431     u32     form;
432     u32     tgType;
433     u32     proj;
434     u32     row;
435     u32     embossRow;
436     u32     embossLit;
437 
438     form      = XF_TEX_AB11;
439     proj      = XF_TEX_ST;
440     row       = XF_TEX0_INROW;
441     embossRow = XF_TEX0_INROW;
442     embossLit = 0;
443 
444     ASSERTMSG((dst_coord < GX_MAX_TEXCOORD),
445               "GDSetTexCoordGen: invalid texcoord ID");
446 
447     switch (src_param) {
448       case GX_TG_POS:     row = XF_GEOM_INROW;       form = XF_TEX_ABC1; break;
449       case GX_TG_NRM:     row = XF_NORMAL_INROW;     form = XF_TEX_ABC1; break;
450       case GX_TG_BINRM:   row = XF_BINORMAL_T_INROW; form = XF_TEX_ABC1; break;
451       case GX_TG_TANGENT: row = XF_BINORMAL_B_INROW; form = XF_TEX_ABC1; break;
452       case GX_TG_COLOR0:  row = XF_COLORS_INROW; break;
453       case GX_TG_COLOR1:  row = XF_COLORS_INROW; break;
454       case GX_TG_TEX0:    row = XF_TEX0_INROW;   break;
455       case GX_TG_TEX1:    row = XF_TEX1_INROW;   break;
456       case GX_TG_TEX2:    row = XF_TEX2_INROW;   break;
457       case GX_TG_TEX3:    row = XF_TEX3_INROW;   break;
458       case GX_TG_TEX4:    row = XF_TEX4_INROW;   break;
459       case GX_TG_TEX5:    row = XF_TEX5_INROW;   break;
460       case GX_TG_TEX6:    row = XF_TEX6_INROW;   break;
461       case GX_TG_TEX7:    row = XF_TEX7_INROW;   break;
462       case GX_TG_TEXCOORD0: embossRow = 0; break;
463       case GX_TG_TEXCOORD1: embossRow = 1; break;
464       case GX_TG_TEXCOORD2: embossRow = 2; break;
465       case GX_TG_TEXCOORD3: embossRow = 3; break;
466       case GX_TG_TEXCOORD4: embossRow = 4; break;
467       case GX_TG_TEXCOORD5: embossRow = 5; break;
468       case GX_TG_TEXCOORD6: embossRow = 6; break;
469       default:
470         ASSERTMSG(0, "GDSetTexCoordGen: invalid texgen source");
471         break;
472     }
473 
474     switch (func) {
475       case GX_TG_MTX2x4:
476         tgType = XF_TEXGEN_REGULAR;
477         break;
478 
479       case GX_TG_MTX3x4:
480         tgType = XF_TEXGEN_REGULAR;
481         proj   = XF_TEX_STQ;
482         break;
483 
484       case GX_TG_BUMP0:
485       case GX_TG_BUMP1:
486       case GX_TG_BUMP2:
487       case GX_TG_BUMP3:
488       case GX_TG_BUMP4:
489       case GX_TG_BUMP5:
490       case GX_TG_BUMP6:
491       case GX_TG_BUMP7:
492         ASSERTMSG((src_param >= GX_TG_TEXCOORD0) &&
493                   (src_param <= GX_TG_TEXCOORD6),
494                   "GDSetTexCoordGen: invalid emboss source");
495         tgType = XF_TEXGEN_EMBOSS_MAP;
496         embossLit = (u32) (func - GX_TG_BUMP0);
497         break;
498 
499       case GX_TG_SRTG:
500         if (src_param == GX_TG_COLOR0) {
501             tgType = XF_TEXGEN_COLOR_STRGBC0;
502         } else {
503             tgType = XF_TEXGEN_COLOR_STRGBC1;
504         }
505         break;
506 
507       default:
508         ASSERTMSG(0, "GDSetTexCoordGen: invalid texgen function");
509         break;
510     }
511 
512     GDWriteXFCmd( (u16) (XF_TEX0_ID + dst_coord),
513                   XF_TEX( proj, form, tgType, row,
514                           embossRow, embossLit ));
515 
516     //---------------------------------------------------------------------
517     // Update DUALTEX state
518     //---------------------------------------------------------------------
519 
520     GDWriteXFCmd( (u16) (XF_DUALTEX0_ID + dst_coord), XF_DUALTEX(
521         (postmtx - GX_PTTEXMTX0), normalize ));
522 }
523 
524 /*---------------------------------------------------------------------------*/
525 //  Name:         GDSetCullMode
526 //
527 //  Description:  Sets front/back face culling mode. The register mask
528 //                is used to changing anything other than cull mode.
529 //                Note: The HW's notion of frontface is opposite of the
530 //                api's notion of front face so we need to translate the
531 //                enums.
532 //
533 //  Arguments:    mode:          cull mode.
534 //
535 //  Returns:      None
536 //
537 /*---------------------------------------------------------------------------*/
538 
539 #define GEN_MODE_MASK_SETCULLMODE \
540     ( 0x000003 << GEN_MODE_REJECT_EN_SHIFT )
541 
GDSetCullMode(GXCullMode mode)542 void GDSetCullMode( GXCullMode mode )
543 {
544     static u8 cm2hw[] = { 0, 2, 1, 3 };
545 
546     GDWriteBPCmd( SS_MASK( GEN_MODE_MASK_SETCULLMODE ));
547 
548     GDWriteBPCmd( GEN_MODE( 0, 0, 0, 0, cm2hw[mode], 0, 0, GEN_MODE_ID ));
549 }
550 
551 /*---------------------------------------------------------------------------*/
552 //  Name:         GDSetGenMode
553 //
554 //  Description:  Sets the gen mode register for the raster pipe.
555 //                The register mask is used to prevent changing the cull mode,
556 //                the coplanar bit, AA mode, or number of indirect stages.
557 //
558 //  Arguments:    nTexGens:    Number of texgens.
559 //                nChans:      Number of active lighting channels.
560 //                nTevs:       Number of active TEV stages.
561 //
562 //  Returns:      None
563 //
564 /*---------------------------------------------------------------------------*/
565 
566 #define GEN_MODE_MASK_SETGENMODE \
567     (( 0x00000F << GEN_MODE_NTEX_SHIFT ) | \
568      ( 0x000003 << GEN_MODE_NCOL_SHIFT ) | \
569      ( 0x00000F << GEN_MODE_NTEV_SHIFT ))
570 
571 
GDSetGenMode(u8 nTexGens,u8 nChans,u8 nTevs)572 void GDSetGenMode( u8 nTexGens, u8 nChans, u8 nTevs )
573 {
574     GDWriteBPCmd( SS_MASK( GEN_MODE_MASK_SETGENMODE ));
575 
576     GDWriteBPCmd( GEN_MODE( nTexGens, nChans, 0, (nTevs-1),
577                             0, 0, 0, GEN_MODE_ID ));
578 
579     GDWriteXFCmd( XF_NUMCOLORS_ID, XF_NUMCOLORS( nChans ));
580     GDWriteXFCmd( XF_NUMTEX_ID, XF_NUMTEX( nTexGens ));
581 }
582 
583 /*---------------------------------------------------------------------------*/
584 //  Name:         GDSetGenMode2
585 //
586 //  Description:  Sets the gen mode register for the raster pipe.
587 //                Also lets you specify the culling mode.  The mask is used
588 //                to prevent changing the coplanar bit or AA mode.
589 //
590 //  NOTE:         The indirect mask is not dealt with!  If you change the
591 //                number of indirect stages, you'd better also set the
592 //                indirect mask as appropriate.
593 //
594 //  Arguments:    nTexGens:    Number of texgens.
595 //                nChans:      Number of active lighting channels.
596 //                nTev:        Number of active TEV stages.
597 //                nInds:       Number of active indirect texture stages.
598 //                cm:          Front/back-face culling mode.
599 //
600 //  Returns:      None
601 //
602 /*---------------------------------------------------------------------------*/
603 
604 #define GEN_MODE_MASK_SETGENMODE2 \
605     (( 0x00000F << GEN_MODE_NTEX_SHIFT )      | \
606      ( 0x000003 << GEN_MODE_NCOL_SHIFT )      | \
607      ( 0x00000F << GEN_MODE_NTEV_SHIFT )      | \
608      ( 0x000003 << GEN_MODE_REJECT_EN_SHIFT ) | \
609      ( 0x000007 << GEN_MODE_NBMP_SHIFT ))
610 
611 
GDSetGenMode2(u8 nTexGens,u8 nChans,u8 nTevs,u8 nInds,GXCullMode cm)612 void GDSetGenMode2( u8 nTexGens, u8 nChans, u8 nTevs, u8 nInds, GXCullMode cm )
613 {
614     static u8 cm2hw[] = { 0, 2, 1, 3 };
615 
616     GDWriteBPCmd( SS_MASK( GEN_MODE_MASK_SETGENMODE2 ));
617 
618     GDWriteBPCmd( GEN_MODE( nTexGens, nChans, 0, (nTevs-1),
619                             cm2hw[cm], nInds, 0, GEN_MODE_ID ));
620 
621     GDWriteXFCmd( XF_NUMCOLORS_ID, XF_NUMCOLORS( nChans ));
622     GDWriteXFCmd( XF_NUMTEX_ID, XF_NUMTEX( nTexGens ));
623 }
624 
625 /*---------------------------------------------------------------------------*/
626 //  Name:         GDSetLPSize
627 //
628 //  Description:  Sets the line width & texture offset, point size &
629 //                texture offset, and line aspect ratio.
630 //
631 //  Arguments:    lineWidth:        	line width, in 1/6's
632 //                pointSize:        	point size, in 1/6's
633 //                lineOffset:       	line texture offset
634 //                pointOffset:      	point texture offset
635 //                lineHalfAspect:   	TRUE for drawing lines in field mode
636 //                                      FALSE for drawing lines in frame mode
637 //
638 //  Returns:      None
639 //
640 /*---------------------------------------------------------------------------*/
641 
GDSetLPSize(u8 lineWidth,u8 pointSize,GXTexOffset lineOffset,GXTexOffset pointOffset,GXBool lineHalfAspect)642 void GDSetLPSize( u8 lineWidth, u8 pointSize,
643                   GXTexOffset lineOffset, GXTexOffset pointOffset,
644                   GXBool lineHalfAspect )
645 {
646     GDWriteBPCmd( SU_LPSIZE( lineWidth, pointSize,
647                              lineOffset, pointOffset,
648                              lineHalfAspect, SU_LPSIZE_ID ));
649 }
650 
651 /*---------------------------------------------------------------------------*/
652 //  Name:         GDSetCoPlanar
653 //
654 //  Description:  Sets the coplanar mode within the gen mode register.
655 //                This freezes the Z slopes of the last triangle sent.
656 //                All subsequent triangles will use the same Z slopes,
657 //                meaning that they will be coplanar.  The register mask
658 //                is used to set only this bit within gen mode.
659 //
660 //  Arguments:    enable:      GX_TRUE to enable coplanar mode
661 //
662 //  Returns:      None
663 //
664 /*---------------------------------------------------------------------------*/
665 
666 #define GEN_MODE_MASK_SETCOPLANAR \
667     ( 0x000001 << GEN_MODE_ZFREEZE_SHIFT )
668 
GDSetCoPlanar(GXBool enable)669 void GDSetCoPlanar( GXBool enable )
670 {
671     GDWriteBPCmd( SS_MASK( GEN_MODE_MASK_SETCOPLANAR ));
672 
673     GDWriteBPCmd( GEN_MODE( 0, 0, 0, 0, 0, 0, enable, GEN_MODE_ID ));
674 }
675