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