1 /*---------------------------------------------------------------------------*
2   Project:  rsodemo
3   File:     rsodemo.cpp
4 
5   Copyright 2006-2008 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 u16 sFbWidth = 608;
69 u16 sFbHeight = 456;
70 
71 // VI size
72 u16 viWidth = 670;
73 u16 viWidthWide = 686;
74 u16 viWidthWide_Pal = 682;
75 
76 u16 viHeight = 456;
77 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 - viWidth)/2),
138         (u16)((VI_MAX_HEIGHT_NTSC - viHeight)/2),
139         viWidth,
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 set up 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 //
makeCodeMem2(RSOObjectHeader * i_rso)272 static u32 *makeCodeMem2(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 *)allocMem2((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 = makeCodeMem2(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     freeMem2( (void*)moduleA );
398     freeMem2( (void*)buff_static );
399     freeMem2( (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_mem2Allocator );
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 wide-screen flag */
612                     drawModeFlag = !drawModeFlag;
613                     /* Applicable to hbm */
614                     setWideMode( drawModeFlag );
615                     /* Re-set the projection matrix */
616                     SetProjection( drawModeFlag );
617                     /* Get viewport information */
618                     pRm = DEMOGetRenderModeObj();
619                     /* Adjust the pointer's position in accordance with the screen's aspect ratio. */
620                     if( drawModeFlag )
621                     {
622                         /* 4:3 */
623                         posAdjust.x       = 1.0f;
624                         posAdjust.y       = 1.0f;
625                     }
626                     else
627                     {
628                         /* 16:9 */
629                         posAdjust.x       = 832.f / 608.f;
630                         posAdjust.y       = 1.0f;
631                     }
632                 }
633 
634                 /* HOME button prohibited icon */
635                 if ( kpad_status[i].trig == KPAD_BUTTON_PLUS && !banIconSwitch )
636                 {
637                     /* Initialize the values that will be used to control the icon's alpha value */
638                     banIconMode   = eAlphaInIcon;
639                     banIconTime   = OSGetTick();
640                     banIconAlpha  = 0;
641                     banIconSwitch = ON;
642                 }
643             }
644 
645             /* Begin rendering */
646             DEMOBeforeRender();
647             InitGX();
648 
649             for( i = 0; i < WPAD_MAX_CONTROLLERS; i++)
650             {
651                 u32 type;
652                 s32 result = WPADProbe( i, &type );
653                 if ( result == WPAD_ERR_NONE && type != WPAD_DEV_NOT_FOUND )
654                 {
655                     /* Determine the Wii pointer position */
656                     pos[i].x = kpad_status[i].pos.x;
657                     pos[i].y = kpad_status[i].pos.y;
658                     pos[i].x *= pRm->fbWidth * 0.5f;
659                     pos[i].y *= pRm->xfbHeight * 0.5f;
660                     pos[i].x *= posAdjust.x;
661                     pos[i].y *= posAdjust.y;
662 
663                     /* Render the Wii Pointer */
664                     GXBegin( GX_QUADS, GX_VTXFMT4, 4 );
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                     GXPosition2f32(  10 + pos[i].x, -10 - pos[i].y );
672                     GXColor3u8( 255, 255, 255 );
673                     GXEnd();
674                 }
675             }
676 
677             /* Render the HOME Menu prohibited icon */
678             if ( banIconSwitch )
679             {
680                 f32 elapse = OSTicksToMilliseconds( OSDiffTick( OSGetTick(), banIconTime ) );
681 
682                 switch ( banIconMode )
683                 {
684                     case eAlphaInIcon: /* AlphaIn (250ms) */
685                     banIconAlpha = ( u8 )( 255.9f * ( elapse / 250.f ) );
686                     if ( elapse >= 250.f )
687                     {
688                         banIconTime  = OSGetTick();
689                         banIconMode  = ePauseIcon;
690                         banIconAlpha = 255;
691                     }
692                     break;
693                     case ePauseIcon: /* Pause (1000ms) */
694                         if ( elapse >= 1000.f )
695                         {
696                             banIconTime = OSGetTick();
697                             banIconMode = eAlphaOutIcon;
698                         }
699                         break;
700                     case eAlphaOutIcon: /* AlphaOut (250ms) */
701                         banIconAlpha = ( u8 )( 255.9f * ( ( 250.f - elapse ) / 250.f ) );
702                         if ( elapse >= 250.f )
703                         {
704                             banIconAlpha  = 0;
705                             banIconSwitch = OFF;
706                         }
707                         break;
708                 }
709                 DrawBanIcon( banIconAlpha );
710             }
711 
712             /* Rendering ended */
713             DEMODoneRender();
714         }
715 
716         /* Reset/Power Callback */
717         if( reset_called == TRUE )
718         {
719             OSRestart( 0 );
720         }
721         if( power_called == TRUE )
722         {
723             OSReturnToMenu();
724         }
725     }
726 
727     return 0;
728 }
729 
730 /*---------------------------------------------------------------------------*
731  * Name        : allocMem1()
732  * Description : Callback needed by WPAD to allocate mem from MEM2 heap.
733  * Arguments   : size of block, in bytes.
734  * Returns     : pointer to allocated block.
735  *---------------------------------------------------------------------------*/
allocMem1(u32 size)736 static void *allocMem1(u32 size)
737 {
738     void *ptr;
739 
740     ptr = MEMAllocFromAllocator(&s_mem1Allocator, size);
741     ASSERTMSG(ptr, "Memory allocation failed\n");
742 
743     return(ptr);
744 
745 }
746 
747 /*---------------------------------------------------------------------------*
748  * Name        : freeMem1()
749  * Description : Callback needed by WPAD to free mem from MEM2 heap.
750  * Arguments   : None.
751  * Returns     : Always 1.
752  *---------------------------------------------------------------------------*/
freeMem1(void * ptr)753 static u8 freeMem1(void *ptr)
754 {
755 
756     MEMFreeToAllocator(&s_mem1Allocator, ptr);
757 
758     // we should ensure that memory is free'd properly, but oh well
759     return(1);
760 
761 }
762 
763 /*---------------------------------------------------------------------------*
764  * Name        : allocMem2()
765  * Description : Callback needed by WPAD to allocate mem from MEM2 heap.
766  * Arguments   : size of block, in bytes.
767  * Returns     : pointer to allocated block.
768  *---------------------------------------------------------------------------*/
allocMem2(u32 size)769 static void *allocMem2(u32 size)
770 {
771     void *ptr;
772 
773     ptr = MEMAllocFromAllocator(&s_mem2Allocator, size);
774     ASSERTMSG(ptr, "Memory allocation failed\n");
775 
776     return(ptr);
777 
778 }
779 
780 /*---------------------------------------------------------------------------*
781  * Name        : freeMem2()
782  * Description : Callback needed by WPAD to free mem from MEM2 heap.
783  * Arguments   : None.
784  * Returns     : Always 1.
785  *---------------------------------------------------------------------------*/
freeMem2(void * ptr)786 static u8 freeMem2(void *ptr)
787 {
788 
789     MEMFreeToAllocator(&s_mem2Allocator, ptr);
790 
791     // we should ensure that memory is free'd properly, but oh well
792     return(1);
793 
794 }
795 
796 /* Load file */
ReadDvdFile(const char * fileName,MEMAllocator * mem)797 static void* ReadDvdFile(
798     const char*     fileName,
799     MEMAllocator*   mem
800 )
801 {
802     u32 fileLen, fileLenUp32;
803     void* readBuf;
804     s32 readBytes;
805 
806     DVDFileInfo fileInfo;
807     if (! DVDOpen(fileName, &fileInfo))
808     {
809         return NULL;
810     }
811 
812     fileLen     = DVDGetLength(&fileInfo);
813     if( (fileLen % 32) != 0 )
814     {
815         fileLenUp32 = fileLen + (32 - (fileLen % 32));
816     }
817     else
818     {
819         fileLenUp32 = fileLen;
820     }
821     readBuf = MEMAllocFromAllocator(mem, fileLenUp32);
822     readBytes = DVDRead(&fileInfo, readBuf, (s32)(fileLenUp32), 0);
823     ASSERT(readBytes > 0);
824     DVDClose(&fileInfo);
825 
826     return readBuf;
827 }
828 
829 /*---------------------------------------------------------------------------*
830   Name:         RsoLoad
831 
832   Description:  Loads and then links an RSO module.
833 
834   Arguments:    None.
835 
836   Returns:
837  *---------------------------------------------------------------------------*/
838 
839 static RSOObjectHeader*
RsoLoad(char * moduleName)840 RsoLoad(char* moduleName)
841 {
842     RSOObjectHeader* module;
843 
844     module = (RSOObjectHeader*)ReadDvdFile(moduleName, &s_mem2Allocator);
845     if (module->bssSize > 0)
846     {
847         bss = (u8*)allocMem2( module->bssSize );
848     }
849 
850     RSOLinkList(module, bss);
851 
852     return module;
853 }
854 
855 
856 /*---------------------------------------------------------------------------*
857   Name:         StaticRsoLoad
858 
859   Description:  Loads and then links a static module.
860   Arguments:    None.
861 
862   Returns:
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 the link to a function that is referenced from a static module has not been resolved.
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 static void
RSOResolvedModuleA(const RSOObjectHeader * module)904 RSOResolvedModuleA(const RSOObjectHeader* module)
905 {
906     int i;
907     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
908         if(RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name) == NULL)
909         {
910             OSReport("-----> unresolved %s\n", exp_tbl[i].symbol_name);
911         }
912         else
913         {
914             OSReport("=====> resolved %s\n", exp_tbl[i].symbol_name);
915             OSReport("       addr = %X\n", RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name));
916         }
917         *(exp_tbl[i].symbol_ptr) =
918             (u32)RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name);
919     }
920 }
921 
922 
923 /*---------------------------------------------------------------------------*
924   Name:         RSOUnresolvedModuleA
925 
926   Description:  Invalidates references to RSO module A.
927 
928   Arguments:    None.
929 
930   Returns:
931  *---------------------------------------------------------------------------*/
932 static void
RSOUnresolvedModuleA(void)933 RSOUnresolvedModuleA(void)
934 {
935     int i;
936     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
937         *(exp_tbl[i].symbol_ptr) = (u32)_unresolved;
938     }
939 }
940 
941 /* Projection settings */
942 static void
SetProjection(int wideflag)943 SetProjection( int wideflag )
944 {
945     Mtx44 projMtx;
946 
947     if( !wideflag )
948     {
949         DEMOReInit(&sRMObj[sTvmode]);
950         f32 viRateX = sRMObj[sTvmode].viWidth  / 670.f;
951         f32 viRateY = sRMObj[sTvmode].viHeight / 456.f;
952         MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 304.0f, viRateX * 304.0f, 0.0f, 500.0f);
953     }
954     else
955     {
956         DEMOReInit(&sRMObjWide[sTvmode]);
957         f32 viRateX = sRMObjWide[sTvmode].viWidth  / 686.f;
958         f32 viRateY = sRMObjWide[sTvmode].viHeight / 456.f;
959         MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 437.0f, viRateX * 437.0f, 0.0f, 500.0f);
960     }
961 
962     GXSetProjection(projMtx, GX_ORTHOGRAPHIC);
963 }
964 
965 /* Absolute value clamp */
AbsClamp(f32 val,f32 max)966 static f32 AbsClamp( f32 val, f32 max )
967 {
968     return ( ( val > max ) ? max : ( val < -max ) ? -max : val );
969 }
970 
971 /* Cursor movement processing for analog stick */
calcAnalogCursorPos(f32 stickX,f32 stickY,Vec2 * pos)972 static int calcAnalogCursorPos( f32 stickX, f32 stickY, Vec2* pos )
973 {
974     f32 x,y;
975     x = ( stickX / scStickMoveCoe );
976     y = ( stickY / scStickMoveCoe );
977     x = AbsClamp( x, 1.0f );
978     y = AbsClamp( y, 1.0f );
979     if( x == 0.0f && y == 0.0f ) return FALSE;
980     pos->x = AbsClamp( pos->x + x, 1.0f );
981     pos->y = AbsClamp( pos->y - y, 1.0f );
982     return TRUE;
983 }
984 
985 /* Cursor movement processing when using +Control key */
calcDigitalCursorPos(u32 button,Vec2 * pos)986 static int calcDigitalCursorPos( u32 button, Vec2* pos )
987 {
988     const float spd =1.0f / scStickMoveCoe;
989     const float spd2= spd * 0.7071f;
990 
991     button&=KPAD_CL_BUTTON_UP|KPAD_CL_BUTTON_LEFT|KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT;
992     switch (button)
993     {
994     case KPAD_CL_BUTTON_UP:     pos->y-=spd; break;
995     case KPAD_CL_BUTTON_LEFT:   pos->x-=spd; break;
996     case KPAD_CL_BUTTON_DOWN:   pos->y+=spd; break;
997     case KPAD_CL_BUTTON_RIGHT:  pos->x+=spd; break;
998     case KPAD_CL_BUTTON_UP  |KPAD_CL_BUTTON_LEFT:   pos->y-=spd2; pos->x-=spd2; break;
999     case KPAD_CL_BUTTON_UP  |KPAD_CL_BUTTON_RIGHT:  pos->y-=spd2; pos->x+=spd2; break;
1000     case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_LEFT:   pos->y+=spd2; pos->x-=spd2; break;
1001     case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT:  pos->y+=spd2; pos->x+=spd2; break;
1002     default: return FALSE;
1003     }
1004     pos->x = AbsClamp( pos->x, 1.0f );
1005     pos->y = AbsClamp( pos->y, 1.0f );
1006     return TRUE;
1007 }
1008 
1009 static void
GetControllerStatus(int no,KPADStatus * kpad)1010 GetControllerStatus(int no, KPADStatus* kpad)
1011 {
1012     int input_classic;
1013 
1014     s32 wpad_result;
1015     s32 kpad_result;
1016     u32 pad_type;
1017 
1018     wpad_result = WPADProbe( no, &pad_type );
1019     kpad_result	= KPADRead( no, &sKpads[no][0], KPAD_MAX_READ_BUFS );
1020     if ( kpad_result == 0 )
1021         memset(&sKpads[no][0], 0, sizeof(KPADStatus));
1022     switch( wpad_result )
1023     {
1024         /* In the following error states, the value gotten by KPADRead is applied as-is. */
1025         case WPAD_ERR_BUSY:
1026         case WPAD_ERR_TRANSFER:
1027         case WPAD_ERR_INVALID:
1028         case WPAD_ERR_CORRUPTED:
1029         case WPAD_ERR_NONE:
1030             *kpad = sKpads[no][0];
1031             kpad->horizon.x = sKpads[no][0].horizon.x;
1032             kpad->horizon.y = sKpads[no][0].horizon.y;
1033             {
1034                 /*
1035                 According to guidelines, if there is input from a Classic Controller, that input is prioritized and inherits DPD coordinates.
1036 
1037                 Specify the DPD absolute coordinates when there is no Classic Controller input.
1038                 */
1039 
1040                 input_classic = calcDigitalCursorPos( kpad->ex_status.cl.hold, &cursorPos[no] );
1041 
1042                 input_classic = input_classic | calcAnalogCursorPos(
1043                     kpad->ex_status.cl.lstick.x,
1044                     kpad->ex_status.cl.lstick.y,
1045                     &cursorPos[no] );
1046 
1047                 if( !input_classic && kpad->dpd_valid_fg > 0)
1048                 {
1049                      cursorPos[no].x = kpad->pos.x;
1050                      cursorPos[no].y = kpad->pos.y;
1051                 }
1052 
1053                 kpad->pos.x = cursorPos[no].x;
1054                 kpad->pos.y = cursorPos[no].y;
1055             }
1056             break;
1057             /* Apply NULL in the following error states. */
1058         case WPAD_ERR_NO_CONTROLLER:
1059         default:
1060             kpad = NULL;
1061             break;
1062     }
1063 }
1064 
1065 /* Initialize GX */
InitGX()1066 static void InitGX()
1067 {
1068     GXClearVtxDesc();
1069 
1070     GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_POS,  GX_POS_XY,  GX_F32, 0);
1071     GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGB, GX_RGB8, 0);
1072     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
1073     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
1074 
1075     GXSetNumChans(1);
1076     GXSetNumTexGens(0);
1077     GXSetNumTevStages(1);
1078     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
1079     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
1080 
1081     GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR);
1082     GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
1083     GXSetCurrentMtx( GX_PNMTX1 );
1084 }
1085 
ResetCallback()1086 static void ResetCallback()
1087 {
1088     reset_called = TRUE;
1089 }
1090 
PowerCallback()1091 static void PowerCallback()
1092 {
1093     power_called = TRUE;
1094 }
1095