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