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