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