1 /*---------------------------------------------------------------------------*
2   Project:  rsodemo
3   File:     rsodemo.cpp
4 
5   Copyright 2006-2009 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 
14 #include <stdlib.h>
15 #include <string.h>
16 #include <stddef.h>
17 #include <stdarg.h>
18 #include <stdio.h>
19 #include <ctype.h>
20 
21 #include <revolution.h>
22 #include <revolution/kpad.h>
23 #include <revolution/sc.h>
24 
25 // RSO Module
26 #include <revolution/rso.h>
27 #include <revolution/RSOLink.h>
28 #include <revolution/mem.h>
29 
30 // HBM
31 #include <revolution/hbm.h>
32 
33 #include <demo.h>
34 
35 // RSO ModuleName
36 #ifdef NDEBUG
37     #define MODULE_A     "hbmdemo/rsomodule.rso"
38     #define STATIC_RSO   "hbmdemo/rsodemo.sel"
39 #else
40     #define MODULE_A     "hbmdemo/rsomoduleD.rso"
41     #define STATIC_RSO   "hbmdemo/rsodemoD.sel"
42 #endif
43 
44 void _unresolved();
45 
46 #define HOMEBUTTON_NOERROR 0
47 #define HOMEBUTTON_ICON 1
48 #define HOMEBUTTON_ALIVE 2
49 #define HOMEBUTTON_END 3
50 
51 enum
52 {
53     OFF = 0,
54     ON
55 };
56 
57 enum
58 {
59     eAlphaInIcon = 0,
60     ePauseIcon,
61     eAlphaOutIcon
62 };
63 
64 // NTSC / PAL
65 int sTvmode;
66 
67 // Frame buffer size
68 static const u16 sFbWidth = 608;
69 static const u16 sFbHeight = 456;
70 
71 // VI size
72 static const u16 viWidth = 670;
73 static const u16 viWidthWide = 686;
74 static const u16 viWidthWide_Pal = 682;
75 
76 static const u16 viHeight = 456;
77 static const u16 viHeight_Pal = 542;
78 
79 #ifdef  ENABLE_BALANCE_BOARD
80 static u8  workarea[WPAD_BLCINT_WORK_LEN] ATTRIBUTE_ALIGN(32);
81 #endif // ENABLE_BALANCE_BOARD
82 /* RenderMode */
83 static GXRenderModeObj sRMObj[2] =
84 {
85     /* NTSC 4:3 */
86     {
87         VI_TVMODE_NTSC_INT,
88         sFbWidth,
89         sFbHeight,
90         viHeight,
91         (u16)((VI_MAX_WIDTH_NTSC - viWidth)/2),
92         (u16)((VI_MAX_HEIGHT_NTSC - viHeight)/2),
93         viWidth,
94         viHeight,
95         VI_XFBMODE_DF,
96         GX_FALSE,
97         GX_FALSE,
98         6, 6, 6, 6, 6, 6,
99         6, 6, 6, 6, 6, 6,
100         6, 6, 6, 6, 6, 6,
101         6, 6, 6, 6, 6, 6,
102         8, 8,
103         10, 12, 10,
104         8, 8,
105     },
106     /* PAL 4:3 */
107     {
108         VI_TVMODE_PAL_INT,
109         sFbWidth,
110         sFbHeight,
111         viHeight_Pal,
112         (u16)((VI_MAX_WIDTH_PAL - viWidth)/2),
113         (u16)((VI_MAX_HEIGHT_PAL - viHeight_Pal)/2),
114         viWidth,
115         viHeight_Pal,
116         VI_XFBMODE_DF,
117         GX_FALSE,
118         GX_FALSE,
119         6, 6, 6, 6, 6, 6,
120         6, 6, 6, 6, 6, 6,
121         6, 6, 6, 6, 6, 6,
122         6, 6, 6, 6, 6, 6,
123         8, 8,
124         10, 12, 10,
125         8, 8,
126     }
127 };
128 
129 static GXRenderModeObj sRMObjWide[2] =
130 {
131     /* NTSC 16:9 */
132     {
133         VI_TVMODE_NTSC_INT,
134         sFbWidth,
135         sFbHeight,
136         viHeight,
137         (u16)((VI_MAX_WIDTH_NTSC - viWidthWide)/2),
138         (u16)((VI_MAX_HEIGHT_NTSC - viHeight)/2),
139         viWidthWide,
140         viHeight,
141         VI_XFBMODE_DF,
142         GX_FALSE,
143         GX_FALSE,
144         6, 6, 6, 6, 6, 6,
145         6, 6, 6, 6, 6, 6,
146         6, 6, 6, 6, 6, 6,
147         6, 6, 6, 6, 6, 6,
148         8, 8,
149         10, 12, 10,
150         8, 8,
151     },
152     /* PAL 16:9 */
153     {
154         VI_TVMODE_PAL_INT,
155         sFbWidth,
156         sFbHeight,
157         viHeight_Pal,
158         (u16)((VI_MAX_WIDTH_PAL - viWidthWide_Pal)/2),
159         (u16)((VI_MAX_HEIGHT_PAL - viHeight_Pal)/2),
160         viWidthWide_Pal,
161         viHeight_Pal,
162         VI_XFBMODE_DF,
163         GX_FALSE,
164         GX_FALSE,
165         6, 6, 6, 6, 6, 6,
166         6, 6, 6, 6, 6, 6,
167         6, 6, 6, 6, 6, 6,
168         6, 6, 6, 6, 6, 6,
169         8, 8,
170         10, 12, 10,
171         8, 8,
172     }
173 };
174 
175 // ICON
176 /* Related to the HOME button prohibited icon */
177 int banIconSwitch  = OFF;   /* HOME button prohibited icon */
178 s8  banIconMode    = 0;     /* 0: AlphaIn, 1: Pause, 2: AlphaOut */
179 OSTick banIconTime = 0;
180 u8  banIconAlpha   = 0;
181 static TPLPalettePtr sIconTpl;
182 
183 /* RSO module-related */
184 RSOObjectHeader *staticRso;
185 RSOObjectHeader *moduleA;
186 u32             *buff_static;
187 u8              *bss;
188 
189 /* Controller-related */
190 static const f32 scStickMoveCoe =  2048.0f/72.0f; /* Amount-of-movement coefficient of the analog stick */
191 static KPADStatus sKpads[ WPAD_MAX_CONTROLLERS ][ KPAD_MAX_READ_BUFS ];
192 static Vec2 cursorPos[ WPAD_MAX_CONTROLLERS ];
193 
194 
195 /* Functions and variables we want to access */
196 int (*HomebuttonMain)();
197 void (*InitHomebutton)();
198 void (*EndHomebutton)();
199 void (*getCursorPos)( int no, Vec2 *result );
200 void (*setCursorPos)( int no, Vec2 result );
201 void (*setAllocator)(MEMAllocator* allocator);
202 void (*setSoundCallback)(HBMSoundCallback callback);
203 void (*setWideMode)( int mode );
204 
205 
206 static RSOExportFuncTable exp_tbl[] =
207 {
208     {"HomebuttonMain",   (u32 *)&HomebuttonMain},
209     {"InitHomebutton",  (u32 *)&InitHomebutton},
210     {"EndHomebutton",  (u32 *)&EndHomebutton},
211     {"getCursorPos",  (u32 *)&getCursorPos},
212     {"setCursorPos",  (u32 *)&setCursorPos},
213     {"setAllocator",  (u32 *)&setAllocator},
214     {"setSoundCallback",  (u32 *)&setSoundCallback},
215     {"setWideMode",  (u32 *)&setWideMode}
216 };
217 
218 
219 static void* ReadDvdFile( const char*     fileName, MEMAllocator*   mem);
220 static RSOObjectHeader* RsoLoad(char* moduleName);
221 static RSOObjectHeader* StaticRsoLoad(char* moduleName);
222 static void RSOResolvedModuleA(const RSOObjectHeader* module);
223 static void RSOUnresolvedModuleA(void);
224 
225 static void CreateBanIcon();
226 
227 // MEM2 memory allocation routines. The application must provide these to
228 // WPAD, so it can setup the data transfer buffer. This buffer must reside
229 // in MEM2.
230 
231 static void *allocMem1                 (u32 size);
232 static u8    freeMem1                  (void *ptr);
233 static void *allocMem2                 (u32 size);
234 static u8    freeMem2                  (void *ptr);
235 
236 /* Projection settings */
237 static void SetProjection( int wideflag );
238 /* Absolute value clamp */
239 static f32 AbsClamp( f32 val, f32 max );
240 /* Cursor movement processing when using +Control key */
241 static int calcDigitalCursorPos( u32 button, Vec2* pos );
242 /* Get controller status */
243 static void GetControllerStatus(int no, KPADStatus* kpad);
244 /* */
245 static void InitGX();
246 
247 // Reset/Power Callback
248 int reset_called = FALSE;
249 int power_called = FALSE;
250 static void ResetCallback();
251 static void PowerCallback();
252 
253 static void InitRSOModule();
254 static void EndRSOModule();
255 
256 
257 static MEMAllocator s_mem1Allocator;
258 static MEMHeapHandle sMemHandle1;
259 
260 static MEMAllocator s_mem2Allocator;
261 static MEMHeapHandle sMemHandle2;
262 
263 
264 /*===========================================================================*
265  *                   F U N C T I O N    D E F I N I T I O N S
266  *===========================================================================*/
267 
268 /*---------------------------------------------------------------------------*
269    RsoLinkJump
270  *---------------------------------------------------------------------------*/
271 //
makeCodeMem1(RSOObjectHeader * i_rso)272 static u32 *makeCodeMem1(RSOObjectHeader *i_rso)
273 {
274     int a_size = RSOGetJumpCodeSize(i_rso);
275     void *r_buff;
276 
277     if(a_size == 0) return NULL;
278     r_buff = (void *)allocMem1((unsigned long)a_size);
279     //
280     RSOMakeJumpCode(i_rso,r_buff);
281     //
282     return (u32 *)r_buff;
283 }
284 
285 /* Creation of the "Prohibited" icon resource */
CreateBanIcon()286 static void CreateBanIcon()
287 {
288 #ifdef BTN_NUM_3
289     char dirName[] = "hbm/HomeButton3";
290 #else
291     char dirName[] = "hbm/HomeButton2";
292 #endif
293 
294     char nameBuf[32];
295     /* Load icon */
296     strcpy( nameBuf, dirName );
297     strcat( nameBuf, "/homeBtnIcon.tpl" );
298     sIconTpl = ( TPLPalettePtr )ReadDvdFile( nameBuf, &s_mem2Allocator );
299     TPLBind( sIconTpl );
300 }
301 
302 /* Render the "Prohibited" icon */
DrawBanIcon(u8 alpha)303 static void DrawBanIcon( u8 alpha )
304 {
305     GXTexObj texObj;
306     Mtx      view_mtx ;
307     // mtx
308     MTXIdentity( view_mtx ) ;
309     GXLoadPosMtxImm( view_mtx, GX_PNMTX1 ) ;
310     GXSetCurrentMtx( GX_PNMTX1 ) ;
311 
312     GXClearVtxDesc();
313 
314     GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_POS,  GX_POS_XY,  GX_S16, 0);
315     GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0);
316     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
317     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
318 
319     GXSetNumChans(1);
320     GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
321 
322     GXSetNumTexGens(1);
323     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
324 
325     GXSetNumTevStages(1);
326     GXSetTevColor(GX_TEVREG0, (GXColor){255, 255, 255, alpha});
327     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
328     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
329     GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
330     GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
331     GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
332 
333     GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
334     GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE);
335 
336     TPLGetGXTexObjFromPalette( sIconTpl, &texObj, 0 );
337     GXLoadTexObj( &texObj, GX_TEXMAP0 );
338 
339     /* The rendering position may be anywhere inside the safe frame. */
340     GXBegin( GX_QUADS, GX_VTXFMT5, 4 );
341     GXPosition2s16( -256 + 0, 188 - 56 );
342     GXTexCoord2s16( 0, 1 );
343     GXPosition2s16( -256 + 0, 188 + 0 );
344     GXTexCoord2s16( 0, 0 );
345     GXPosition2s16( -256 + 56, 188 + 0 );
346     GXTexCoord2s16( 1, 0 );
347     GXPosition2s16( -256 + 56, 188 - 56 );
348     GXTexCoord2s16( 1, 1 );
349     GXEnd();
350 }
351 
InitRSOModule()352 static void InitRSOModule()
353 {
354     /* Load static rso file */
355     OSReport("Loading static rso...\n");
356     staticRso = StaticRsoLoad(STATIC_RSO);
357     if (!staticRso)
358         return;
359     // Create relay code
360     buff_static = makeCodeMem1(staticRso);
361 
362     /* Load and link module A */
363     OSReport("Linking module A...\n");
364     moduleA = RsoLoad(MODULE_A);
365     if (!moduleA)
366     {
367         return;
368     }
369 
370     // Memory status after the Home Menu RSO exits
371     OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem1Allocator.pHeap) );
372     OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem2Allocator.pHeap) );
373 
374     // Use relay code to link
375     RSOLinkJump(moduleA,staticRso,buff_static);
376     /* Check whether everything has been resolved */
377     if (RSOIsImportSymbolResolvedAll(moduleA))
378     {
379         OSReport("moduleA's ImportSymbol is resolved all.\n");
380     }
381     OSReport("\nA prolog()\n");
382     ((u32 (*)(void)) moduleA->prolog)();
383     RSOResolvedModuleA(moduleA);
384 
385 }
386 
EndRSOModule()387 static void EndRSOModule()
388 {
389     OSReport("\nA epilog()\n");
390     ((u32 (*)(void)) moduleA->epilog)();
391     RSOUnresolvedModuleA();
392 
393     // Unlink module A
394     RSOUnLinkList(moduleA);
395 
396     freeMem1( (void*)staticRso );
397     freeMem1( (void*)moduleA );
398     freeMem1( (void*)buff_static );
399     freeMem1( (void*)bss );
400 
401     OSReport("\nRSOLink finish all!\n");
402 
403 }
404 
init_memory1(void)405 static void init_memory1(void)
406 {
407     void *lo = OSAllocFromArenaHi( 20 * 1024 * 1024, 32 ) ;
408     void *hi = OSGetMEM1ArenaHi();
409 
410     sMemHandle1 = MEMCreateExpHeap(lo,(u32)(hi) - (u32)(lo));
411     if ( sMemHandle1 == MEM_HEAP_INVALID_HANDLE )
412     {
413         OSHalt("MEM1 heap allocation error.\n");
414     }
415     else
416     {
417         OSSetMEM1ArenaLo(hi);
418         MEMInitAllocatorForExpHeap(&s_mem1Allocator, sMemHandle1, 32);
419     }
420 }
421 
init_memory2(void)422 static void init_memory2(void)
423 {
424     void *lo = OSGetMEM2ArenaLo();
425     void *hi = OSGetMEM2ArenaHi();
426     sMemHandle2 = MEMCreateExpHeap(lo, reinterpret_cast<u32>(hi) - reinterpret_cast<u32>(lo));
427     if ( sMemHandle2 == MEM_HEAP_INVALID_HANDLE )
428     {
429         OSHalt("MEM2 heap allocation error.\n");
430     }
431     else
432     {
433         OSSetMEM2ArenaLo(hi);
434         MEMInitAllocatorForExpHeap(&s_mem2Allocator, sMemHandle2, 32);
435     }
436 }
437 
438 /*---------------------------------------------------------------------------*
439  * Name        : main()
440  * Description :
441  * Arguments   : None.
442  * Returns     : None.
443  *---------------------------------------------------------------------------*/
main(void)444 int main( void )
445 {
446     Mtx mv;
447     s32 homebutton = 0;
448     KPADStatus kpad_status[WPAD_MAX_CONTROLLERS];
449     Vec2 pos[WPAD_MAX_CONTROLLERS];
450     Vec2 posAdjust = { 1.0f, 1.0f };
451     GXRenderModeObj* pRm;
452     int Homebutton = OFF;
453     int i;
454     int drawModeFlag = 0;
455 
456 
457     // get heap !!
458     {
459         void* arenaHi = OSGetArenaHi();
460         void* arenaLo = OSAllocFromArenaHi( 21 * 1024 * 1024, 32 ) ;
461         sMemHandle1 = MEMCreateExpHeap(arenaLo, (u32)(arenaHi) - (u32)(arenaLo));
462         MEMInitAllocatorForExpHeap(&s_mem1Allocator, sMemHandle1, 32);
463     }
464 
465     init_memory2() ;
466 
467     OSInit();
468     VIInit();
469 
470     switch (VIGetTvFormat())
471     {
472         case VI_NTSC:
473              sTvmode = 0;
474              break;
475         case VI_PAL:
476              sTvmode = 1;
477              break;
478         default:
479              OSHalt("VIGetTvFormat(): invalid TV format\n");
480              break;
481     }
482 
483 
484 
485     DEMOInit(&sRMObj[sTvmode]);
486 
487     SCInit();
488     while ( SC_STATUS_OK != SCCheckStatus() ) {} /* Wait for completion of SCInit() */
489     DVDInit();
490 
491     /* Necessary for the layout editor */
492     OSInitFastCast();
493 
494 #ifdef  ENABLE_BALANCE_BOARD
495     WPADRegisterBLCWorkarea( workarea );
496 #endif // ENABLE_BALANCE_BOARD
497     /* Specify the WPAD memory allocation and deallocation functions */
498     WPADRegisterAllocator(allocMem2, freeMem2);
499 
500     /* KPAD initialization */
501     KPADInit();
502 
503     /* Set correction processing of the sensor bar's placement position to ON. */
504     for( i = 0; i < WPAD_MAX_CONTROLLERS; i++ )
505     {
506         KPADEnableAimingMode( i );
507     }
508 
509     /* Get the viewport's status */
510     pRm = DEMOGetRenderModeObj();
511 
512     /* Set callback functions */
513     OSSetResetCallback(ResetCallback);
514     OSSetPowerCallback(PowerCallback);
515 
516     /* Creation of the Home Menu Prohibited icon resource */
517     CreateBanIcon();
518 
519     /* Matrix settings */
520     MTXIdentity(mv);
521     GXLoadPosMtxImm(mv, GX_PNMTX1);
522 
523     /* Projection matrix settings */
524     SetProjection( drawModeFlag );
525 
526     /* Display the operation method on the console */
527     OSReport( "------------------------------\n" );
528     OSReport( "HOME Button Menu Rso Sample\n\n" );
529     OSReport( "+ : Show Icon\n" );
530     OSReport( "2 : Switch Video Mode\n" );
531     OSReport( "------------------------------\n" );
532 
533     OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem1Allocator.pHeap) );
534     OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem2Allocator.pHeap) );
535 
536     /* Main loop */
537     while(1)
538     {
539         /* Home Menu is starting */
540         if( Homebutton )
541         {
542             int homebuttonprocess;
543             /* Execute the homebutton processing function within the RSO module */
544             homebuttonprocess = HomebuttonMain();
545             /* Home Menu close */
546             if( homebuttonprocess == HOMEBUTTON_END )
547             {
548                 int i;
549                 for(i = 0; i < WPAD_MAX_CONTROLLERS; i++)
550                 {
551                     /* Get the cursor position that was changed in the Home Menu */
552                     getCursorPos( i, &cursorPos[i] );
553                 }
554                 // RSOModule close
555                 EndRSOModule();
556                 Homebutton = OFF;
557 
558                 // Memory status after the Home Menu RSO exits
559                 OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem1Allocator.pHeap) );
560                 OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem2Allocator.pHeap) );
561             }
562         }
563         /* Home Menu is not active (this includes rendering of the Home Menu Prohibited icon) */
564         else
565         {
566             int i;
567             for(i = 0; i < WPAD_MAX_CONTROLLERS; i++)
568             {
569                 GetControllerStatus( i, &kpad_status[i] );
570                 /* Start the Home Menu */
571                 /* When HOME is pressed on the Wii Remote or Classic Controller */
572                 if ( (kpad_status[i].trig == KPAD_BUTTON_HOME ||
573                      kpad_status[i].ex_status.cl.trig==KPAD_CL_BUTTON_HOME)  && !banIconSwitch )
574                 {
575                     int j;
576                     Vec2 result;
577 
578 
579                     // Load the RSOModule
580                     InitRSOModule();
581                     /* Set the allocator */
582                     setAllocator( &s_mem1Allocator );
583 
584                     /* Set the rendering settings*/
585                     setWideMode( drawModeFlag );
586 
587                     getCursorPos(0,&result);
588                     // Start the Home Menu
589                     InitHomebutton();
590                     for(j = 0; j < WPAD_MAX_CONTROLLERS; j++)
591                     {
592                         /* Set the current cursor position in the Home Menu */
593                         setCursorPos( j, cursorPos[j] );
594                     }
595                     Homebutton = ON;
596 
597                     // Memory status after the Home Menu RSO and materials for the Home Menu have been loaded
598                     OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem1Allocator.pHeap) );
599                     OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)s_mem2Allocator.pHeap) );
600                 }
601 
602                 if( kpad_status[i].trig == KPAD_BUTTON_1 )
603                 {
604                     VISetBlack(FALSE);
605                     VIFlush();
606                 }
607 
608                 /* Change the rendering mode */
609                 if( kpad_status[i].trig == KPAD_BUTTON_2 )
610                 {
611                     /* Change the widescreen flag */
612                     drawModeFlag = !drawModeFlag;
613                     /* Reset the projection matrix */
614                     SetProjection( drawModeFlag );
615                     /* Get viewport information */
616                     pRm = DEMOGetRenderModeObj();
617                     /* Adjust the pointer's position in accordance with the screen's aspect ratio. */
618                     if( drawModeFlag )
619                     {
620                         /* 4:3 */
621                         posAdjust.x       = 1.0f;
622                         posAdjust.y       = 1.0f;
623                     }
624                     else
625                     {
626                         /* 16:9 */
627                         posAdjust.x       = 832.f / 608.f;
628                         posAdjust.y       = 1.0f;
629                     }
630                 }
631 
632                 /* HOME button prohibited icon */
633                 if ( kpad_status[i].trig == KPAD_BUTTON_PLUS && !banIconSwitch )
634                 {
635                     /* Initialize the values that will be used to control the icon's alpha value */
636                     banIconMode   = eAlphaInIcon;
637                     banIconTime   = OSGetTick();
638                     banIconAlpha  = 0;
639                     banIconSwitch = ON;
640                 }
641             }
642 
643             /* Begin rendering */
644             DEMOBeforeRender();
645             InitGX();
646 
647             for( i = 0; i < WPAD_MAX_CONTROLLERS; i++)
648             {
649                 u32 type;
650                 s32 result = WPADProbe( i, &type );
651                 if ( result == WPAD_ERR_NONE && type != WPAD_DEV_NOT_FOUND )
652                 {
653                     /* Determine the Wii pointer position */
654                     pos[i].x = kpad_status[i].pos.x;
655                     pos[i].y = kpad_status[i].pos.y;
656                     pos[i].x *= pRm->fbWidth * 0.5f;
657                     pos[i].y *= pRm->xfbHeight * 0.5f;
658                     pos[i].x *= posAdjust.x;
659                     pos[i].y *= posAdjust.y;
660 
661                     /* Render the Wii Pointer */
662                     GXBegin( GX_QUADS, GX_VTXFMT4, 4 );
663                     GXPosition2f32( -10 + pos[i].x, -10 - pos[i].y );
664                     GXColor3u8( 255, 255, 255 );
665                     GXPosition2f32( -10 + pos[i].x,  10 - pos[i].y );
666                     GXColor3u8( 255, 255, 255 );
667                     GXPosition2f32(  10 + pos[i].x,  10 - pos[i].y );
668                     GXColor3u8( 255, 255, 255 );
669                     GXPosition2f32(  10 + pos[i].x, -10 - pos[i].y );
670                     GXColor3u8( 255, 255, 255 );
671                     GXEnd();
672                 }
673             }
674 
675             /* Render the HOME Menu prohibited icon */
676             if ( banIconSwitch )
677             {
678                 f32 elapse = OSTicksToMilliseconds( OSDiffTick( OSGetTick(), banIconTime ) );
679 
680                 switch ( banIconMode )
681                 {
682                     case eAlphaInIcon: /* AlphaIn (250ms) */
683                     banIconAlpha = ( u8 )( 255.9f * ( elapse / 250.f ) );
684                     if ( elapse >= 250.f )
685                     {
686                         banIconTime  = OSGetTick();
687                         banIconMode  = ePauseIcon;
688                         banIconAlpha = 255;
689                     }
690                     break;
691                     case ePauseIcon: /* Pause (1000ms) */
692                         if ( elapse >= 1000.f )
693                         {
694                             banIconTime = OSGetTick();
695                             banIconMode = eAlphaOutIcon;
696                         }
697                         break;
698                     case eAlphaOutIcon: /* AlphaOut (250ms) */
699                         banIconAlpha = ( u8 )( 255.9f * ( ( 250.f - elapse ) / 250.f ) );
700                         if ( elapse >= 250.f )
701                         {
702                             banIconAlpha  = 0;
703                             banIconSwitch = OFF;
704                         }
705                         break;
706                 }
707                 DrawBanIcon( banIconAlpha );
708             }
709 
710             /* Rendering ended */
711             DEMODoneRender();
712         }
713 
714         /* Reset/Power Callback */
715         if( reset_called == TRUE )
716         {
717             OSRestart( 0 );
718         }
719         if( power_called == TRUE )
720         {
721             OSReturnToMenu();
722         }
723     }
724 
725     return 0;
726 }
727 
728 /*---------------------------------------------------------------------------*
729  * Name        : allocMem1()
730  * Description : Callback needed by WPAD to allocate mem from MEM2 heap.
731  * Arguments   : size of block, in bytes.
732  * Returns     : pointer to allocated block.
733  *---------------------------------------------------------------------------*/
allocMem1(u32 size)734 static void *allocMem1(u32 size)
735 {
736     void *ptr;
737 
738     ptr = MEMAllocFromAllocator(&s_mem1Allocator, size);
739     ASSERTMSG(ptr, "Memory allocation failed\n");
740 
741     return(ptr);
742 
743 }
744 
745 /*---------------------------------------------------------------------------*
746  * Name        : freeMem1()
747  * Description : Callback needed by WPAD to free mem from MEM2 heap.
748  * Arguments   : None.
749  * Returns     : Always 1.
750  *---------------------------------------------------------------------------*/
freeMem1(void * ptr)751 static u8 freeMem1(void *ptr)
752 {
753 
754     MEMFreeToAllocator(&s_mem1Allocator, ptr);
755 
756     // we should ensure that memory is free'd properly, but oh well
757     return(1);
758 
759 }
760 
761 /*---------------------------------------------------------------------------*
762  * Name        : allocMem2()
763  * Description : Callback needed by WPAD to allocate mem from MEM2 heap.
764  * Arguments   : size of block, in bytes.
765  * Returns     : pointer to allocated block.
766  *---------------------------------------------------------------------------*/
allocMem2(u32 size)767 static void *allocMem2(u32 size)
768 {
769     void *ptr;
770 
771     ptr = MEMAllocFromAllocator(&s_mem2Allocator, size);
772     ASSERTMSG(ptr, "Memory allocation failed\n");
773 
774     return(ptr);
775 
776 }
777 
778 /*---------------------------------------------------------------------------*
779  * Name        : freeMem2()
780  * Description : Callback needed by WPAD to free mem from MEM2 heap.
781  * Arguments   : None.
782  * Returns     : Always 1.
783  *---------------------------------------------------------------------------*/
freeMem2(void * ptr)784 static u8 freeMem2(void *ptr)
785 {
786 
787     MEMFreeToAllocator(&s_mem2Allocator, ptr);
788 
789     // we should ensure that memory is free'd properly, but oh well
790     return(1);
791 
792 }
793 
794 /* Load file */
ReadDvdFile(const char * fileName,MEMAllocator * mem)795 static void* ReadDvdFile(
796     const char*     fileName,
797     MEMAllocator*   mem
798 )
799 {
800     u32 fileLen, fileLenUp32;
801     void* readBuf;
802     s32 readBytes;
803 
804     DVDFileInfo fileInfo;
805     if (! DVDOpen(fileName, &fileInfo))
806     {
807         return NULL;
808     }
809 
810     fileLen     = DVDGetLength(&fileInfo);
811     if( (fileLen % 32) != 0 )
812     {
813         fileLenUp32 = fileLen + (32 - (fileLen % 32));
814     }
815     else
816     {
817         fileLenUp32 = fileLen;
818     }
819     readBuf = MEMAllocFromAllocator(mem, fileLenUp32);
820     readBytes = DVDRead(&fileInfo, readBuf, (s32)(fileLenUp32), 0);
821     ASSERT(readBytes > 0);
822     DVDClose(&fileInfo);
823 
824     return readBuf;
825 }
826 
827 /*---------------------------------------------------------------------------*
828   Name:         RsoLoad
829 
830   Description:  Loads and then links an RSO module.
831 
832   Arguments:    None.
833 
834   Returns:
835 
836  *---------------------------------------------------------------------------*/
837 
838 static RSOObjectHeader*
RsoLoad(char * moduleName)839 RsoLoad(char* moduleName)
840 {
841     RSOObjectHeader* module;
842 
843     module = (RSOObjectHeader*)ReadDvdFile(moduleName, &s_mem1Allocator);
844     if (module->bssSize > 0)
845     {
846         bss = (u8*)allocMem1( module->bssSize );
847     }
848 
849     RSOLinkList(module, bss);
850 
851     return module;
852 }
853 
854 
855 /*---------------------------------------------------------------------------*
856   Name:         StaticRsoLoad
857 
858   Description:  Loads and then links a static module.
859   Arguments:    None.
860 
861   Returns:
862 
863  *---------------------------------------------------------------------------*/
864 static RSOObjectHeader*
StaticRsoLoad(char * moduleName)865 StaticRsoLoad(char* moduleName)
866 {
867 
868     RSOObjectHeader* module;
869 
870     module = (RSOObjectHeader*)ReadDvdFile(moduleName, &s_mem1Allocator);
871     RSOListInit(module);
872 
873     return module;
874 }
875 
876 
877 /*---------------------------------------------------------------------------*
878   Name:         _unresolved
879 
880   Description:  Called when a function link from a static module is unresolved.
881 
882 
883   Arguments:    None.
884 
885   Returns:      None.
886  *---------------------------------------------------------------------------*/
887 __declspec(export) void
_unresolved()888 _unresolved()
889 {
890     OSReport("_unresolved func.\n");
891 }
892 
893 
894 /*---------------------------------------------------------------------------*
895   Name:         RSOResolvedModuleA
896 
897   Description:  Resolves references to RSO module A.
898 
899   Arguments:    None.
900 
901   Returns:
902 
903  *---------------------------------------------------------------------------*/
904 static void
RSOResolvedModuleA(const RSOObjectHeader * module)905 RSOResolvedModuleA(const RSOObjectHeader* module)
906 {
907     int i;
908     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
909         if(RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name) == NULL)
910         {
911             OSReport("-----> unresolved %s\n", exp_tbl[i].symbol_name);
912         }
913         else
914         {
915             OSReport("=====> resolved %s\n", exp_tbl[i].symbol_name);
916             OSReport("       addr = %X\n", RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name));
917         }
918         *(exp_tbl[i].symbol_ptr) =
919             (u32)RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name);
920     }
921 }
922 
923 
924 /*---------------------------------------------------------------------------*
925   Name:         RSOUnresolvedModuleA
926 
927   Description:  Invalidates references to RSO module A.
928 
929   Arguments:    None.
930 
931   Returns:
932 
933  *---------------------------------------------------------------------------*/
934 static void
RSOUnresolvedModuleA(void)935 RSOUnresolvedModuleA(void)
936 {
937     int i;
938     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
939         *(exp_tbl[i].symbol_ptr) = (u32)_unresolved;
940     }
941 }
942 
943 /* Projection settings */
944 static void
SetProjection(int wideflag)945 SetProjection( int wideflag )
946 {
947     Mtx44 projMtx;
948 
949     if( !wideflag )
950     {
951         DEMOReInit(&sRMObj[sTvmode]);
952         f32 viRateX = sRMObj[sTvmode].viWidth  / 670.f;
953         f32 viRateY = sRMObj[sTvmode].viHeight / 456.f;
954         MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 304.0f, viRateX * 304.0f, 0.0f, 500.0f);
955     }
956     else
957     {
958         DEMOReInit(&sRMObjWide[sTvmode]);
959         f32 viRateX = sRMObjWide[sTvmode].viWidth  / 682.f;
960         f32 viRateY = sRMObjWide[sTvmode].viHeight / 456.f;
961         MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 416.0f, viRateX * 416.0f, 0.0f, 500.0f);
962     }
963 
964     GXSetProjection(projMtx, GX_ORTHOGRAPHIC);
965 }
966 
967 /* Absolute value clamp */
AbsClamp(f32 val,f32 max)968 static f32 AbsClamp( f32 val, f32 max )
969 {
970     return ( ( val > max ) ? max : ( val < -max ) ? -max : val );
971 }
972 
973 /* Cursor movement processing for analog stick */
calcAnalogCursorPos(f32 stickX,f32 stickY,Vec2 * pos)974 static int calcAnalogCursorPos( f32 stickX, f32 stickY, Vec2* pos )
975 {
976     f32 x,y;
977     x = ( stickX / scStickMoveCoe );
978     y = ( stickY / scStickMoveCoe );
979     x = AbsClamp( x, 1.0f );
980     y = AbsClamp( y, 1.0f );
981     if( x == 0.0f && y == 0.0f ) return FALSE;
982     pos->x = AbsClamp( pos->x + x, 1.0f );
983     pos->y = AbsClamp( pos->y - y, 1.0f );
984     return TRUE;
985 }
986 
987 /* Cursor movement processing when using +Control key */
calcDigitalCursorPos(u32 button,Vec2 * pos)988 static int calcDigitalCursorPos( u32 button, Vec2* pos )
989 {
990     const float spd =1.0f / scStickMoveCoe;
991     const float spd2= spd * 0.7071f;
992 
993     button&=KPAD_CL_BUTTON_UP|KPAD_CL_BUTTON_LEFT|KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT;
994     switch (button)
995     {
996     case KPAD_CL_BUTTON_UP:     pos->y-=spd; break;
997     case KPAD_CL_BUTTON_LEFT:   pos->x-=spd; break;
998     case KPAD_CL_BUTTON_DOWN:   pos->y+=spd; break;
999     case KPAD_CL_BUTTON_RIGHT:  pos->x+=spd; break;
1000     case KPAD_CL_BUTTON_UP  |KPAD_CL_BUTTON_LEFT:   pos->y-=spd2; pos->x-=spd2; break;
1001     case KPAD_CL_BUTTON_UP  |KPAD_CL_BUTTON_RIGHT:  pos->y-=spd2; pos->x+=spd2; break;
1002     case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_LEFT:   pos->y+=spd2; pos->x-=spd2; break;
1003     case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT:  pos->y+=spd2; pos->x+=spd2; break;
1004     default: return FALSE;
1005     }
1006     pos->x = AbsClamp( pos->x, 1.0f );
1007     pos->y = AbsClamp( pos->y, 1.0f );
1008     return TRUE;
1009 }
1010 
1011 static void
GetControllerStatus(int no,KPADStatus * kpad)1012 GetControllerStatus(int no, KPADStatus* kpad)
1013 {
1014     int input_classic;
1015 
1016     s32 wpad_result;
1017     s32 kpad_result;
1018     u32 pad_type;
1019 
1020     wpad_result = WPADProbe( no, &pad_type );
1021     kpad_result	= KPADRead( no, &sKpads[no][0], KPAD_MAX_READ_BUFS );
1022 
1023     switch( wpad_result )
1024     {
1025         /* In the following error states, the value gotten by KPADRead is applied as-is. */
1026         case WPAD_ERR_BUSY:
1027         case WPAD_ERR_TRANSFER:
1028         case WPAD_ERR_INVALID:
1029         case WPAD_ERR_CORRUPTED:
1030         case WPAD_ERR_NONE:
1031             *kpad = sKpads[no][0];
1032             kpad->horizon.x = sKpads[no][0].horizon.x;
1033             kpad->horizon.y = sKpads[no][0].horizon.y;
1034             {
1035                 /*
1036                 According to guidelines, if there is input from a Classic Controller, that input is prioritized and inherits DPD coordinates.
1037 
1038                 Specify the DPD absolute coordinates when there is no Classic Controller input.
1039                 */
1040 
1041                 input_classic = calcDigitalCursorPos( kpad->ex_status.cl.hold, &cursorPos[no] );
1042 
1043                 input_classic = input_classic | calcAnalogCursorPos(
1044                     kpad->ex_status.cl.lstick.x,
1045                     kpad->ex_status.cl.lstick.y,
1046                     &cursorPos[no] );
1047 
1048                 if( !input_classic && kpad->dpd_valid_fg > 0)
1049                 {
1050                      cursorPos[no].x = kpad->pos.x;
1051                      cursorPos[no].y = kpad->pos.y;
1052                 }
1053 
1054                 kpad->pos.x = cursorPos[no].x;
1055                 kpad->pos.y = cursorPos[no].y;
1056             }
1057             break;
1058             /* Apply NULL in the following error states. */
1059         case WPAD_ERR_NO_CONTROLLER:
1060         default:
1061             kpad = NULL;
1062             break;
1063     }
1064 }
1065 
1066 /* Initialize GX */
InitGX()1067 static void InitGX()
1068 {
1069     GXClearVtxDesc();
1070 
1071     GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_POS,  GX_POS_XY,  GX_F32, 0);
1072     GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGB, GX_RGB8, 0);
1073     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
1074     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
1075 
1076     GXSetNumChans(1);
1077     GXSetNumTexGens(0);
1078     GXSetNumTevStages(1);
1079     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
1080     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
1081 
1082     GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR);
1083     GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
1084     GXSetCurrentMtx( GX_PNMTX1 );
1085 }
1086 
ResetCallback()1087 static void ResetCallback()
1088 {
1089     reset_called = TRUE;
1090 }
1091 
PowerCallback()1092 static void PowerCallback()
1093 {
1094     power_called = TRUE;
1095 }
1096