/*---------------------------------------------------------------------------* Project: WD demo File: sample.c Copyright 2006 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: sample.c,v $ Revision 1.8 2008/06/02 02:24:15 seiki_masashi Added support for KPADRead specification changes. Revision 1.7 2008/05/30 02:27:03 seiki_masashi Reverted code consequent upon reverted SDK code. Revision 1.5 2006/08/15 03:51:15 yasu Support for PADDING warnings. Revision 1.4 2006/07/18 09:25:25 terui Fixed appearance Revision 1.3 2006/07/13 13:55:09 terui Adjusted the size of the heap for PAD. Revision 1.2 2006/07/13 12:38:32 terui Fixed appearance Revision 1.1 2006/07/13 12:16:23 terui Initial upload $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include #include #include "sample.h" #include #include #include /*---------------------------------------------------------------------------* Constant Definitions *---------------------------------------------------------------------------*/ #define SAMPLE_FIFO_SIZE ( 256 * 1024 ) #define SAMPLE_XFB_COUNT ( 2 ) #define SAMPLE_PADHEAP_SIZE ( 128 * 1024 ) #define SAMPLE_RAW_COUNT ( 33 + 1 ) #define SAMPLE_COL_COUNT ( 88 ) /*---------------------------------------------------------------------------* Structure Definitions *---------------------------------------------------------------------------*/ typedef struct SAMPLECamera { Vec pos; Vec up; Vec target; f32 fovy; f32 aspect; f32 znear; f32 zfar; } SAMPLECamera; /*---------------------------------------------------------------------------* Internal Variable Definitions *---------------------------------------------------------------------------*/ static s32 sampleFrameCount = 0; static s32 sampleFrameCycle; static GXRenderModeObj sampleRend; static u8 sampleFifoBuf[ SAMPLE_FIFO_SIZE ] ATTRIBUTE_ALIGN( 32 ); static void* sampleXFB[ SAMPLE_XFB_COUNT ]; static MEMHeapHandle samplePadHeap; static u8 sampleFontBuf[ OSRoundUp32B( OS_FONT_SIZE_ANSI + OS_FONT_SIZE_SJIS ) ] ATTRIBUTE_ALIGN( 32 ); static OSFontHeader* sampleFont = (OSFontHeader*)( &( sampleFontBuf[ 0 ] ) ); static char sampleString[ SAMPLE_RAW_COUNT ][ 256 ]; static s32 sampleRawIndex; static s32 sampleNextRawIndex; static s32 sampleNextColIndex; static SAMPLECamera sampleCamera; static GXLightObj sampleLight; /*---------------------------------------------------------------------------* Internal Function Prototype *---------------------------------------------------------------------------*/ static void InitString( void ); static void RenderString( void ); static void* AllocFromPadHeap( u32 size ); static u8 FreeToPadHeap( void* ptr ); /*---------------------------------------------------------------------------* Name : SampleInit Description : Performs initialization required for on-screen display. Arguments : None. Returns : None. *---------------------------------------------------------------------------*/ void SampleInit( void ) { /* Initialize VI */ { const GXRenderModeObj* viConf = &GXNtsc480IntDf; VIInit(); (void)memcpy( &sampleRend, viConf, sizeof( GXRenderModeObj ) ); GXAdjustForOverscan( &sampleRend, &sampleRend, 0, 16 ); sampleFrameCycle = ( ( ( sampleRend.viTVmode >> 2 ) == VI_PAL ) ? 50 : 60 ); VIConfigure( &sampleRend ); } /* Allocate eXternal frame buffer */ { void* arena_s; u32 xfbSize; s32 i; arena_s = OSGetMEM1ArenaLo(); xfbSize = (u32)( VIPadFrameBufferWidth( sampleRend.fbWidth ) * sampleRend.xfbHeight * VI_DISPLAY_PIX_SZ ); for( i = 0; i < SAMPLE_XFB_COUNT; i ++ ) { sampleXFB[ i ] = (void*)OSRoundUp32B( (u32)arena_s ); arena_s = (void*)OSRoundUp32B( (u32)( sampleXFB[ i ] ) + xfbSize ); } OSSetMEM1ArenaLo( arena_s ); } /* Initialize heap for WPAD sampling */ { void* heapAddress; heapAddress = OSGetMEM2ArenaLo(); OSSetMEM2ArenaLo( (void*)OSRoundUp32B( (u32)heapAddress + SAMPLE_PADHEAP_SIZE ) ); samplePadHeap = MEMCreateExpHeap( heapAddress, SAMPLE_PADHEAP_SIZE ); if( samplePadHeap == NULL ) { OSHalt( "Could not create heap.\n" ); } WPADRegisterAllocator( AllocFromPadHeap, FreeToPadHeap ); } /* Initialize controllers */ { KPADStatus status; KPADInit(); while( KPADRead( WPAD_CHAN0, &status, 1 ) > 0 ) {} while( KPADRead( WPAD_CHAN1, &status, 1 ) > 0 ) {} while( KPADRead( WPAD_CHAN2, &status, 1 ) > 0 ) {} while( KPADRead( WPAD_CHAN3, &status, 1 ) > 0 ) {} } /* Initialize GX */ { GXFifoObj* gxFifo; f32 yScale; u16 xfbHeight; gxFifo = GXInit( sampleFifoBuf, SAMPLE_FIFO_SIZE ); GXSetViewport( 0.0F, 0.0F, (f32)sampleRend.fbWidth, (f32)sampleRend.efbHeight, 0.0F, 1.0F ); GXSetScissor( 0, 0, (u32)sampleRend.fbWidth, (u32)sampleRend.efbHeight ); yScale = GXGetYScaleFactor( sampleRend.efbHeight, sampleRend.xfbHeight ); xfbHeight = (u16)GXSetDispCopyYScale( yScale ); GXSetDispCopySrc( 0, 0, sampleRend.fbWidth, sampleRend.efbHeight ); GXSetDispCopyDst( sampleRend.fbWidth, xfbHeight ); GXSetCopyFilter( sampleRend.aa, sampleRend.sample_pattern, GX_TRUE, sampleRend.vfilter ); GXSetDispCopyGamma( GX_GM_1_0 ); if( sampleRend.aa ) { GXSetPixelFmt( GX_PF_RGB565_Z16, GX_ZC_LINEAR ); } else { GXSetPixelFmt( GX_PF_RGB8_Z24, GX_ZC_LINEAR ); } GXCopyDisp( sampleXFB[ 0 ], GX_TRUE ); } InitString(); /* Wait for first frame */ { VISetNextFrameBuffer( sampleXFB[ 0 ] ); VISetBlack( FALSE ); VIFlush(); VIWaitForRetrace(); if( (u32)( sampleRend.viTVmode ) & 0x1 ) { VIWaitForRetrace(); } } } /*---------------------------------------------------------------------------* Name : SampleWaitRetrace Description : Wait until V-Blank interrupt is generated. Arguments : None. Returns : None. *---------------------------------------------------------------------------*/ void SampleWaitRetrace( void ) { RenderString(); GXCopyDisp( sampleXFB[ sampleFrameCount % SAMPLE_XFB_COUNT ], GX_TRUE ); VISetNextFrameBuffer( sampleXFB[ sampleFrameCount % SAMPLE_XFB_COUNT ] ); VIFlush(); VIWaitForRetrace(); sampleFrameCount ++; } /*---------------------------------------------------------------------------* Name : SampleReport Description : Performs debug display of text. Arguments : msg - The character string to be displayed ... - Virtual argument. Returns : None. *---------------------------------------------------------------------------*/ void SampleReport( const char* msg, ... ) { va_list vl; char temp[ 256 ]; s32 i; char* p; (void)memset( temp, 0, sizeof( temp ) ); va_start( vl, msg ); (void)vsprintf( temp, msg, vl ); va_end( vl ); OSReport( temp ); p = &temp[ 0 ]; for( i = 0; i < 256; i ++ ) { if( *p == 0x00 ) { sampleString[ sampleNextRawIndex % SAMPLE_RAW_COUNT ][ sampleNextColIndex ] = 0x00; break; } if( *p == 0x0d ) { p ++; continue; } if( *p == 0x0a ) { sampleString[ sampleNextRawIndex % SAMPLE_RAW_COUNT ][ sampleNextColIndex ] = 0x00; sampleNextColIndex = 0; sampleNextRawIndex ++; if( sampleNextRawIndex >= SAMPLE_RAW_COUNT ) { sampleRawIndex = ( sampleRawIndex + 1 ) % SAMPLE_RAW_COUNT; } p ++; continue; } sampleString[ sampleNextRawIndex % SAMPLE_RAW_COUNT ][ sampleNextColIndex ] = *p; if( ( ++ sampleNextColIndex ) > 255 ) { sampleNextColIndex = 0; sampleNextRawIndex ++; if( sampleNextRawIndex >= SAMPLE_RAW_COUNT ) { sampleRawIndex = ( sampleRawIndex + 1 ) % SAMPLE_RAW_COUNT; } } p ++; } } /*---------------------------------------------------------------------------* Name : AllocFromPadHeap Description : Dynamically allocates memory for the WPAD library. Arguments : size - Specifies the size of memory to be allocated. Returns : void* - Returns the starting address of the allocated memory. *---------------------------------------------------------------------------*/ static void* AllocFromPadHeap( u32 size ) { return MEMAllocFromExpHeap( samplePadHeap, size ); } /*---------------------------------------------------------------------------* Name : FreeToPadHeap Description : Deallocates memory dynamically allocated for the WPAD library. Arguments : ptr - Specifies the start address of the memory to be deallocated. Returns : u8 - Returns 0 if attempt to deallocate memory fails. *---------------------------------------------------------------------------*/ static u8 FreeToPadHeap( void* ptr ) { if( ptr == NULL ) { return 0; } MEMFreeToExpHeap( samplePadHeap, ptr ); return 1; } /*---------------------------------------------------------------------------* Name : InitString Description : Performs initialization necessary to display strings for debugging. Arguments : None. Returns : None. *---------------------------------------------------------------------------*/ static void InitString( void ) { /* Initialize the string buffer */ (void)memset( sampleString, 0, sizeof( sampleString ) ); sampleRawIndex = 0; sampleNextRawIndex = 0; sampleNextColIndex = 0; /* Load font data */ (void)OSInitFont( sampleFont ); /* Initialize camera */ { sampleCamera.fovy = 33.3f; sampleCamera.aspect = (f32)( 10.0f / 7.0f ); sampleCamera.znear = 0.001f; sampleCamera.zfar = 1023.999f; sampleCamera.pos.x = 0.0f; sampleCamera.pos.y = 0.0f; sampleCamera.pos.z = -20.0f; sampleCamera.up.x = 0.0f; sampleCamera.up.y = 1.0f; sampleCamera.up.z = 0.0f; sampleCamera.target.x = 0.0f; sampleCamera.target.y = 0.0f; sampleCamera.target.z = 0.0f; } /* Initialize light */ { const Vec lpos = { 0.0f, 0.0f, 0.0f }; const Vec ldir = { 0.0f, 0.0f, -1.0f }; const GXColor lcol = { 0xff, 0xff, 0xff, 0xff }; GXInitLightPosv( &sampleLight, &lpos ); GXInitLightDirv( &sampleLight, &ldir ); GXInitLightColor( &sampleLight, lcol ); GXInitLightSpot( &sampleLight, 0.03f, GX_SP_COS ); GXInitLightDistAttn( &sampleLight, 3.0f, 0.5f, GX_DA_GENTLE ); } } /*---------------------------------------------------------------------------* Name : RenderString Description : Performs the rendering required for each picture frame in order to perform debug display of text string. Arguments : None. Returns : None. *---------------------------------------------------------------------------*/ static void RenderString( void ) { f32 scrWidth = (f32)( sampleRend.fbWidth ); f32 scrHeight = (f32)( sampleRend.efbHeight ); const GXColor ambientCol = { 0xff, 0xff, 0xff, 0xff }; const GXColor strCol = { 0x00, 0x00, 0x00, 0xff }; const GXColor backCol = { 0xff, 0xff, 0xff, 0xff }; /* rendering preparation */ { Mtx44 projMtx; Mtx posMtx; GXInvalidateTexAll(); /* Viewport settings */ if( (u32)( sampleRend.viTVmode ) & 0x1 ) { GXSetViewportJitter( 0.0f, 0.0f, (f32)( sampleRend.fbWidth ), (f32)( sampleRend.efbHeight ), 0.0f, 1.0f, VIGetNextField() ); } else { GXSetViewport( 0.0f, 0.0f, (f32)( sampleRend.fbWidth ), (f32)( sampleRend.efbHeight ), 0.0f, 1.0f ); } GXSetScissor( 0, 0, (u32)( sampleRend.fbWidth ), (u32)( sampleRend.efbHeight ) ); /* camera settings */ MTXOrtho( projMtx, 0.0f, scrHeight, 0.0f, scrWidth, sampleCamera.znear, sampleCamera.zfar ); GXSetProjection( projMtx, GX_ORTHOGRAPHIC ); MTXIdentity( posMtx ); GXLoadPosMtxImm( posMtx, GX_PNMTX0 ); GXSetCurrentMtx( GX_PNMTX0 ); GXSetZMode( GX_TRUE, GX_LEQUAL, GX_TRUE ); GXSetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR ); /* light settings */ GXSetNumChans( 1 ); GXSetChanAmbColor( GX_COLOR0A0, ambientCol ); GXLoadLightObjImm( &sampleLight, GX_LIGHT0 ); GXSetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_NONE, GX_AF_NONE ); GXSetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_NONE, GX_AF_NONE ); } /* Render background */ { s16 z = -1023; /* Set vertex */ GXClearVtxDesc(); GXSetVtxDesc( GX_VA_POS, GX_DIRECT ); GXSetVtxAttrFmt( GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 0 ); /* Texture settings */ GXSetNumTexGens( 0 ); GXSetNumTevStages( 1 ); GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR ); GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0 ); /* Render square polygon */ GXSetChanMatColor( GX_COLOR0A0, backCol ); GXBegin( GX_QUADS, GX_VTXFMT1, 4 ); GXPosition3s16( 0, 0, z ); GXPosition3s16( (s16)scrWidth, 0, z ); GXPosition3s16( (s16)scrWidth, (s16)scrHeight, z ); GXPosition3s16( 0, (s16)scrHeight, z ); GXEnd(); } /* Render character string */ { s32 fx, fy, fw; void* image; char* ptr; s32 i, j; GXTexObj tobj; s16 x, y, z, w, h; Mtx scaleMtx; /* Set vertex */ GXClearVtxDesc(); GXSetVtxDesc( GX_VA_POS, GX_DIRECT ); GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT ); GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0 ); GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0 ); /* Texture settings */ GXSetNumTexGens( 1 ); MTXScale( scaleMtx, ( 1.0f / sampleFont->sheetWidth ), ( 1.0f / sampleFont->sheetHeight ), 1.0f ); GXLoadTexMtxImm( scaleMtx, GX_TEXMTX0, GX_MTX2x4 ); GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0 ); GXSetNumTevStages( 1 ); GXSetTevOp( GX_TEVSTAGE0, GX_MODULATE ); GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0 ); /* Render the string buffer */ GXSetChanMatColor( GX_COLOR0A0, strCol ); for( i = 0; i < ( SAMPLE_RAW_COUNT - 1 ); i ++ ) { x = 2; y = (s16)( ( scrHeight * i ) / ( SAMPLE_RAW_COUNT - 1 ) ); z = -1; h = (s16)( scrHeight / ( SAMPLE_RAW_COUNT - 1 ) ); ptr = &( sampleString[ ( sampleRawIndex + i ) % SAMPLE_RAW_COUNT ][ 0 ] ); for( j = 0; j < 256; j ++ ) { if( ( *ptr == 0x00 ) || ( *ptr == 0x0d ) || ( *ptr == 0x0a ) ) { break; } ptr = OSGetFontTexture( ptr, &image, &fx, &fy, &fw ); w = (s16)( ( fw * scrWidth ) / ( 12 * SAMPLE_COL_COUNT ) ); GXInitTexObj( &tobj, image, sampleFont->sheetWidth, sampleFont->sheetHeight, GX_TF_I4, GX_REPEAT, GX_REPEAT, GX_FALSE ); GXLoadTexObj( &tobj, GX_TEXMAP0 ); GXBegin( GX_QUADS, GX_VTXFMT0, 4 ); GXPosition3s16( (s16)( x + 0 ), (s16)( y + 0 ), z ); GXTexCoord2s16( (s16)( fx + 0 ), (s16)( fy + 0 ) ); GXPosition3s16( (s16)( x + w ), (s16)( y + 0 ), z ); GXTexCoord2s16( (s16)( fx + fw ), (s16)( fy + 0 ) ); GXPosition3s16( (s16)( x + w ), (s16)( y + h ), z ); GXTexCoord2s16( (s16)( fx + fw ), (s16)( fy + 24 ) ); GXPosition3s16( (s16)( x + 0 ), (s16)( y + h ), z ); GXTexCoord2s16( (s16)( fx + 0 ), (s16)( fy + 24 ) ); GXEnd(); x += w; if( x >= scrWidth ) { break; } } } } } /*---------------------------------------------------------------------------* End of file *---------------------------------------------------------------------------*/