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