/*---------------------------------------------------------------------------* Project: rsodemo File: rsodemo.cpp Copyright 2006-2008 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 #include #include #include #include // RSO Module #include #include #include // HBM #include #include // RSO ModuleName #ifdef NDEBUG #define MODULE_A "hbmdemo/rsomodule.rso" #define STATIC_RSO "hbmdemo/rsodemo.sel" #else #define MODULE_A "hbmdemo/rsomoduleD.rso" #define STATIC_RSO "hbmdemo/rsodemoD.sel" #endif void _unresolved(); #define HOMEBUTTON_NOERROR 0 #define HOMEBUTTON_ICON 1 #define HOMEBUTTON_ALIVE 2 #define HOMEBUTTON_END 3 enum { OFF = 0, ON }; enum { eAlphaInIcon = 0, ePauseIcon, eAlphaOutIcon }; // NTSC / PAL int sTvmode; // Frame buffer size u16 sFbWidth = 608; u16 sFbHeight = 456; // VI size u16 viWidth = 670; u16 viWidthWide = 686; u16 viWidthWide_Pal = 682; u16 viHeight = 456; u16 viHeight_Pal = 542; #ifdef ENABLE_BALANCE_BOARD static u8 workarea[WPAD_BLCINT_WORK_LEN] ATTRIBUTE_ALIGN(32); #endif // ENABLE_BALANCE_BOARD /* RenderMode */ static GXRenderModeObj sRMObj[2] = { /* NTSC 4:3 */ { VI_TVMODE_NTSC_INT, sFbWidth, sFbHeight, viHeight, (u16)((VI_MAX_WIDTH_NTSC - viWidth)/2), (u16)((VI_MAX_HEIGHT_NTSC - viHeight)/2), viWidth, viHeight, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 10, 12, 10, 8, 8, }, /* PAL 4:3 */ { VI_TVMODE_PAL_INT, sFbWidth, sFbHeight, viHeight_Pal, (u16)((VI_MAX_WIDTH_PAL - viWidth)/2), (u16)((VI_MAX_HEIGHT_PAL - viHeight_Pal)/2), viWidth, viHeight_Pal, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 10, 12, 10, 8, 8, } }; static GXRenderModeObj sRMObjWide[2] = { /* NTSC 16:9 */ { VI_TVMODE_NTSC_INT, sFbWidth, sFbHeight, viHeight, (u16)((VI_MAX_WIDTH_NTSC - viWidth)/2), (u16)((VI_MAX_HEIGHT_NTSC - viHeight)/2), viWidth, viHeight, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 10, 12, 10, 8, 8, }, /* PAL 16:9 */ { VI_TVMODE_PAL_INT, sFbWidth, sFbHeight, viHeight_Pal, (u16)((VI_MAX_WIDTH_PAL - viWidthWide_Pal)/2), (u16)((VI_MAX_HEIGHT_PAL - viHeight_Pal)/2), viWidthWide_Pal, viHeight_Pal, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 10, 12, 10, 8, 8, } }; // ICON /* Related to the HOME button prohibited icon */ int banIconSwitch = OFF; /* HOME button prohibited icon */ s8 banIconMode = 0; /* 0: AlphaIn, 1: Pause, 2: AlphaOut */ OSTick banIconTime = 0; u8 banIconAlpha = 0; static TPLPalettePtr sIconTpl; /* RSO module-related */ RSOObjectHeader *staticRso; RSOObjectHeader *moduleA; u32 *buff_static; u8 *bss; /* Controller-related */ static const f32 scStickMoveCoe = 2048.0f/72.0f; /* Amount-of-movement coefficient of the analog stick */ static KPADStatus sKpads[ WPAD_MAX_CONTROLLERS ][ KPAD_MAX_READ_BUFS ]; static Vec2 cursorPos[ WPAD_MAX_CONTROLLERS ]; /* Functions and variables we want to access */ int (*HomebuttonMain)(); void (*InitHomebutton)(); void (*EndHomebutton)(); void (*getCursorPos)( int no, Vec2 *result ); void (*setCursorPos)( int no, Vec2 result ); void (*setAllocator)(MEMAllocator* allocator); void (*setSoundCallback)(HBMSoundCallback callback); void (*setWideMode)( int mode ); static RSOExportFuncTable exp_tbl[] = { {"HomebuttonMain", (u32 *)&HomebuttonMain}, {"InitHomebutton", (u32 *)&InitHomebutton}, {"EndHomebutton", (u32 *)&EndHomebutton}, {"getCursorPos", (u32 *)&getCursorPos}, {"setCursorPos", (u32 *)&setCursorPos}, {"setAllocator", (u32 *)&setAllocator}, {"setSoundCallback", (u32 *)&setSoundCallback}, {"setWideMode", (u32 *)&setWideMode} }; static void* ReadDvdFile( const char* fileName, MEMAllocator* mem); static RSOObjectHeader* RsoLoad(char* moduleName); static RSOObjectHeader* StaticRsoLoad(char* moduleName); static void RSOResolvedModuleA(const RSOObjectHeader* module); static void RSOUnresolvedModuleA(void); static void CreateBanIcon(); // MEM2 memory allocation routines. The application must provide these to // WPAD, so it can set up the data transfer buffer. This buffer must reside // in MEM2. static void *allocMem1 (u32 size); static u8 freeMem1 (void *ptr); static void *allocMem2 (u32 size); static u8 freeMem2 (void *ptr); /* Projection settings */ static void SetProjection( int wideflag ); /* Absolute value clamp */ static f32 AbsClamp( f32 val, f32 max ); /* Cursor movement processing when using +Control key */ static int calcDigitalCursorPos( u32 button, Vec2* pos ); /* Get controller status */ static void GetControllerStatus(int no, KPADStatus* kpad); /* */ static void InitGX(); // Reset/Power Callback int reset_called = FALSE; int power_called = FALSE; static void ResetCallback(); static void PowerCallback(); static void InitRSOModule(); static void EndRSOModule(); static MEMAllocator s_mem1Allocator; static MEMHeapHandle sMemHandle1; static MEMAllocator s_mem2Allocator; static MEMHeapHandle sMemHandle2; /*===========================================================================* * F U N C T I O N D E F I N I T I O N S *===========================================================================*/ /*---------------------------------------------------------------------------* RsoLinkJump *---------------------------------------------------------------------------*/ // static u32 *makeCodeMem2(RSOObjectHeader *i_rso) { int a_size = RSOGetJumpCodeSize(i_rso); void *r_buff; if(a_size == 0) return NULL; r_buff = (void *)allocMem2((unsigned long)a_size); // RSOMakeJumpCode(i_rso,r_buff); // return (u32 *)r_buff; } /* Creation of the "Prohibited" icon resource */ static void CreateBanIcon() { #ifdef BTN_NUM_3 char dirName[] = "hbm/HomeButton3"; #else char dirName[] = "hbm/HomeButton2"; #endif char nameBuf[32]; /* Load icon */ strcpy( nameBuf, dirName ); strcat( nameBuf, "/homeBtnIcon.tpl" ); sIconTpl = ( TPLPalettePtr )ReadDvdFile( nameBuf, &s_mem2Allocator ); TPLBind( sIconTpl ); } /* Render the "Prohibited" icon */ static void DrawBanIcon( u8 alpha ) { GXTexObj texObj; Mtx view_mtx ; // mtx MTXIdentity( view_mtx ) ; GXLoadPosMtxImm( view_mtx, GX_PNMTX1 ) ; GXSetCurrentMtx( GX_PNMTX1 ) ; GXClearVtxDesc(); GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_POS, GX_POS_XY, GX_S16, 0); GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetNumChans(1); GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); GXSetNumTexGens(1); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); GXSetNumTevStages(1); GXSetTevColor(GX_TEVREG0, (GXColor){255, 255, 255, alpha}); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC); GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO); GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE); TPLGetGXTexObjFromPalette( sIconTpl, &texObj, 0 ); GXLoadTexObj( &texObj, GX_TEXMAP0 ); /* The rendering position may be anywhere inside the safe frame. */ GXBegin( GX_QUADS, GX_VTXFMT5, 4 ); GXPosition2s16( -256 + 0, 188 - 56 ); GXTexCoord2s16( 0, 1 ); GXPosition2s16( -256 + 0, 188 + 0 ); GXTexCoord2s16( 0, 0 ); GXPosition2s16( -256 + 56, 188 + 0 ); GXTexCoord2s16( 1, 0 ); GXPosition2s16( -256 + 56, 188 - 56 ); GXTexCoord2s16( 1, 1 ); GXEnd(); } static void InitRSOModule() { /* Load static rso file */ OSReport("Loading static rso...\n"); staticRso = StaticRsoLoad(STATIC_RSO); if (!staticRso) return; // Create relay code buff_static = makeCodeMem2(staticRso); /* Load and link module A */ OSReport("Linking module A...\n"); moduleA = RsoLoad(MODULE_A); if (!moduleA) { return; } // Memory status after the Home Menu RSO exits OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem1Allocator.pHeap) ); OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem2Allocator.pHeap) ); // Use relay code to link RSOLinkJump(moduleA,staticRso,buff_static); /* Check whether everything has been resolved */ if (RSOIsImportSymbolResolvedAll(moduleA)) { OSReport("moduleA's ImportSymbol is resolved all.\n"); } OSReport("\nA prolog()\n"); ((u32 (*)(void)) moduleA->prolog)(); RSOResolvedModuleA(moduleA); } static void EndRSOModule() { OSReport("\nA epilog()\n"); ((u32 (*)(void)) moduleA->epilog)(); RSOUnresolvedModuleA(); // Unlink module A RSOUnLinkList(moduleA); freeMem1( (void*)staticRso ); freeMem2( (void*)moduleA ); freeMem2( (void*)buff_static ); freeMem2( (void*)bss ); OSReport("\nRSOLink finish all!\n"); } static void init_memory1(void) { void *lo = OSAllocFromArenaHi( 20 * 1024 * 1024, 32 ) ; void *hi = OSGetMEM1ArenaHi(); sMemHandle1 = MEMCreateExpHeap(lo,(u32)(hi) - (u32)(lo)); if ( sMemHandle1 == MEM_HEAP_INVALID_HANDLE ) { OSHalt("MEM1 heap allocation error.\n"); } else { OSSetMEM1ArenaLo(hi); MEMInitAllocatorForExpHeap(&s_mem1Allocator, sMemHandle1, 32); } } static void init_memory2(void) { void *lo = OSGetMEM2ArenaLo(); void *hi = OSGetMEM2ArenaHi(); sMemHandle2 = MEMCreateExpHeap(lo, reinterpret_cast(hi) - reinterpret_cast(lo)); if ( sMemHandle2 == MEM_HEAP_INVALID_HANDLE ) { OSHalt("MEM2 heap allocation error.\n"); } else { OSSetMEM2ArenaLo(hi); MEMInitAllocatorForExpHeap(&s_mem2Allocator, sMemHandle2, 32); } } /*---------------------------------------------------------------------------* * Name : main() * Description : * Arguments : None. * Returns : None. *---------------------------------------------------------------------------*/ int main( void ) { Mtx mv; s32 homebutton = 0; KPADStatus kpad_status[WPAD_MAX_CONTROLLERS]; Vec2 pos[WPAD_MAX_CONTROLLERS]; Vec2 posAdjust = { 1.0f, 1.0f }; GXRenderModeObj* pRm; int Homebutton = OFF; int i; int drawModeFlag = 0; // get heap !! { void* arenaHi = OSGetArenaHi(); void* arenaLo = OSAllocFromArenaHi( 21 * 1024 * 1024, 32 ) ; sMemHandle1 = MEMCreateExpHeap(arenaLo, (u32)(arenaHi) - (u32)(arenaLo)); MEMInitAllocatorForExpHeap(&s_mem1Allocator, sMemHandle1, 32); } init_memory2() ; OSInit(); VIInit(); switch (VIGetTvFormat()) { case VI_NTSC: sTvmode = 0; break; case VI_PAL: sTvmode = 1; break; default: OSHalt("VIGetTvFormat(): invalid TV format\n"); break; } DEMOInit(&sRMObj[sTvmode]); SCInit(); while ( SC_STATUS_OK != SCCheckStatus() ) {} /* Wait for completion of SCInit() */ DVDInit(); /* Necessary for the layout editor */ OSInitFastCast(); #ifdef ENABLE_BALANCE_BOARD WPADRegisterBLCWorkarea( workarea ); #endif // ENABLE_BALANCE_BOARD /* Specify the WPAD memory allocation and deallocation functions */ WPADRegisterAllocator(allocMem2, freeMem2); /* KPAD initialization */ KPADInit(); /* Set correction processing of the sensor bar's placement position to ON. */ for( i = 0; i < WPAD_MAX_CONTROLLERS; i++ ) { KPADEnableAimingMode( i ); } /* Get the viewport's status */ pRm = DEMOGetRenderModeObj(); /* Set callback functions */ OSSetResetCallback(ResetCallback); OSSetPowerCallback(PowerCallback); /* Creation of the Home Menu Prohibited icon resource */ CreateBanIcon(); /* Matrix settings */ MTXIdentity(mv); GXLoadPosMtxImm(mv, GX_PNMTX1); /* Projection matrix settings */ SetProjection( drawModeFlag ); /* Display the operation method on the console */ OSReport( "------------------------------\n" ); OSReport( "HOME Button Menu Rso Sample\n\n" ); OSReport( "+ : Show Icon\n" ); OSReport( "2 : Switch Video Mode\n" ); OSReport( "------------------------------\n" ); OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem1Allocator.pHeap) ); OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem2Allocator.pHeap) ); /* Main loop */ while(1) { /* Home Menu is starting */ if( Homebutton ) { int homebuttonprocess; /* Execute the homebutton processing function within the rso module */ homebuttonprocess = HomebuttonMain(); /* Home Menu close */ if( homebuttonprocess == HOMEBUTTON_END ) { int i; for(i = 0; i < WPAD_MAX_CONTROLLERS; i++) { /* Get the cursor position that was changed in the Home Menu */ getCursorPos( i, &cursorPos[i] ); } // RSOModule close EndRSOModule(); Homebutton = OFF; // Memory status after the Home Menu RSO exits OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem1Allocator.pHeap) ); OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem2Allocator.pHeap) ); } } /* Home Menu is not active (this includes rendering of the Home Menu Prohibited icon) */ else { int i; for(i = 0; i < WPAD_MAX_CONTROLLERS; i++) { GetControllerStatus( i, &kpad_status[i] ); /* Start the Home Menu */ /* When HOME is pressed on the Wii Remote or Classic Controller */ if ( (kpad_status[i].trig == KPAD_BUTTON_HOME || kpad_status[i].ex_status.cl.trig==KPAD_CL_BUTTON_HOME) && !banIconSwitch ) { int j; Vec2 result; // Load the RSOModule InitRSOModule(); /* Set the allocator */ setAllocator( &s_mem2Allocator ); /* Set the rendering settings*/ setWideMode( drawModeFlag ); getCursorPos(0,&result); // Start the Home Menu InitHomebutton(); for(j = 0; j < WPAD_MAX_CONTROLLERS; j++) { /* Set the current cursor position in the Home Menu */ setCursorPos( j, cursorPos[j] ); } Homebutton = ON; // Memory status after the Home Menu RSO and materials for the Home Menu have been loaded OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem1Allocator.pHeap) ); OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem2Allocator.pHeap) ); } if( kpad_status[i].trig == KPAD_BUTTON_1 ) { VISetBlack(FALSE); VIFlush(); } /* Change the rendering mode */ if( kpad_status[i].trig == KPAD_BUTTON_2 ) { /* Change the wide-screen flag */ drawModeFlag = !drawModeFlag; /* Applicable to hbm */ setWideMode( drawModeFlag ); /* Re-set the projection matrix */ SetProjection( drawModeFlag ); /* Get viewport information */ pRm = DEMOGetRenderModeObj(); /* Adjust the pointer's position in accordance with the screen's aspect ratio. */ if( drawModeFlag ) { /* 4:3 */ posAdjust.x = 1.0f; posAdjust.y = 1.0f; } else { /* 16:9 */ posAdjust.x = 832.f / 608.f; posAdjust.y = 1.0f; } } /* HOME button prohibited icon */ if ( kpad_status[i].trig == KPAD_BUTTON_PLUS && !banIconSwitch ) { /* Initialize the values that will be used to control the icon's alpha value */ banIconMode = eAlphaInIcon; banIconTime = OSGetTick(); banIconAlpha = 0; banIconSwitch = ON; } } /* Begin rendering */ DEMOBeforeRender(); InitGX(); for( i = 0; i < WPAD_MAX_CONTROLLERS; i++) { u32 type; s32 result = WPADProbe( i, &type ); if ( result == WPAD_ERR_NONE && type != WPAD_DEV_NOT_FOUND ) { /* Determine the Wii pointer position */ pos[i].x = kpad_status[i].pos.x; pos[i].y = kpad_status[i].pos.y; pos[i].x *= pRm->fbWidth * 0.5f; pos[i].y *= pRm->xfbHeight * 0.5f; pos[i].x *= posAdjust.x; pos[i].y *= posAdjust.y; /* Render the Wii Pointer */ GXBegin( GX_QUADS, GX_VTXFMT4, 4 ); GXPosition2f32( -10 + pos[i].x, -10 - pos[i].y ); GXColor3u8( 255, 255, 255 ); GXPosition2f32( -10 + pos[i].x, 10 - pos[i].y ); GXColor3u8( 255, 255, 255 ); GXPosition2f32( 10 + pos[i].x, 10 - pos[i].y ); GXColor3u8( 255, 255, 255 ); GXPosition2f32( 10 + pos[i].x, -10 - pos[i].y ); GXColor3u8( 255, 255, 255 ); GXEnd(); } } /* Render the HOME Menu prohibited icon */ if ( banIconSwitch ) { f32 elapse = OSTicksToMilliseconds( OSDiffTick( OSGetTick(), banIconTime ) ); switch ( banIconMode ) { case eAlphaInIcon: /* AlphaIn (250ms) */ banIconAlpha = ( u8 )( 255.9f * ( elapse / 250.f ) ); if ( elapse >= 250.f ) { banIconTime = OSGetTick(); banIconMode = ePauseIcon; banIconAlpha = 255; } break; case ePauseIcon: /* Pause (1000ms) */ if ( elapse >= 1000.f ) { banIconTime = OSGetTick(); banIconMode = eAlphaOutIcon; } break; case eAlphaOutIcon: /* AlphaOut (250ms) */ banIconAlpha = ( u8 )( 255.9f * ( ( 250.f - elapse ) / 250.f ) ); if ( elapse >= 250.f ) { banIconAlpha = 0; banIconSwitch = OFF; } break; } DrawBanIcon( banIconAlpha ); } /* Rendering ended */ DEMODoneRender(); } /* Reset/Power Callback */ if( reset_called == TRUE ) { OSRestart( 0 ); } if( power_called == TRUE ) { OSReturnToMenu(); } } return 0; } /*---------------------------------------------------------------------------* * Name : allocMem1() * Description : Callback needed by WPAD to allocate mem from MEM2 heap. * Arguments : size of block, in bytes. * Returns : pointer to allocated block. *---------------------------------------------------------------------------*/ static void *allocMem1(u32 size) { void *ptr; ptr = MEMAllocFromAllocator(&s_mem1Allocator, size); ASSERTMSG(ptr, "Memory allocation failed\n"); return(ptr); } /*---------------------------------------------------------------------------* * Name : freeMem1() * Description : Callback needed by WPAD to free mem from MEM2 heap. * Arguments : None. * Returns : Always 1. *---------------------------------------------------------------------------*/ static u8 freeMem1(void *ptr) { MEMFreeToAllocator(&s_mem1Allocator, ptr); // we should ensure that memory is free'd properly, but oh well return(1); } /*---------------------------------------------------------------------------* * Name : allocMem2() * Description : Callback needed by WPAD to allocate mem from MEM2 heap. * Arguments : size of block, in bytes. * Returns : pointer to allocated block. *---------------------------------------------------------------------------*/ static void *allocMem2(u32 size) { void *ptr; ptr = MEMAllocFromAllocator(&s_mem2Allocator, size); ASSERTMSG(ptr, "Memory allocation failed\n"); return(ptr); } /*---------------------------------------------------------------------------* * Name : freeMem2() * Description : Callback needed by WPAD to free mem from MEM2 heap. * Arguments : None. * Returns : Always 1. *---------------------------------------------------------------------------*/ static u8 freeMem2(void *ptr) { MEMFreeToAllocator(&s_mem2Allocator, ptr); // we should ensure that memory is free'd properly, but oh well return(1); } /* Load file */ static void* ReadDvdFile( const char* fileName, MEMAllocator* mem ) { u32 fileLen, fileLenUp32; void* readBuf; s32 readBytes; DVDFileInfo fileInfo; if (! DVDOpen(fileName, &fileInfo)) { return NULL; } fileLen = DVDGetLength(&fileInfo); if( (fileLen % 32) != 0 ) { fileLenUp32 = fileLen + (32 - (fileLen % 32)); } else { fileLenUp32 = fileLen; } readBuf = MEMAllocFromAllocator(mem, fileLenUp32); readBytes = DVDRead(&fileInfo, readBuf, (s32)(fileLenUp32), 0); ASSERT(readBytes > 0); DVDClose(&fileInfo); return readBuf; } /*---------------------------------------------------------------------------* Name: RsoLoad Description: Loads and then links an RSO module. Arguments: None. Returns: *---------------------------------------------------------------------------*/ static RSOObjectHeader* RsoLoad(char* moduleName) { RSOObjectHeader* module; module = (RSOObjectHeader*)ReadDvdFile(moduleName, &s_mem2Allocator); if (module->bssSize > 0) { bss = (u8*)allocMem2( module->bssSize ); } RSOLinkList(module, bss); return module; } /*---------------------------------------------------------------------------* Name: StaticRsoLoad Description: Loads and then links a static module. Arguments: None. Returns: *---------------------------------------------------------------------------*/ static RSOObjectHeader* StaticRsoLoad(char* moduleName) { RSOObjectHeader* module; module = (RSOObjectHeader*)ReadDvdFile(moduleName, &s_mem1Allocator); RSOListInit(module); return module; } /*---------------------------------------------------------------------------* Name: _unresolved Description: Called when the link to a function that is referenced from a static module has not been resolved. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ __declspec(export) void _unresolved() { OSReport("_unresolved func.\n"); } /*---------------------------------------------------------------------------* Name: RSOResolvedModuleA Description: Resolves references to RSO module A. Arguments: None. Returns: *---------------------------------------------------------------------------*/ static void RSOResolvedModuleA(const RSOObjectHeader* module) { int i; for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) { if(RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name) == NULL) { OSReport("-----> unresolved %s\n", exp_tbl[i].symbol_name); } else { OSReport("=====> resolved %s\n", exp_tbl[i].symbol_name); OSReport(" addr = %X\n", RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name)); } *(exp_tbl[i].symbol_ptr) = (u32)RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name); } } /*---------------------------------------------------------------------------* Name: RSOUnresolvedModuleA Description: Invalidates references to RSO module A. Arguments: None. Returns: *---------------------------------------------------------------------------*/ static void RSOUnresolvedModuleA(void) { int i; for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) { *(exp_tbl[i].symbol_ptr) = (u32)_unresolved; } } /* Projection settings */ static void SetProjection( int wideflag ) { Mtx44 projMtx; if( !wideflag ) { DEMOReInit(&sRMObj[sTvmode]); f32 viRateX = sRMObj[sTvmode].viWidth / 670.f; f32 viRateY = sRMObj[sTvmode].viHeight / 456.f; MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 304.0f, viRateX * 304.0f, 0.0f, 500.0f); } else { DEMOReInit(&sRMObjWide[sTvmode]); f32 viRateX = sRMObjWide[sTvmode].viWidth / 686.f; f32 viRateY = sRMObjWide[sTvmode].viHeight / 456.f; MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 437.0f, viRateX * 437.0f, 0.0f, 500.0f); } GXSetProjection(projMtx, GX_ORTHOGRAPHIC); } /* Absolute value clamp */ static f32 AbsClamp( f32 val, f32 max ) { return ( ( val > max ) ? max : ( val < -max ) ? -max : val ); } /* Cursor movement processing for analog stick */ static int calcAnalogCursorPos( f32 stickX, f32 stickY, Vec2* pos ) { f32 x,y; x = ( stickX / scStickMoveCoe ); y = ( stickY / scStickMoveCoe ); x = AbsClamp( x, 1.0f ); y = AbsClamp( y, 1.0f ); if( x == 0.0f && y == 0.0f ) return FALSE; pos->x = AbsClamp( pos->x + x, 1.0f ); pos->y = AbsClamp( pos->y - y, 1.0f ); return TRUE; } /* Cursor movement processing when using +Control key */ static int calcDigitalCursorPos( u32 button, Vec2* pos ) { const float spd =1.0f / scStickMoveCoe; const float spd2= spd * 0.7071f; button&=KPAD_CL_BUTTON_UP|KPAD_CL_BUTTON_LEFT|KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT; switch (button) { case KPAD_CL_BUTTON_UP: pos->y-=spd; break; case KPAD_CL_BUTTON_LEFT: pos->x-=spd; break; case KPAD_CL_BUTTON_DOWN: pos->y+=spd; break; case KPAD_CL_BUTTON_RIGHT: pos->x+=spd; break; case KPAD_CL_BUTTON_UP |KPAD_CL_BUTTON_LEFT: pos->y-=spd2; pos->x-=spd2; break; case KPAD_CL_BUTTON_UP |KPAD_CL_BUTTON_RIGHT: pos->y-=spd2; pos->x+=spd2; break; case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_LEFT: pos->y+=spd2; pos->x-=spd2; break; case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT: pos->y+=spd2; pos->x+=spd2; break; default: return FALSE; } pos->x = AbsClamp( pos->x, 1.0f ); pos->y = AbsClamp( pos->y, 1.0f ); return TRUE; } static void GetControllerStatus(int no, KPADStatus* kpad) { int input_classic; s32 wpad_result; s32 kpad_result; u32 pad_type; wpad_result = WPADProbe( no, &pad_type ); kpad_result = KPADRead( no, &sKpads[no][0], KPAD_MAX_READ_BUFS ); if ( kpad_result == 0 ) memset(&sKpads[no][0], 0, sizeof(KPADStatus)); switch( wpad_result ) { /* In the following error states, the value gotten by KPADRead is applied as-is. */ case WPAD_ERR_BUSY: case WPAD_ERR_TRANSFER: case WPAD_ERR_INVALID: case WPAD_ERR_CORRUPTED: case WPAD_ERR_NONE: *kpad = sKpads[no][0]; kpad->horizon.x = sKpads[no][0].horizon.x; kpad->horizon.y = sKpads[no][0].horizon.y; { /* According to guidelines, if there is input from a Classic Controller, that input is prioritized and inherits DPD coordinates. Specify the DPD absolute coordinates when there is no Classic Controller input. */ input_classic = calcDigitalCursorPos( kpad->ex_status.cl.hold, &cursorPos[no] ); input_classic = input_classic | calcAnalogCursorPos( kpad->ex_status.cl.lstick.x, kpad->ex_status.cl.lstick.y, &cursorPos[no] ); if( !input_classic && kpad->dpd_valid_fg > 0) { cursorPos[no].x = kpad->pos.x; cursorPos[no].y = kpad->pos.y; } kpad->pos.x = cursorPos[no].x; kpad->pos.y = cursorPos[no].y; } break; /* Apply NULL in the following error states. */ case WPAD_ERR_NO_CONTROLLER: default: kpad = NULL; break; } } /* Initialize GX */ static void InitGX() { GXClearVtxDesc(); GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_POS, GX_POS_XY, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGB, GX_RGB8, 0); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); GXSetNumChans(1); GXSetNumTexGens(0); GXSetNumTevStages(1); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR); GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); GXSetCurrentMtx( GX_PNMTX1 ); } static void ResetCallback() { reset_called = TRUE; } static void PowerCallback() { power_called = TRUE; }