/*---------------------------------------------------------------------------* Project: KPAD sample program File: main.c Programmer: Keizo Ohta HIRATSU Daisuke Copyright 2005-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. *---------------------------------------------------------------------------*/ #include #include #include #include #include "main.h" #include "kfont.h" #include "sample.h" /*************************************************************** GXFIFO ***************************************************************/ #define GX_FIFO_SIZE ( 1 * 1024*1024 ) // Large enough (The smaller the FIFO, the larger the chance of waiting for space to open when a command is issued.) static void *gx_fifo_p ; // Pointer to buffer static GXFifoObj *gx_fifo_obj ; // Management structure /*************************************************************** Frame buffer ***************************************************************/ GXRenderModeObj *rmode_p ; // Pointer to drawing mode static u8 vfilter[7] = { 0,8, 16,16,16, 8,0 } ; static void *xfb_p[ 2 ] ; // Pointer to double buffer static s32 draw_xfb_idx ; // XFB being drawn by GX static s32 disp_xfb_idx ; // XFB being displayed by VI /*************************************************************** Controller ***************************************************************/ KPADStatus kpads[ WPAD_MAX_CONTROLLERS ][ KPAD_MAX_READ_BUFS ] ; s32 kpad_reads ; /******************************************************************************* Memory initialization *******************************************************************************/ static void init_memory( void ) { void *arenaLo, *arenaHi ; OSHeapHandle heap ; //----- Check available memory arenaLo = OSGetArenaLo() ; arenaHi = OSGetArenaHi() ; //----- Declare the creation of one heap that takes up all available memory arenaLo = OSInitAlloc( arenaLo, arenaHi, 1 ) ; OSSetArenaLo( arenaLo ) ; // Reset because the available memory changes //----- Create a heap which takes up all available memory and set it as the current heap heap = OSCreateHeap( arenaLo, arenaHi ) ; (void)OSSetCurrentHeap( heap ) ; //----- Make it clear ahead of time that available memory has been utilized arenaLo = arenaHi ; OSSetArenaLo( arenaLo ) ; } /******************************************************************************* Initialize memory (MEM2) *******************************************************************************/ static MEMAllocator s_mem2Allocator; static MEMHeapHandle s_handle; static void init_memory2(void) { void *lo = OSGetMEM2ArenaLo(); void *hi = OSGetMEM2ArenaHi(); s_handle = MEMCreateFrmHeap(lo, (u32)hi - (u32)lo); if ( s_handle == MEM_HEAP_INVALID_HANDLE ) { OSHalt("MEM2 heap allocation error.\n"); } else { OSSetMEM2ArenaLo(hi); MEMInitAllocatorForFrmHeap(&s_mem2Allocator, s_handle, 32); // Buffer requires 32-byte alignment. } } static void* alloc32(u32 size) { return MEMAllocFromAllocator(&s_mem2Allocator, size); } static u8 free32(void *addr) { MEMFreeToAllocator(&s_mem2Allocator, addr); return 1; } /******************************************************************************* Initialize relationship with display device *******************************************************************************/ static void init_display( void ) { u32 xfb_size ; //----- Select drawing mode rmode_p = &GXNtsc480IntDf ; //----- Allocate frame buffer xfb_size = VIPadFrameBufferWidth(rmode_p->fbWidth) * rmode_p->xfbHeight * (u32)VI_DISPLAY_PIX_SZ ; xfb_p[0] = OSAlloc( xfb_size ) ; xfb_p[1] = OSAlloc( xfb_size ) ; //----- Select a drawing buffer and display buffer draw_xfb_idx = 0 ; disp_xfb_idx = 1 ; //----- Initialize VI VIConfigure( rmode_p ) ; VISetNextFrameBuffer( xfb_p[ disp_xfb_idx ] ) ; VIFlush() ; VIWaitForRetrace() ; // In order to enable Configure, VIWaitForRetrace() ; // you need to wait two times. } /******************************************************************************* Initialize GX relationship *******************************************************************************/ static void init_gx( void ) { GXColor clear_clr = { 0,0,0, 0 } ; //----- Create GXFIFO gx_fifo_p = OSAlloc( GX_FIFO_SIZE ) ; gx_fifo_obj = GXInit( gx_fifo_p, GX_FIFO_SIZE ) ; //----- Select pixel format GXSetPixelFmt( GX_PF_RGB8_Z24, GX_ZC_LINEAR ) ; GXSetDither( GX_DISABLE ) ; //----- Initialize settings for copying from EFB to XFB GXSetDispCopySrc( 0, 0, rmode_p->fbWidth, rmode_p->efbHeight ) ; GXSetDispCopyDst( rmode_p->fbWidth, rmode_p->xfbHeight ) ; (void)GXSetDispCopyYScale( (f32)(rmode_p->xfbHeight) / (f32)(rmode_p->efbHeight) ) ; GXSetDispCopyGamma( GX_GM_1_0 ) ; GXSetCopyFilter( rmode_p->aa, rmode_p->sample_pattern, GX_ENABLE, vfilter ) ; GXSetCopyClear( clear_clr, 0x00FFFFFF ) ; //----- Initialize EFB drawing area GXSetViewport( 0.0f, 0.0f, rmode_p->fbWidth, rmode_p->efbHeight, 0.0f, 1.0f ) ; GXSetScissor( 0, 0, (u32)rmode_p->fbWidth, (u32)rmode_p->efbHeight ) ; //----- Clear EFB and XFB GXCopyDisp( xfb_p[0], GX_ENABLE ) ; // The EFB is cleared and garbage is placed in XFB[0] GXCopyDisp( xfb_p[0], GX_DISABLE ) ; // The cleared EFB is placed in XFB[0] GXCopyDisp( xfb_p[1], GX_DISABLE ) ; // The cleared EFB is placed in XFB[1] GXDrawDone() ; } /******************************************************************************* Main *******************************************************************************/ void main( void ) { /*********************************************************************** Initialization processing ***********************************************************************/ //----- Highest-priority hardware initialization VIInit() ; //----- Other priority initializations init_memory() ; // Enable allocation and release of memory init_memory2(); init_display() ; // Display device-related init_gx() ; // GX-related WPADRegisterAllocator(alloc32, free32); KPADInit() ; // Controller //----- Initialize application init_kfont_texture() ; init_sample() ; //----- Screen display ON VISetBlack( FALSE ) ; VIFlush() ; /*********************************************************************** Main loop ***********************************************************************/ while (1) { /*************************************************************** First, perform calculations by the CPU Then find coordinates based on controller input, And prepare the data necessary to issue a GX command ***************************************************************/ //----- Load controller kpad_reads = KPADRead( 0, &kpads[0][0], KPAD_MAX_READ_BUFS ) ; //----- Various calculations work_sample() ; /*************************************************************** Issue GX command and go on drawing to EFB ***************************************************************/ //----- Cast spell to start issuing the command GXInvalidateVtxCache() ; GXInvalidateTexAll() ; //----- Issue various commands draw_sample() ; //----- Finally, copy from EFB to XFB GXCopyDisp( xfb_p[ draw_xfb_idx ], GX_ENABLE ) ; GXDrawDone() ; /*************************************************************** The XFB copied here can be selected for display on the TV ***************************************************************/ disp_xfb_idx = draw_xfb_idx ; VISetNextFrameBuffer( xfb_p[ disp_xfb_idx ] ) ; VIFlush() ; //----- Wait for the display to actually switch VIWaitForRetrace() ; //----- Switch to the no longer displayed XFB ahead of time for the next drawing draw_xfb_idx ^= 1 ; } }