1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin GD library
3   File:     GDIndirect.c
4 
5   Copyright 2001- 2003 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: GDIndirect.c,v $
14   Revision 1.2  2006/02/20 04:24:39  mitu
15   Changed include path from dolphin/ to revolution/.
16 
17   Revision 1.1.1.1  2005/05/12 02:15:49  yasuh-to
18   Ported from dolphin source tree.
19 
20 
21     2     2003/02/19 17:37 Hirose
22 
23     1     2003/02/03 14:03 Hirose
24     Initial check in.
25 
26   $NoKeywords: $
27  *---------------------------------------------------------------------------*/
28 
29 #include <revolution/gd.h>
30 #include <revolution/os.h>
31 
32 /*---------------------------------------------------------------------------*/
33 
34 /*---------------------------------------------------------------------------*
35     Macros
36  *---------------------------------------------------------------------------*/
37 #define IND_TEX_MTX_EXP     10
38 #define IND_TEX_MTX_SCALE   (f32)(1 << IND_TEX_MTX_EXP)
39 #define IND_TEX_MTX_MASK    0x7ff
40 #define IND_TEX_SCALE_BIAS  0x11
41 
42 
43 /*---------------------------------------------------------------------------*/
44 //  Name:         GDSetTevIndirect
45 //
46 //  Desc:         Compile the state of an Indirect texture object in to HW
47 //                dependent values.
48 //
49 //  Arguments:    tev_stage:  	TEV stage name.
50 //                ind_stage:  	Index of the Indirect texture being bound
51 //                format:     	format of indirect texture offsets.
52 //                bias_sel:   	Bias added to the texture offsets.
53 //                matrix_sel: 	Selects texture offset matrix.
54 //                wrap_s:     	Wrap value of Direct S coordinate.
55 //                wrap_t:     	Wrap value of Direct T coordinate
56 //                add_prev:   	Add output from previous stage to texture coords.
57 //                utc_lod:    	Use the unmodified texture coordinates for LOD.
58 //                alpha_sel:  	Selects indirect texture alpha output.
59 //
60 //  Returns:      none
61 //
62 /*---------------------------------------------------------------------------*/
GDSetTevIndirect(GXTevStageID tev_stage,GXIndTexStageID ind_stage,GXIndTexFormat format,GXIndTexBiasSel bias_sel,GXIndTexMtxID matrix_sel,GXIndTexWrap wrap_s,GXIndTexWrap wrap_t,GXBool add_prev,GXBool utc_lod,GXIndTexAlphaSel alpha_sel)63 void GDSetTevIndirect (
64     GXTevStageID        tev_stage,
65     GXIndTexStageID     ind_stage,
66     GXIndTexFormat      format,
67     GXIndTexBiasSel     bias_sel,
68     GXIndTexMtxID       matrix_sel,
69     GXIndTexWrap        wrap_s,
70     GXIndTexWrap        wrap_t,
71     GXBool              add_prev,
72     GXBool              utc_lod,
73     GXIndTexAlphaSel    alpha_sel )
74 {
75     GDWriteBPCmd( IND_CMD(
76         (ind_stage & 3),
77         (format & 3),
78         (bias_sel & 7),
79         (alpha_sel & 3),
80         (matrix_sel & 0x0F),
81         (wrap_s & 7),
82         (wrap_t & 7),
83         (utc_lod & 1),
84         (add_prev & 1),
85         (IND_CMD0_ID + (tev_stage & 0x0F)) ));
86 }
87 
88 /*---------------------------------------------------------------------------*/
89 //
90 // Name:          GDSetIndTexMtx
91 //
92 // Desc:          Sets transformation matrix for indirect texture coordinates.
93 //
94 // Arguments:     MtxId:                Matrix Name.
95 //                OffsetMatrix[3][2]:   Matrix for the texture offsets.
96 //                ScaleExp:             Exponent value for scale ( scale = 2ScaleExp)
97 //
98 // Returns:       none
99 //
100 /*---------------------------------------------------------------------------*/
GDSetIndTexMtx(GXIndTexMtxID mtx_id,const f32 offset[2][3],s8 scale_exp)101 void GDSetIndTexMtx ( GXIndTexMtxID mtx_id, const f32 offset[2][3], s8 scale_exp )
102 {
103     u32     id_offset;
104 
105     switch ( mtx_id )
106     {
107       case GX_ITM_0:
108         id_offset = 0;
109         break;
110       case GX_ITM_1:
111         id_offset = 3;
112         break;
113       case GX_ITM_2:
114         id_offset = 6;
115         break;
116       default:
117         ASSERTMSG(0, "GDSetIndTexMtx: Invalid matrix id");
118         break;
119     }
120 
121     scale_exp += IND_TEX_SCALE_BIAS;
122 
123     GDWriteBPCmd( IND_MTXA(
124         (((s32)(offset[0][0] * IND_TEX_MTX_SCALE)) & IND_TEX_MTX_MASK),
125         (((s32)(offset[1][0] * IND_TEX_MTX_SCALE)) & IND_TEX_MTX_MASK),
126         (scale_exp & 0x03),
127         (IND_MTXA0_ID + id_offset) ));
128 
129     GDWriteBPCmd( IND_MTXB(
130         (((s32)(offset[0][1] * IND_TEX_MTX_SCALE)) & IND_TEX_MTX_MASK),
131         (((s32)(offset[1][1] * IND_TEX_MTX_SCALE)) & IND_TEX_MTX_MASK),
132         ((scale_exp >> 2) & 0x03),
133         (IND_MTXB0_ID + id_offset) ));
134 
135     GDWriteBPCmd( IND_MTXC(
136         (((s32)(offset[0][2] * IND_TEX_MTX_SCALE)) & IND_TEX_MTX_MASK),
137         (((s32)(offset[1][2] * IND_TEX_MTX_SCALE)) & IND_TEX_MTX_MASK),
138         ((scale_exp >> 4) & 0x03),
139         (IND_MTXC0_ID + id_offset) ));
140 }
141 
142 /*---------------------------------------------------------------------------*/
143 //
144 // Name:          GDSetIndTexScale
145 //
146 // Desc:          Sets scale value for indirect textures.
147 //
148 // Args:          indStageEven: 	Indirect stage id (must be even).
149 //                scaleS0:       	Scale value for S (even stage).
150 //                scaleT0:       	Scale value for T (even stage).
151 //                scaleS1:       	Scale value for S (odd stage).
152 //                scaleT1:       	Scale value for T (odd stage).
153 //
154 /*---------------------------------------------------------------------------*/
GDSetIndTexCoordScale(GXIndTexStageID indStageEven,GXIndTexScale scaleS0,GXIndTexScale scaleT0,GXIndTexScale scaleS1,GXIndTexScale scaleT1)155 void GDSetIndTexCoordScale (
156     GXIndTexStageID     indStageEven,
157     GXIndTexScale       scaleS0,
158     GXIndTexScale       scaleT0,
159     GXIndTexScale       scaleS1,
160     GXIndTexScale       scaleT1 )
161 {
162     GDWriteBPCmd( RAS1_SS(
163         (scaleS0 & 0x0F),
164         (scaleT0 & 0x0F),
165         (scaleS1 & 0x0F),
166         (scaleT1 & 0x0F),
167         (RAS1_SS0_ID + ((indStageEven >> 1) & 0x01)) ));
168 }
169 
170 /*---------------------------------------------------------------------------*/
171 //
172 // Name:          GDSetIndTexOrder
173 //
174 // Desc:          Associates direct texture maps and coordinate names
175 //                with indirect texture maps.
176 //
177 // Arguments:     texCoord0:    	Associated texcoord for indirect texture 0.
178 //                texMap0:      	Associated texture map for indirect texture 0.
179 //                texCoord1:    	Associated texcoord for indirect texture 1.
180 //                texMap1:      	Associated texture map for indirect texture 1.
181 //                texCoord2:    	Associated texcoord for indirect texture 2.
182 //                texMap2:      	Associated texture map for indirect texture 2.
183 //                texCoord3:    	Associated texcoord for indirect texture 3.
184 //                texMap3:      	Associated texture map for indirect texture 3.
185 //
186 /*---------------------------------------------------------------------------*/
GDSetIndTexOrder(GXTexCoordID texCoord0,GXTexMapID texMap0,GXTexCoordID texCoord1,GXTexMapID texMap1,GXTexCoordID texCoord2,GXTexMapID texMap2,GXTexCoordID texCoord3,GXTexMapID texMap3)187 void GDSetIndTexOrder (
188     GXTexCoordID        texCoord0,
189     GXTexMapID          texMap0,
190     GXTexCoordID        texCoord1,
191     GXTexMapID          texMap1,
192     GXTexCoordID        texCoord2,
193     GXTexMapID          texMap2,
194     GXTexCoordID        texCoord3,
195     GXTexMapID          texMap3 )
196 {
197     GDWriteBPCmd( RAS1_IREF(
198         (texMap0 & 7),
199         (texCoord0 & 7),
200         (texMap1 & 7),
201         (texCoord1 & 7),
202         (texMap2 & 7),
203         (texCoord2 & 7),
204         (texMap3 & 7),
205         (texCoord3 & 7),
206         RAS1_IREF_ID) );
207 }
208 
209 /*---------------------------------------------------------------------------*/
210 //
211 // Name:        GDSetTevDirect
212 //
213 // Desc:        Sets a TEV stage back to a normal, direct lookup.
214 //
215 // Arguments:   tev_stage: 	TEV stage number.
216 //
217 /*---------------------------------------------------------------------------*/
GDSetTevDirect(GXTevStageID tev_stage)218 void GDSetTevDirect ( GXTevStageID tev_stage )
219 {
220     GDSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8,
221                      GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF,
222                      GX_FALSE, GX_FALSE, GX_ITBA_OFF);
223 }
224 
225 /*---------------------------------------------------------------------------*/
226 //
227 // Name:    GDSetTevIndWarp
228 //
229 // Desc:    Used for simple indirect texture warping.
230 //
231 /*---------------------------------------------------------------------------*/
GDSetTevIndWarp(GXTevStageID tev_stage,GXIndTexStageID ind_stage,GXBool signed_offset,GXBool replace_mode,GXIndTexMtxID matrix_sel)232 void GDSetTevIndWarp ( GXTevStageID tev_stage, GXIndTexStageID ind_stage,
233                        GXBool signed_offset, GXBool replace_mode,
234                        GXIndTexMtxID matrix_sel)
235 {
236     GXIndTexWrap wrap = (replace_mode) ? GX_ITW_0 : GX_ITW_OFF;
237 
238     GDSetTevIndirect(tev_stage,         // tev stage
239                      ind_stage,         // indirect stage
240                      GX_ITF_8,          // format
241                      (signed_offset) ? GX_ITB_STU : GX_ITB_NONE, // bias
242                      matrix_sel,        // matrix select
243                      wrap,              // wrap direct S
244                      wrap,              // wrap direct T
245                      GX_FALSE,          // add prev stage output?
246                      GX_FALSE,          // use unmodified TC for LOD?
247                      GX_ITBA_OFF );     // bump alpha select
248 }
249 
250 /*---------------------------------------------------------------------------*/
251 //
252 // Name:    GXSetTevIndTile
253 //
254 // Desc:    Used for indirect texture tiling and pseudo-3D texturing.
255 //
256 /*---------------------------------------------------------------------------*/
GDSetTevIndTile(GXTevStageID tev_stage,GXIndTexStageID ind_stage,u16 tilesize_s,u16 tilesize_t,u16 tilespacing_s,u16 tilespacing_t,GXIndTexFormat format,GXIndTexMtxID matrix_sel,GXIndTexBiasSel bias_sel,GXIndTexAlphaSel alpha_sel)257 void GDSetTevIndTile ( GXTevStageID tev_stage, GXIndTexStageID ind_stage,
258                        u16 tilesize_s, u16 tilesize_t,
259                        u16 tilespacing_s, u16 tilespacing_t,
260                        GXIndTexFormat format, GXIndTexMtxID matrix_sel,
261                        GXIndTexBiasSel bias_sel, GXIndTexAlphaSel alpha_sel)
262 {
263     GXIndTexWrap        wrap_s, wrap_t;
264     f32                 mtx[2][3];
265 
266     // Compute wrap parameters from tilesize
267     switch (tilesize_s) {
268         case 256:       wrap_s = GX_ITW_256;    break;
269         case 128:       wrap_s = GX_ITW_128;    break;
270         case 64:        wrap_s = GX_ITW_64;     break;
271         case 32:        wrap_s = GX_ITW_32;     break;
272         case 16:        wrap_s = GX_ITW_16;     break;
273         default:
274             ASSERTMSG(0, "GDSetTevIndTile: Invalid tilesize for S coordinate");
275             wrap_s = GX_ITW_OFF;
276             break;
277     }
278 
279     switch (tilesize_t) {
280         case 256:       wrap_t = GX_ITW_256;    break;
281         case 128:       wrap_t = GX_ITW_128;    break;
282         case 64:        wrap_t = GX_ITW_64;     break;
283         case 32:        wrap_t = GX_ITW_32;     break;
284         case 16:        wrap_t = GX_ITW_16;     break;
285         default:
286             ASSERTMSG(0, "GDSetTevIndTile: Invalid tilesize for T coordinate");
287             wrap_t = GX_ITW_OFF;
288             break;
289     }
290 
291     // compute the matrix using tilespacing values.
292     mtx[0][0] = ((f32) tilespacing_s / IND_TEX_MTX_SCALE);
293     mtx[0][1] = mtx[0][2] = 0.0f;
294     mtx[1][1] = ((f32) tilespacing_t / IND_TEX_MTX_SCALE);
295     mtx[1][0] = mtx[1][2] = 0.0f;
296     GDSetIndTexMtx(matrix_sel, mtx, IND_TEX_MTX_EXP);
297 
298     GDSetTevIndirect(tev_stage,         // tev stage
299                      ind_stage,         // indirect stage
300                      format,            // format
301                      bias_sel,          // bias select
302                      matrix_sel,        // matrix select
303                      wrap_s,            // wrap direct S
304                      wrap_t,            // wrap direct T
305                      GX_FALSE,          // add prev stage output?
306                      GX_TRUE,           // use unmodified TC for LOD?
307                      alpha_sel);        // bump alpha select
308 }
309 
310 /*---------------------------------------------------------------------------*/
311 //
312 // Name:    GDSetTevIndBumpST
313 //
314 // Desc:    Set up TEV stages for environment-mapped bump-mapped texture
315 //          lookup.  The bump map is in ST space.
316 //
317 /*---------------------------------------------------------------------------*/
GDSetTevIndBumpST(GXTevStageID tev_stage,GXIndTexStageID ind_stage,GXIndTexMtxID matrix_sel)318 void GDSetTevIndBumpST ( GXTevStageID tev_stage, GXIndTexStageID ind_stage,
319                          GXIndTexMtxID matrix_sel )
320 {
321     GXIndTexMtxID sm, tm;
322 
323     switch(matrix_sel)
324     {
325       case GX_ITM_0:
326         sm = GX_ITM_S0;
327         tm = GX_ITM_T0;
328         break;
329       case GX_ITM_1:
330         sm = GX_ITM_S1;
331         tm = GX_ITM_T1;
332         break;
333       case GX_ITM_2:
334         sm = GX_ITM_S2;
335         tm = GX_ITM_T2;
336         break;
337       default:
338         ASSERTMSG(0, "GDSetTevIndBumpST: Invalid matrix selection");
339     }
340 
341     GDSetTevIndirect(tev_stage,         // tev stage
342                      ind_stage,         // indirect stage
343                      GX_ITF_8,          // format
344                      GX_ITB_ST,         // bias
345                      sm,                // matrix select
346                      GX_ITW_0,          // wrap direct S
347                      GX_ITW_0,          // wrap direct T
348                      GX_FALSE,          // add prev stage output?
349                      GX_FALSE,          // use unmodified TC for LOD?
350                      GX_ITBA_OFF);      // bump alpha select
351 
352     GDSetTevIndirect((GXTevStageID) (tev_stage+1),       // tev stage
353                      ind_stage,         // indirect stage
354                      GX_ITF_8,          // format
355                      GX_ITB_ST,         // bias
356                      tm,                // matrix select
357                      GX_ITW_0,          // wrap direct S
358                      GX_ITW_0,          // wrap direct T
359                      GX_TRUE,           // add prev stage output?
360                      GX_FALSE,          // use unmodified TC for LOD?
361                      GX_ITBA_OFF);      // bump alpha select
362 
363     GDSetTevIndirect((GXTevStageID) (tev_stage+2),       // tev stage
364                      ind_stage,         // indirect stage
365                      GX_ITF_8,          // format
366                      GX_ITB_NONE,       // bias
367                      GX_ITM_OFF,        // matrix select
368                      GX_ITW_OFF,        // wrap direct S
369                      GX_ITW_OFF,        // wrap direct T
370                      GX_TRUE,           // add prev stage output?
371                      GX_FALSE,          // use unmodified TC for LOD?
372                      GX_ITBA_OFF);      // bump alpha select
373 }
374 
375 /*---------------------------------------------------------------------------*/
376 //
377 // Name:    GDSetTevIndBumpXYZ
378 //
379 // Desc:    Set up TEV stages for environment-mapped bump-mapped texture
380 //          lookup.  The bump map is in 3D object space.
381 //
382 /*---------------------------------------------------------------------------*/
GDSetTevIndBumpXYZ(GXTevStageID tev_stage,GXIndTexStageID ind_stage,GXIndTexMtxID matrix_sel)383 void GDSetTevIndBumpXYZ ( GXTevStageID tev_stage, GXIndTexStageID ind_stage,
384                           GXIndTexMtxID matrix_sel )
385 {
386     GDSetTevIndirect(tev_stage,         // tev stage
387                      ind_stage,         // indirect stage
388                      GX_ITF_8,          // format
389                      GX_ITB_STU,        // bias
390                      matrix_sel,        // matrix select
391                      GX_ITW_OFF,        // wrap direct S
392                      GX_ITW_OFF,        // wrap direct T
393                      GX_FALSE,          // add prev stage output?
394                      GX_FALSE,          // use unmodified TC for LOD?
395                      GX_ITBA_OFF);      // bump alpha select
396 }
397 
398 /*---------------------------------------------------------------------------*/
399 //
400 // Name:    GDSetTevIndRepeat
401 //
402 // Desc:    Provides a texture coordinate that is the repeat of the
403 //          TC computation from the previous stage.  Intended only to
404 //          be used with GDSetTevIndBumpST().
405 //
406 /*---------------------------------------------------------------------------*/
GDSetTevIndRepeat(GXTevStageID tev_stage)407 void GDSetTevIndRepeat ( GXTevStageID tev_stage )
408 {
409     GDSetTevIndirect(tev_stage,         // tev stage
410                      GX_INDTEXSTAGE0,   // indirect stage
411                      GX_ITF_8,          // format
412                      GX_ITB_NONE,       // bias
413                      GX_ITM_OFF,        // matrix select
414                      GX_ITW_0,          // wrap direct S
415                      GX_ITW_0,          // wrap direct T
416                      GX_TRUE,           // add prev stage output?
417                      GX_FALSE,          // use unmodified TC for LOD?
418                      GX_ITBA_OFF);      // bump alpha select
419 }
420 
421 /*---------------------------------------------------------------------------*/
422 //
423 // Name:          __GDSetIndTexMask
424 //
425 // Desc:          Sets new value of imask register.
426 //                (Probably not necessary to do, though)
427 //
428 // Arguments:     mask:     	Mask parameter.
429 //
430 /*---------------------------------------------------------------------------*/
__GDSetIndTexMask(u32 mask)431 void __GDSetIndTexMask ( u32 mask )
432 {
433     GDWriteBPCmd( IND_IMASK(
434         (mask & 0x0FF),
435         IND_IMASK_ID) );
436 }
437 
438 /*---------------------------------------------------------------------------*/
439