1 /*---------------------------------------------------------------------------*
2   Project:  WD demo
3   File:     sample.c
4 
5   Copyright 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: sample.c,v $
14   Revision 1.5  2006/08/15 03:51:15  yasu
15   Support for PADDING warnings
16 
17   Revision 1.4  2006/07/18 09:25:25  terui
18   Fix appearance
19 
20   Revision 1.3  2006/07/13 13:55:09  terui
21   Adjusted the size of the heap for PAD.
22 
23   Revision 1.2  2006/07/13 12:38:32  terui
24   Fix appearance
25 
26   Revision 1.1  2006/07/13 12:16:23  terui
27   Initial upload
28 
29   $NoKeywords: $
30  *---------------------------------------------------------------------------*/
31 
32 #include <revolution.h>
33 #include <revolution/kpad.h>
34 #include <revolution/mem.h>
35 #include "sample.h"
36 #include <string.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 
40 /*---------------------------------------------------------------------------*
41     Constant Definitions
42  *---------------------------------------------------------------------------*/
43 #define     SAMPLE_FIFO_SIZE    ( 256 * 1024 )
44 #define     SAMPLE_XFB_COUNT    ( 2 )
45 #define     SAMPLE_PADHEAP_SIZE ( 128 * 1024 )
46 
47 #define     SAMPLE_RAW_COUNT    ( 33 + 1 )
48 #define     SAMPLE_COL_COUNT    ( 88 )
49 
50 /*---------------------------------------------------------------------------*
51     Structure definitions
52  *---------------------------------------------------------------------------*/
53 typedef struct SAMPLECamera
54 {
55     Vec     pos;
56     Vec     up;
57     Vec     target;
58     f32     fovy;
59     f32     aspect;
60     f32     znear;
61     f32     zfar;
62 
63 } SAMPLECamera;
64 
65 /*---------------------------------------------------------------------------*
66     internal variable definitions
67  *---------------------------------------------------------------------------*/
68 static s32              sampleFrameCount    = 0;
69 static s32              sampleFrameCycle;
70 static GXRenderModeObj  sampleRend;
71 static u8               sampleFifoBuf[ SAMPLE_FIFO_SIZE ] ATTRIBUTE_ALIGN( 32 );
72 static void*            sampleXFB[ SAMPLE_XFB_COUNT ];
73 static MEMHeapHandle    samplePadHeap;
74 
75 static u8               sampleFontBuf[ OSRoundUp32B( OS_FONT_SIZE_ANSI + OS_FONT_SIZE_SJIS ) ] ATTRIBUTE_ALIGN( 32 );
76 static OSFontHeader*    sampleFont  = (OSFontHeader*)( &( sampleFontBuf[ 0 ] ) );
77 static char             sampleString[ SAMPLE_RAW_COUNT ][ 256 ];
78 static s32              sampleRawIndex;
79 static s32              sampleNextRawIndex;
80 static s32              sampleNextColIndex;
81 static SAMPLECamera     sampleCamera;
82 static GXLightObj       sampleLight;
83 
84 /*---------------------------------------------------------------------------*
85     internal function prototype
86  *---------------------------------------------------------------------------*/
87 static void     InitString( void );
88 static void     RenderString( void );
89 static void*    AllocFromPadHeap( u32 size );
90 static u8       FreeToPadHeap( void* ptr );
91 
92 /*---------------------------------------------------------------------------*
93   Name: SampleInit
94   Description: Performs initialization required for on-screen display.
95   Arguments: None
96   Returns: None
97  *---------------------------------------------------------------------------*/
98 void
SampleInit(void)99 SampleInit( void )
100 {
101     /* Initialize VI */
102     {
103         const GXRenderModeObj*  viConf  = &GXNtsc480IntDf;
104 
105         VIInit();
106         (void)memcpy( &sampleRend, viConf, sizeof( GXRenderModeObj ) );
107         GXAdjustForOverscan( &sampleRend, &sampleRend, 0, 16 );
108         sampleFrameCycle    = ( ( ( sampleRend.viTVmode >> 2 ) == VI_PAL ) ? 50 : 60 );
109         VIConfigure( &sampleRend );
110     }
111 
112     /* Allocate external frame buffer */
113     {
114         void*   arena_s;
115         u32     xfbSize;
116         s32     i;
117 
118         arena_s = OSGetMEM1ArenaLo();
119         xfbSize = (u32)( VIPadFrameBufferWidth( sampleRend.fbWidth ) * sampleRend.xfbHeight * VI_DISPLAY_PIX_SZ );
120         for( i = 0; i < SAMPLE_XFB_COUNT; i ++ )
121         {
122             sampleXFB[ i ]  = (void*)OSRoundUp32B( (u32)arena_s );
123             arena_s = (void*)OSRoundUp32B( (u32)( sampleXFB[ i ] ) + xfbSize );
124         }
125         OSSetMEM1ArenaLo( arena_s );
126     }
127 
128     /* Initialize heap for WPAD sampling */
129     {
130         void*   heapAddress;
131 
132         heapAddress = OSGetMEM2ArenaLo();
133         OSSetMEM2ArenaLo( (void*)OSRoundUp32B( (u32)heapAddress + SAMPLE_PADHEAP_SIZE ) );
134         samplePadHeap   = MEMCreateExpHeap( heapAddress, SAMPLE_PADHEAP_SIZE );
135         if( samplePadHeap == NULL )
136         {
137             OSHalt( "Could not create heap.\n" );
138         }
139         WPADRegisterAllocator( AllocFromPadHeap, FreeToPadHeap );
140     }
141 
142     /* Initialize controllers */
143     {
144         KPADStatus  status;
145 
146         KPADInit();
147         while( KPADRead( WPAD_CHAN0, &status, 1 ) ) {}
148         while( KPADRead( WPAD_CHAN1, &status, 1 ) ) {}
149         while( KPADRead( WPAD_CHAN2, &status, 1 ) ) {}
150         while( KPADRead( WPAD_CHAN3, &status, 1 ) ) {}
151     }
152 
153     /* Initialize GX */
154     {
155         GXFifoObj*  gxFifo;
156         f32         yScale;
157         u16         xfbHeight;
158 
159         gxFifo  = GXInit( sampleFifoBuf, SAMPLE_FIFO_SIZE );
160         GXSetViewport( 0.0F, 0.0F, (f32)sampleRend.fbWidth, (f32)sampleRend.efbHeight, 0.0F, 1.0F );
161         GXSetScissor( 0, 0, (u32)sampleRend.fbWidth, (u32)sampleRend.efbHeight );
162         yScale  = GXGetYScaleFactor( sampleRend.efbHeight, sampleRend.xfbHeight );
163         xfbHeight   = (u16)GXSetDispCopyYScale( yScale );
164         GXSetDispCopySrc( 0, 0, sampleRend.fbWidth, sampleRend.efbHeight );
165         GXSetDispCopyDst( sampleRend.fbWidth, xfbHeight );
166         GXSetCopyFilter( sampleRend.aa, sampleRend.sample_pattern, GX_TRUE, sampleRend.vfilter );
167         GXSetDispCopyGamma( GX_GM_1_0 );
168         if( sampleRend.aa )
169         {
170             GXSetPixelFmt( GX_PF_RGB565_Z16, GX_ZC_LINEAR );
171         }
172         else
173         {
174             GXSetPixelFmt( GX_PF_RGB8_Z24, GX_ZC_LINEAR );
175         }
176         GXCopyDisp( sampleXFB[ 0 ], GX_TRUE );
177     }
178 
179     InitString();
180 
181     /* Wait for first frame */
182     {
183         VISetNextFrameBuffer( sampleXFB[ 0 ] );
184         VISetBlack( FALSE );
185         VIFlush();
186         VIWaitForRetrace();
187         if( (u32)( sampleRend.viTVmode ) & 0x1 )
188         {
189             VIWaitForRetrace();
190         }
191     }
192 }
193 
194 /*---------------------------------------------------------------------------*
195   Name: SampleWaitRetrace
196   Description: Wait until V-Blank interrupt is generated.
197   Arguments: None
198   Returns: None
199  *---------------------------------------------------------------------------*/
200 void
SampleWaitRetrace(void)201 SampleWaitRetrace( void )
202 {
203     RenderString();
204     GXCopyDisp( sampleXFB[ sampleFrameCount % SAMPLE_XFB_COUNT ], GX_TRUE );
205     VISetNextFrameBuffer( sampleXFB[ sampleFrameCount % SAMPLE_XFB_COUNT ] );
206     VIFlush();
207     VIWaitForRetrace();
208     sampleFrameCount ++;
209 }
210 
211 /*---------------------------------------------------------------------------*
212   Name: SampleReport
213   Description: Performs debug display of text.
214   Arguments   : msg - The character string to be displayed
215                 ...     -   Virtual argument.
216   Returns: None
217  *---------------------------------------------------------------------------*/
218 void
SampleReport(const char * msg,...)219 SampleReport( const char* msg, ... )
220 {
221     va_list     vl;
222     char        temp[ 256 ];
223     s32         i;
224     char*       p;
225 
226     (void)memset( temp, 0, sizeof( temp ) );
227     va_start( vl, msg );
228     (void)vsprintf( temp, msg, vl );
229     va_end( vl );
230 
231     OSReport( temp );
232     p   = &temp[ 0 ];
233     for( i = 0; i < 256; i ++ )
234     {
235         if( *p == 0x00 )
236         {
237             sampleString[ sampleNextRawIndex % SAMPLE_RAW_COUNT ][ sampleNextColIndex ] = 0x00;
238             break;
239         }
240         if( *p == 0x0d )
241         {
242             p ++;
243             continue;
244         }
245         if( *p == 0x0a )
246         {
247             sampleString[ sampleNextRawIndex % SAMPLE_RAW_COUNT ][ sampleNextColIndex ] = 0x00;
248             sampleNextColIndex  = 0;
249             sampleNextRawIndex  ++;
250             if( sampleNextRawIndex >= SAMPLE_RAW_COUNT )
251             {
252                 sampleRawIndex = ( sampleRawIndex + 1 ) % SAMPLE_RAW_COUNT;
253             }
254             p ++;
255             continue;
256         }
257         sampleString[ sampleNextRawIndex % SAMPLE_RAW_COUNT ][ sampleNextColIndex ] = *p;
258         if( ( ++ sampleNextColIndex ) > 255 )
259         {
260             sampleNextColIndex  = 0;
261             sampleNextRawIndex  ++;
262             if( sampleNextRawIndex >= SAMPLE_RAW_COUNT )
263             {
264                 sampleRawIndex = ( sampleRawIndex + 1 ) % SAMPLE_RAW_COUNT;
265             }
266         }
267         p ++;
268     }
269 }
270 
271 /*---------------------------------------------------------------------------*
272   Name: AllocFromPadHeap
273   Description: Dynamically allocates memory for the WPAD library.
274   Arguments: size    -   Specifies the amount of memory to be allocated.
275   Returns: void*   - Returns the starting address of the allocated memory.
276  *---------------------------------------------------------------------------*/
277 static void*
AllocFromPadHeap(u32 size)278 AllocFromPadHeap( u32 size )
279 {
280     return MEMAllocFromExpHeap( samplePadHeap, size );
281 }
282 
283 /*---------------------------------------------------------------------------*
284   Name: FreeToPadHeap
285   Description: Frees memory dynamically allocated for the WPAD library.
286   Arguments: ptr     -   Specifies the start address of the memory to be freed.
287   Returns: u8      -   Returns 0 if attempt to free memory fails.
288  *---------------------------------------------------------------------------*/
289 static u8
FreeToPadHeap(void * ptr)290 FreeToPadHeap( void* ptr )
291 {
292     if( ptr == NULL )
293     {
294         return 0;
295     }
296     MEMFreeToExpHeap( samplePadHeap, ptr );
297     return 1;
298 }
299 
300 /*---------------------------------------------------------------------------*
301   Name: InitString
302   Description: Performs the necessary initialization for debug display of strings.
303   Arguments: None
304   Returns: None
305  *---------------------------------------------------------------------------*/
306 static void
InitString(void)307 InitString( void )
308 {
309     /* Initialize the string buffer*/
310     (void)memset( sampleString, 0, sizeof( sampleString ) );
311     sampleRawIndex  = 0;
312     sampleNextRawIndex  = 0;
313     sampleNextColIndex  = 0;
314 
315     /* Load font data */
316     (void)OSInitFont( sampleFont );
317 
318     /* Initialize camera */
319     {
320         sampleCamera.fovy       = 33.3f;
321         sampleCamera.aspect     = (f32)( 10.0f / 7.0f );
322         sampleCamera.znear      = 0.001f;
323         sampleCamera.zfar       = 1023.999f;
324         sampleCamera.pos.x      = 0.0f;
325         sampleCamera.pos.y      = 0.0f;
326         sampleCamera.pos.z      = -20.0f;
327         sampleCamera.up.x       = 0.0f;
328         sampleCamera.up.y       = 1.0f;
329         sampleCamera.up.z       = 0.0f;
330         sampleCamera.target.x   = 0.0f;
331         sampleCamera.target.y   = 0.0f;
332         sampleCamera.target.z   = 0.0f;
333     }
334 
335     /* Initialize lighting */
336     {
337         const Vec       lpos    = { 0.0f, 0.0f, 0.0f };
338         const Vec       ldir    = { 0.0f, 0.0f, -1.0f };
339         const GXColor   lcol    = { 0xff, 0xff, 0xff, 0xff };
340 
341         GXInitLightPosv( &sampleLight, &lpos );
342         GXInitLightDirv( &sampleLight, &ldir );
343         GXInitLightColor( &sampleLight, lcol );
344         GXInitLightSpot( &sampleLight, 0.03f, GX_SP_COS );
345         GXInitLightDistAttn( &sampleLight, 3.0f, 0.5f, GX_DA_GENTLE );
346     }
347 }
348 
349 /*---------------------------------------------------------------------------*
350   Name: RenderString
351   Description: Performs the rendering required for each picture frame in order to perform debug display of strings.
352                 Performs rendering.
353   Arguments: None
354   Returns: None
355  *---------------------------------------------------------------------------*/
356 static void
RenderString(void)357 RenderString( void )
358 {
359     f32     scrWidth    = (f32)( sampleRend.fbWidth );
360     f32     scrHeight   = (f32)( sampleRend.efbHeight );
361 
362     const GXColor   ambientCol  = { 0xff, 0xff, 0xff, 0xff };
363     const GXColor   strCol      = { 0x00, 0x00, 0x00, 0xff };
364     const GXColor   backCol     = { 0xff, 0xff, 0xff, 0xff };
365 
366     /* Rendering preparation */
367     {
368         Mtx44   projMtx;
369         Mtx     posMtx;
370 
371         GXInvalidateTexAll();
372         /* Viewport settings */
373         if( (u32)( sampleRend.viTVmode ) & 0x1 )
374         {
375             GXSetViewportJitter( 0.0f, 0.0f, (f32)( sampleRend.fbWidth ), (f32)( sampleRend.efbHeight ), 0.0f, 1.0f, VIGetNextField() );
376         }
377         else
378         {
379             GXSetViewport( 0.0f, 0.0f, (f32)( sampleRend.fbWidth ), (f32)( sampleRend.efbHeight ), 0.0f, 1.0f );
380         }
381         GXSetScissor( 0, 0, (u32)( sampleRend.fbWidth ), (u32)( sampleRend.efbHeight ) );
382         /* Camera settings */
383         MTXOrtho( projMtx, 0.0f, scrHeight, 0.0f, scrWidth, sampleCamera.znear, sampleCamera.zfar );
384         GXSetProjection( projMtx, GX_ORTHOGRAPHIC );
385         MTXIdentity( posMtx );
386         GXLoadPosMtxImm( posMtx, GX_PNMTX0 );
387         GXSetCurrentMtx( GX_PNMTX0 );
388         GXSetZMode( GX_TRUE, GX_LEQUAL, GX_TRUE );
389         GXSetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR );
390         /* Lighting settings */
391         GXSetNumChans( 1 );
392         GXSetChanAmbColor( GX_COLOR0A0, ambientCol );
393         GXLoadLightObjImm( &sampleLight, GX_LIGHT0 );
394         GXSetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_NONE, GX_AF_NONE );
395         GXSetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_NONE, GX_AF_NONE );
396     }
397 
398     /* Background rendering */
399     {
400         s16     z   = -1023;
401 
402         /* Vertex settings */
403         GXClearVtxDesc();
404         GXSetVtxDesc( GX_VA_POS, GX_DIRECT );
405         GXSetVtxAttrFmt( GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 0 );
406         /* Texture settings  */
407         GXSetNumTexGens( 0 );
408         GXSetNumTevStages( 1 );
409         GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
410         GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0 );
411         /* Render quadrangular polygons */
412         GXSetChanMatColor( GX_COLOR0A0, backCol );
413         GXBegin( GX_QUADS, GX_VTXFMT1, 4 );
414             GXPosition3s16( 0, 0, z );
415             GXPosition3s16( (s16)scrWidth, 0, z );
416             GXPosition3s16( (s16)scrWidth, (s16)scrHeight, z );
417             GXPosition3s16( 0, (s16)scrHeight, z );
418         GXEnd();
419     }
420 
421     /* Render character strings */
422     {
423         s32         fx, fy, fw;
424         void*       image;
425         char*       ptr;
426         s32         i, j;
427         GXTexObj    tobj;
428         s16         x, y, z, w, h;
429         Mtx         scaleMtx;
430 
431         /* Vertex settings */
432         GXClearVtxDesc();
433         GXSetVtxDesc( GX_VA_POS, GX_DIRECT );
434         GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );
435         GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0 );
436         GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0 );
437         /* Texture settings */
438         GXSetNumTexGens( 1 );
439         MTXScale( scaleMtx, ( 1.0f / sampleFont->sheetWidth ), ( 1.0f / sampleFont->sheetHeight ), 1.0f );
440         GXLoadTexMtxImm( scaleMtx, GX_TEXMTX0, GX_MTX2x4 );
441         GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0 );
442         GXSetNumTevStages( 1 );
443         GXSetTevOp( GX_TEVSTAGE0, GX_MODULATE );
444         GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0 );
445 
446         /* Draw string buffer */
447         GXSetChanMatColor( GX_COLOR0A0, strCol );
448         for( i = 0; i < ( SAMPLE_RAW_COUNT - 1 ); i ++ )
449         {
450             x   = 2;
451             y   = (s16)( ( scrHeight * i ) / ( SAMPLE_RAW_COUNT - 1 ) );
452             z   = -1;
453             h   = (s16)( scrHeight / ( SAMPLE_RAW_COUNT - 1 ) );
454 
455             ptr = &( sampleString[ ( sampleRawIndex + i ) % SAMPLE_RAW_COUNT ][ 0 ] );
456             for( j = 0; j < 256; j ++ )
457             {
458                 if( ( *ptr == 0x00 ) || ( *ptr == 0x0d ) || ( *ptr == 0x0a ) )
459                 {
460                     break;
461                 }
462                 ptr = OSGetFontTexture( ptr, &image, &fx, &fy, &fw );
463                 w   = (s16)( ( fw * scrWidth ) / ( 12 * SAMPLE_COL_COUNT ) );
464                 GXInitTexObj( &tobj, image, sampleFont->sheetWidth, sampleFont->sheetHeight, GX_TF_I4, GX_REPEAT, GX_REPEAT, GX_FALSE );
465                 GXLoadTexObj( &tobj, GX_TEXMAP0 );
466                 GXBegin( GX_QUADS, GX_VTXFMT0, 4 );
467                     GXPosition3s16( (s16)( x + 0 ), (s16)( y + 0 ), z );
468                     GXTexCoord2s16( (s16)( fx +  0 ), (s16)( fy +  0 ) );
469                     GXPosition3s16( (s16)( x + w ), (s16)( y + 0 ), z );
470                     GXTexCoord2s16( (s16)( fx + fw ), (s16)( fy +  0 ) );
471                     GXPosition3s16( (s16)( x + w ), (s16)( y + h ), z );
472                     GXTexCoord2s16( (s16)( fx + fw ), (s16)( fy + 24 ) );
473                     GXPosition3s16( (s16)( x + 0 ), (s16)( y + h ), z );
474                     GXTexCoord2s16( (s16)( fx +  0 ), (s16)( fy + 24 ) );
475                 GXEnd();
476                 x   += w;
477                 if( x >= scrWidth )
478                 {
479                     break;
480                 }
481             }
482         }
483     }
484 }
485 
486 /*---------------------------------------------------------------------------*
487   End of file
488  *---------------------------------------------------------------------------*/
489