1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin
3   File:     gd-init-create.c
4 
5   Copyright 2001 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: gd-init-create.c,v $
14   Revision 1.2  02/20/2006 04:13:09  mitu
15   changed include path from dolphin/ to revolution/.
16 
17   Revision 1.1  02/08/2006 11:19:43  mitu
18   1st version.
19 
20 
21     1     9/25/01 6:23p Carl
22     Sources for GD init demo.
23 
24   $NoKeywords: $
25  *---------------------------------------------------------------------------*/
26 
27 #include <revolution/gd.h>
28 #include <revolution/mtx/GeoTypes.h>
29 
30 #ifdef WIN32
31 #include <assert.h>
32 #include <stdlib.h>
33 #else
34 #include <revolution/os.h>
35 #endif
36 
37 /*---------------------------------------------------------------------------*/
38 
39 #ifdef WIN32
40 #define ASSERT           assert
41 #define OSRoundUp32B(x)  (((u32)(x) + 31) & ~31)
42 #define OSAlloc(x)       ((void*)OSRoundUp32B(malloc((x)+31)))
43 #define OSFree(x)        free(x)
44 #endif
45 
46 /*---------------------------------------------------------------------------*
47    Forward references
48  *---------------------------------------------------------------------------*/
49 
50 void CreateDLs( void );
51 
52 /*---------------------------------------------------------------------------*
53    Global variables
54  *---------------------------------------------------------------------------*/
55 
56 // Display lists *************************************************************
57 
58 // This DL is used with the "Draw" display list.
59 // It initializes state that will be used by the Draw DL.
60 
61 extern GDLObj InitDLO;
62 #define INIT_STATE_SIZE 2048  // maximum (not actual) size
63 
64 // This DL draws a cube.
65 
66 extern GDLObj DrawDLO;
67 #define DRAW_SIZE 2048        // maximum (not actual) size
68 
69 // This array indicates the offsets to patch memory addresses for the
70 // primitive data arrays (positions, colors) referred to in the Init DL.
71 
72 extern u32 *setArrayOffsets;
73 
74 /*---------------------------------------------------------------------------*
75    Functions
76  *---------------------------------------------------------------------------*/
77 
78 /*---------------------------------------------------------------------------*
79     Name:           CreateDLs
80 
81     Description:    Creates the display lists used by the program.
82 
83     Arguments:      none
84 
85     Returns:        none
86  *---------------------------------------------------------------------------*/
CreateDLs(void)87 void CreateDLs ( void )
88 {
89     u8 *InitStateList;
90     u8 *DrawList;
91 
92     f32 identity_mtx[3][4];
93     GXColor black = {0, 0, 0, 0};
94     GXColor white = {255, 255, 255, 255};
95     u32 i;
96 
97     //
98     // Create the init-state DL
99     //
100 
101     // This display list (for the most part) follows the settings of GXInit.
102     // Whatever GXInit does (regarding GX API initialization), this DL also
103     // does (wherever possible).
104     //
105     // We also set up a few things in order to draw a cube in the draw DL.
106 
107     InitStateList = OSAlloc( INIT_STATE_SIZE );
108     ASSERT(InitStateList);
109 
110     setArrayOffsets = OSAlloc( 2 * sizeof(u32) );
111     ASSERT(setArrayOffsets);
112 
113     GDInitGDLObj( &InitDLO, InitStateList, INIT_STATE_SIZE );
114     GDSetCurrent( &InitDLO );
115 
116     // ----------------------------------------------------------------------
117 
118     // Here we follow GXInit, section by section.
119     // The comments not in parenthesis are from the original GXInit code.
120 
121     //
122     //  Geometry and Vertex
123     //
124 
125     GDSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0,
126                      GX_FALSE, GX_PTIDENTITY);
127     GDSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1,
128                      GX_FALSE, GX_PTIDENTITY);
129     GDSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2,
130                      GX_FALSE, GX_PTIDENTITY);
131     GDSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3,
132                      GX_FALSE, GX_PTIDENTITY);
133     GDSetTexCoordGen(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4,
134                      GX_FALSE, GX_PTIDENTITY);
135     GDSetTexCoordGen(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5,
136                      GX_FALSE, GX_PTIDENTITY);
137     GDSetTexCoordGen(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6,
138                      GX_FALSE, GX_PTIDENTITY);
139     GDSetTexCoordGen(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7,
140                      GX_FALSE, GX_PTIDENTITY);
141     // (GDSetGenMode2: nTexgens, nChannels, nTevs, nIndirects, cullmode)
142     GDSetGenMode2(1, 0, 1, 0, GX_CULL_BACK);
143 
144     // (GXInit just clears the VCD and does not touch the VATs.
145     //  That is not so useful, so here as an example we set the
146     //  VCD and VAT 0 as required by this demo.)
147     {
148         static GXVtxDescList vcd[] = {
149             { GX_VA_POS, GX_INDEX8 },
150             { GX_VA_CLR0, GX_INDEX8 },
151             { GX_VA_NULL, GX_NONE }, // NULL terminator is required
152         };
153         static GXVtxAttrFmtList vat[] = {
154             { GX_VA_POS, GX_POS_XYZ, GX_F32, 0 },
155             { GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 },
156             { GX_VA_NULL, GX_POS_XY, GX_U8, 0 }, // NULL terminator is required
157         };
158 
159         GDSetVtxDescv( vcd );
160         GDSetVtxAttrFmtv( GX_VTXFMT0, vat );
161     }
162 
163     // (Vertex cache invalidation is not part of GD.)
164 
165     // (For the line-aspect ratio, GXInit looks at the render mode in
166     //  order to set this properly.  We assume frame-rendering mode here.)
167     GDSetLPSize(6, 6, GX_TO_ZERO, GX_TO_ZERO, GX_DISABLE);
168 
169     // (Line/point texture-offset enables are set with texcoord scaling.)
170     // (As an example, we show how to set one here; we do not set all 8.)
171     GDSetTexCoordScaleAndTOEs( GX_TEXCOORD0,             // tcoord
172                                128, GX_FALSE, GX_FALSE,  // s size, bias, wrap
173                                128, GX_FALSE, GX_FALSE,  // t size, bias, wrap
174                                GX_DISABLE, GX_DISABLE ); // tex-offset enables
175 
176     //
177     //  Transformation and Matrix
178     //
179 
180     identity_mtx[0][0] = 1.0f; identity_mtx[0][1] = 0.0f;
181     identity_mtx[0][2] = 0.0f; identity_mtx[0][3] = 0.0f;
182     identity_mtx[1][0] = 0.0f; identity_mtx[1][1] = 1.0f;
183     identity_mtx[1][2] = 0.0f; identity_mtx[1][3] = 0.0f;
184     identity_mtx[2][0] = 0.0f; identity_mtx[2][1] = 0.0f;
185     identity_mtx[2][2] = 1.0f; identity_mtx[2][3] = 0.0f;
186 
187     // (Setting projection matrix is not part of GXInit or GD.)
188     GDLoadPosMtxImm(identity_mtx, GX_PNMTX0);
189     GDLoadNrmMtxImm(identity_mtx, GX_PNMTX0);
190     GDSetCurrentMtx(GX_PNMTX0,
191                     GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY,
192                     GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY);
193     GDLoadTexMtxImm(identity_mtx, GX_IDENTITY, GX_MTX3x4);
194     GDLoadTexMtxImm(identity_mtx, GX_PTIDENTITY, GX_MTX3x4);
195     // (Setting viewport is not part of GD.)
196 
197     //
198     //  Clipping and Culling
199     //
200 
201     GDSetCoPlanar(GX_DISABLE);
202     // (Setting clip mode is not part of GD.)
203     // (Setting scissoring is not part of GD.)
204 
205     //
206     //  Lighting - pass vertex color through
207     //
208 
209     GDSetChanCtrl(
210         GX_COLOR0A0,
211         GX_DISABLE,
212         GX_SRC_REG,
213         GX_SRC_VTX,
214         GX_LIGHT_NULL,
215         GX_DF_NONE,
216         GX_AF_NONE );
217 
218     GDSetChanAmbColor(GX_COLOR0A0, black);
219     GDSetChanMatColor(GX_COLOR0A0, white);
220 
221     GDSetChanCtrl(
222         GX_COLOR1A1,
223         GX_DISABLE,
224         GX_SRC_REG,
225         GX_SRC_VTX,
226         GX_LIGHT_NULL,
227         GX_DF_NONE,
228         GX_AF_NONE );
229 
230     GDSetChanAmbColor(GX_COLOR1A1, black);
231     GDSetChanMatColor(GX_COLOR1A1, white);
232 
233     //
234     //  Texture
235     //
236 
237     // (Texture cache invalidation is not part of GD.)
238 
239     //  Allocate 8 32k caches for RGBA texture mipmaps.
240     //  Equal size caches to support 32b RGBA textures.
241     //
242 
243     // (This is the default TMEM configuration set in GXInit.
244     //  Note that texmap ID's are bound to specific regions.)
245 
246     GDSetTexCached( GX_TEXMAP0, 0x00000, GX_TEXCACHE_32K,
247                                 0x80000, GX_TEXCACHE_32K );
248     GDSetTexCached( GX_TEXMAP1, 0x08000, GX_TEXCACHE_32K,
249                                 0x88000, GX_TEXCACHE_32K );
250     GDSetTexCached( GX_TEXMAP2, 0x10000, GX_TEXCACHE_32K,
251                                 0x90000, GX_TEXCACHE_32K );
252     GDSetTexCached( GX_TEXMAP3, 0x18000, GX_TEXCACHE_32K,
253                                 0x98000, GX_TEXCACHE_32K );
254     GDSetTexCached( GX_TEXMAP4, 0x20000, GX_TEXCACHE_32K,
255                                 0xa0000, GX_TEXCACHE_32K );
256     GDSetTexCached( GX_TEXMAP5, 0x28000, GX_TEXCACHE_32K,
257                                 0xa8000, GX_TEXCACHE_32K );
258     GDSetTexCached( GX_TEXMAP6, 0x30000, GX_TEXCACHE_32K,
259                                 0xb0000, GX_TEXCACHE_32K );
260     GDSetTexCached( GX_TEXMAP7, 0x38000, GX_TEXCACHE_32K,
261                                 0xb8000, GX_TEXCACHE_32K );
262 
263     //  Allocate color index caches in low bank of TMEM.
264     //  Each cache is 32kB.
265     //  Even and odd regions should be allocated on different address.
266     //
267 #if 0
268     // (This is an example of how you would rebind 4 texmap ID's
269     //  to map to the setup suggested above.)
270 
271     GDSetTexCached( GX_TEXMAP0, 0x40000, GX_TEXCACHE_32K,
272                                 0x48000, GX_TEXCACHE_32K );
273     GDSetTexCached( GX_TEXMAP1, 0x50000, GX_TEXCACHE_32K,
274                                 0x58000, GX_TEXCACHE_32K );
275     GDSetTexCached( GX_TEXMAP2, 0x60000, GX_TEXCACHE_32K,
276                                 0x68000, GX_TEXCACHE_32K );
277     GDSetTexCached( GX_TEXMAP3, 0x70000, GX_TEXCACHE_32K,
278                                 0x78000, GX_TEXCACHE_32K );
279 #endif
280 
281     //  Allocate TLUTs, 16 256-entry TLUTs and 4 1K-entry TLUTs.
282     //  256-entry TLUTs are 8kB, 1k-entry TLUTs are 32kB.
283     //
284 #if 0
285     // (This is an example of how you would bind 4 texmap ID's
286     //  to 4 256-entry RGB565 TLUT's and the other 4 texmap ID's
287     //  to 4 1K-entry RGB565 TLUT's.  The bindings are only relevant
288     //  if the texmaps are color-index format, of course.)
289 
290     GDSetTexTlut( GX_TEXMAP0, 0xc0000, GX_TL_RGB565 );
291     GDSetTexTlut( GX_TEXMAP1, 0xc2000, GX_TL_RGB565 );
292     GDSetTexTlut( GX_TEXMAP2, 0xc4000, GX_TL_RGB565 );
293     GDSetTexTlut( GX_TEXMAP3, 0xc6000, GX_TL_RGB565 );
294 
295     GDSetTexTlut( GX_TEXMAP4, 0xe0000, GX_TL_RGB565 );
296     GDSetTexTlut( GX_TEXMAP5, 0xe8000, GX_TL_RGB565 );
297     GDSetTexTlut( GX_TEXMAP6, 0xf0000, GX_TL_RGB565 );
298     GDSetTexTlut( GX_TEXMAP7, 0xf8000, GX_TL_RGB565 );
299 #endif
300 
301     //
302     //  Set texture region and tlut region Callbacks
303     //
304 
305     // (GD does not have any concept of region callbacks.
306     //  Texmap ID's are bound to regions explicitly.)
307 
308     //
309     //  Texture Environment
310     //
311     GDSetTevOrder(GX_TEVSTAGE0,
312                   GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0,
313                   GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0 );
314     GDSetTevOrder(GX_TEVSTAGE2,
315                   GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0,
316                   GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0 );
317     GDSetTevOrder(GX_TEVSTAGE4,
318                   GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0,
319                   GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0 );
320     GDSetTevOrder(GX_TEVSTAGE6,
321                   GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0,
322                   GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0 );
323 
324     GDSetTevOrder(GX_TEVSTAGE8,
325                   GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL,
326                   GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL );
327     GDSetTevOrder(GX_TEVSTAGE10,
328                   GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL,
329                   GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL );
330     GDSetTevOrder(GX_TEVSTAGE12,
331                   GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL,
332                   GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL );
333     GDSetTevOrder(GX_TEVSTAGE14,
334                   GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL,
335                   GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL );
336 
337     GDSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
338     GDSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
339     GDSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0);
340 
341     for (i = GX_TEVSTAGE0; i < GX_MAX_TEVSTAGE; i+=2) {
342         GDSetTevKonstantSel((GXTevStageID) i,
343                             GX_TEV_KCSEL_1_4, GX_TEV_KASEL_1,
344                             GX_TEV_KCSEL_1_4, GX_TEV_KASEL_1 );
345         // (Swap mode is set with TevOp.)
346     }
347     GDSetTevSwapModeTable(GX_TEV_SWAP0,
348                           GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
349     GDSetTevSwapModeTable(GX_TEV_SWAP1,
350                           GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA);
351     GDSetTevSwapModeTable(GX_TEV_SWAP2,
352                           GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA);
353     GDSetTevSwapModeTable(GX_TEV_SWAP3,
354                           GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA);
355 
356     //  Indirect Textures.
357 
358     // (Indirect texturing is not yet part of GD.)
359 
360     //
361     //  Pixel Processing
362     //
363     GDSetFog(GX_FOG_NONE, 0.0F, 1.0F, 0.1F, 1.0F, black);
364     // (Fog range adjust in not part of GD.)
365     GDSetBlendModeEtc(GX_BM_NONE,
366                       GX_BL_SRCALPHA,    // src factor
367                       GX_BL_INVSRCALPHA, // dst factor
368                       GX_LO_CLEAR,
369                       GX_ENABLE,         // color update
370                       GX_ENABLE,         // alpha update
371                       GX_ENABLE);        // dither enable
372 
373     GDSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
374     // (Z compare location is not part of GD.)
375     GDSetDstAlpha(GX_DISABLE, 0);
376     // (pixel format is not part of GD.)
377     // (field mask is not part of GD.)
378     // (field mode is not part of GD, except for line aspect ratio.)
379 
380     //
381     //  Framebuffer
382     //
383 
384     // (Framebuffer operations are not part of GD.)
385 
386     //
387     //  CPU direct EFB access
388     //
389 
390     // (This is not part of GD either.)
391 
392     //
393     //  Performance Counters
394     //
395 
396     // (Nor is this.)
397 
398     // ----------------------------------------------------------------------
399 
400     // That is all of the GXInit-related code.
401     //
402     // The rest of this DL is for the demo.
403 
404     // Set the vertex array pointers and strides.  The actual array
405     // pointers will be patched in later, so we need to keep track of
406     // these patch points.
407     // We add a bit to skip over the command token and register ID bytes.
408 
409     setArrayOffsets[0] = GDGetCurrOffset() + CP_DATA_OFFSET;
410     GDSetArrayRaw(GX_VA_POS, 0, 12);
411 
412     setArrayOffsets[1] = GDGetCurrOffset() + CP_DATA_OFFSET;
413     GDSetArrayRaw(GX_VA_CLR0, 0, 4);
414 
415     // The actual TEV/texture/color-channel configuration we need
416     // is different than what GXInit sets up, so we change it here:
417 
418     GDSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
419     GDSetGenMode(0, 1, 1); // 0 texgens, 1 channel, 1 tevstage
420 
421     // pad & flush
422     GDPadCurr32();
423     GDFlushCurrToMem(); // not strictly needed for PC-side, but not a bad idea
424 
425     //
426     // Create the cube drawing DL
427     //
428 
429     // Draw DL: commands to draw the actual geometry.
430     // Just draws a plain cube with color-indexed face colors.
431 
432     DrawList = OSAlloc( DRAW_SIZE );
433     ASSERT(DrawList);
434 
435     GDInitGDLObj( &DrawDLO, DrawList, DRAW_SIZE );
436     GDSetCurrent( &DrawDLO );
437 
438     // face 1
439 
440     GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
441     GDPosition1x8( 0 ); GDColor1x8( 0 );
442     GDPosition1x8( 1 ); GDColor1x8( 0 );
443     GDPosition1x8( 2 ); GDColor1x8( 0 );
444     GDPosition1x8( 3 ); GDColor1x8( 0 );
445     GDEnd();
446 
447     // face 2
448 
449     GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
450     GDPosition1x8( 4 ); GDColor1x8( 1 );
451     GDPosition1x8( 5 ); GDColor1x8( 1 );
452     GDPosition1x8( 6 ); GDColor1x8( 1 );
453     GDPosition1x8( 7 ); GDColor1x8( 1 );
454     GDEnd();
455 
456     // face 3
457 
458     GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
459     GDPosition1x8( 2 ); GDColor1x8( 2 );
460     GDPosition1x8( 6 ); GDColor1x8( 2 );
461     GDPosition1x8( 5 ); GDColor1x8( 2 );
462     GDPosition1x8( 3 ); GDColor1x8( 2 );
463     GDEnd();
464 
465     // face 4
466 
467     GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
468     GDPosition1x8( 1 ); GDColor1x8( 3 );
469     GDPosition1x8( 0 ); GDColor1x8( 3 );
470     GDPosition1x8( 4 ); GDColor1x8( 3 );
471     GDPosition1x8( 7 ); GDColor1x8( 3 );
472     GDEnd();
473 
474     // face 5
475 
476     GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
477     GDPosition1x8( 5 ); GDColor1x8( 4 );
478     GDPosition1x8( 4 ); GDColor1x8( 4 );
479     GDPosition1x8( 0 ); GDColor1x8( 4 );
480     GDPosition1x8( 3 ); GDColor1x8( 4 );
481     GDEnd();
482 
483     // face 6
484 
485     GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
486     GDPosition1x8( 6 ); GDColor1x8( 5 );
487     GDPosition1x8( 2 ); GDColor1x8( 5 );
488     GDPosition1x8( 1 ); GDColor1x8( 5 );
489     GDPosition1x8( 7 ); GDColor1x8( 5 );
490     GDEnd();
491 
492     // pad & flush
493     GDPadCurr32();
494     GDFlushCurrToMem(); // not strictly needed for PC-side, but not a bad idea
495 
496     GDSetCurrent(NULL); // bug-prevention
497 }
498