1 /*---------------------------------------------------------------------------*
2   Project:  WiiConnect24 API demos
3   File:     MsgViewer.c
4 
5   Copyright 2006 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   $Log: MsgViewer.c,v $
14   Revision 1.7  2008/05/30 02:27:03  seiki_masashi
15   Reverted code consequent upon reverted SDK code.
16 
17   Revision 1.5  2008/05/01 08:50:26  hirose_kazuki
18   Added "Close library" mode.
19 
20   Revision 1.4  2008/04/28 11:20:23  hirose_kazuki
21   Updated framework.
22 
23   Revision 1.3  2008/01/21 10:39:05  hirose_kazuki
24   Changed to suspend the scheduler by default.
25   Modified main sequence to avoid calling OpenLib/CloseLib every frame.
26 
27   Revision 1.2  2007/02/02 02:20:33  torigoe_nobutaka
28   Added OpenLib() and CloseLib().
29   Added handling of messages without subject or body text.
30   Fixed bug in GetMsgIdList().
31 
32   Revision 1.1  2006/09/27 08:57:45  torigoe_nobutaka
33   Renamed from MessageViewer.c
34   Moved from nwc24demo/src.
35 
36   Revision 1.4  2006/09/27 07:31:45  torigoe_nobutaka
37   Improved performance.
38 
39   Revision 1.3  2006/09/13 08:14:22  yosizaki
40   Changed to call VFInit().
41 
42   Revision 1.2  2006/09/10 09:20:56  hirose_kazuki
43   Changed to use NWC24OpenLib/NWC24CloseLib instead of obsolete functions.
44 
45   Revision 1.1  2006/08/28 08:51:51  torigoe_nobutaka
46   Initial check in.
47 
48 
49   $NoKeywords: $
50  *---------------------------------------------------------------------------*/
51 
52 #include <revolution.h>
53 #include <revolution/mem.h>
54 #include <revolution/kpad.h>
55 #include <revolution/nand.h>
56 #include <revolution/vf.h>
57 #include <revolution/nwc24.h>
58 #include <revolution/net.h>
59 #include <string.h>
60 
61 #define DEMO_USE_MEMLIB 1
62 #include <demo.h>
63 
64 #include "MsgViewer.h"
65 #include "MsgViewerRender.h"
66 #include "MsgViewerUpdate.h"
67 
68 /*---------------------------------------------------------------------------*
69    Global variables
70  *---------------------------------------------------------------------------*/
71 s16             g_screenWidth;
72 s16             g_screenHeight;
73 OSFontHeader*   g_fontData                                      = NULL;
74 MsgBoxState     g_state                                         = MB_STATE_MENU;
75 MsgBoxMenu      g_selectedMenu                                  = MB_MENU_RECV_BOX;
76 u32*            g_idListBuf[NUM_MSG_BOX_TYPES]                  = { NULL };
77 u32             g_numMsgs[NUM_MSG_BOX_TYPES]                    = { 0 };
78 u32             g_idxSelectedId[NUM_MSG_BOX_TYPES]              = { 0 };
79 u32             g_idxIdTopOfList[NUM_MSG_BOX_TYPES]             = { 0 };
80 u32             g_lineTopOfBodyText                             = 0;
81 u32             g_numLinesBodyText                              = 1;
82 char*           g_subjectBuf[NUM_MSG_BOX_TYPES][LIST_BOX_ROWS]  = { { NULL }, { NULL } };
83 u32             g_idxSubjectBufStart[NUM_MSG_BOX_TYPES]         = { 0 };
84 MsgData         g_msgData;
85 s32             g_errorCode                                     = 0;
86 
87 /*---------------------------------------------------------------------------*
88    Global constants
89  *---------------------------------------------------------------------------*/
90 const GXColor   CLR_DARKBLUE                        = {   0,   0,  40, 255 };
91 const GXColor   CLR_WHITE                           = { 255, 255, 255, 255 };
92 const char*     HIDDEN_MESSAGE                      = "(Cannot read.)";
93 const char*     BROKEN_MESSAGE                      = "(May be broken.)";
94 
95 /*---------------------------------------------------------------------------*
96    Static constants
97  *---------------------------------------------------------------------------*/
98 static const    u32     HOLD_THRESHOLD      =   10;
99 #define                 NUM_KPAD_BUTTONS        16
100 
101 #define                 PAD_BUTTONS_USED    \
102     ((PAD_BUTTON_A)|(PAD_BUTTON_B)|(PAD_BUTTON_UP)|(PAD_BUTTON_DOWN))
103 
104 #define                 KPAD_BUTTONS_USED   \
105     ((KPAD_BUTTON_A)|(KPAD_BUTTON_B)|(KPAD_BUTTON_UP)|(KPAD_BUTTON_DOWN))
106 
107 #define                 ALL_BUTTONS_USED    \
108     ((KPAD_BUTTONS_USED)|((PAD_BUTTONS_USED)<<16))
109 
110 #define                 PAD_BUTTONS_REPEATABLE  \
111     ((PAD_BUTTON_UP)|(PAD_BUTTON_DOWN))
112 
113 #define                 KPAD_BUTTONS_REPEATABLE \
114     ((KPAD_BUTTON_UP)|(KPAD_BUTTON_DOWN))
115 
116 #define                 ALL_BUTTONS_REPEATABLE  \
117     ((KPAD_BUTTONS_REPEATABLE)|((PAD_BUTTONS_REPEATABLE)<<16))
118 
119 
120 /*---------------------------------------------------------------------------*
121    Static variables
122  *---------------------------------------------------------------------------*/
123 static  char*   s_libWorkMem                        = NULL;
124 static  u32     s_longHold                          = 0;     // Button held down
125 static  u32     s_holdCount[32]                     = { 0 };
126 
127 /*---------------------------------------------------------------------------*
128    Local functions
129  *---------------------------------------------------------------------------*/
130 static void*    AllocFromPadHeap( u32 size );
131 static u8       FreeToPadHeap   ( void* ptr );
132 static void     SampleInitialize( void );
133 static void     SampleFinalize  ( void );
134 
135 /*---------------------------------------------------------------------------*
136    App entry point
137  *---------------------------------------------------------------------------*/
main(void)138 int main( void )
139 {
140     KPADStatus  input;
141     u32         hold;
142     u32         trig;
143     u8          iButton;
144 
145     SampleInitialize();
146     (void)memset( &input, 0, sizeof(KPADStatus) );
147 
148     /* App main loop */
149     while ( TRUE )
150     {
151         DEMOPadRead();
152         (void)KPADRead( WPAD_CHAN0, &input, 1 );
153 
154         /* Combination of KPAD and PAD */
155         hold = (input.hold) | (DEMOPadGetButton(0) << 16);
156         trig = (input.trig) | (DEMOPadGetButtonDown(0) << 16);
157 
158         /* Button hold detect */
159         for ( iButton = 0; iButton < 32; ++iButton )
160         {
161             if ( (hold >> iButton) & 0x1 )
162             {
163                 ++s_holdCount[iButton];
164             }
165             else
166             {
167                 s_holdCount[iButton] = 0;
168             }
169 
170             if ( HOLD_THRESHOLD < s_holdCount[iButton] )
171             {
172                 s_longHold |= 0x1 << iButton;
173             }
174             else
175             {
176                 s_longHold &= ~(0x1 << iButton);
177             }
178         }
179 
180         trig |= (s_longHold & ALL_BUTTONS_REPEATABLE);
181 
182         /* Update processing other than rendering */
183         Update( trig );
184 
185         /* Render */
186         DEMOBeforeRender();
187         Render();
188         DEMODoneRender();
189     }
190 
191     SampleFinalize();
192 
193     OSHalt( "All done." );
194     return 0;
195 }
196 
197 /*---------------------------------------------------------------------------*
198   Name        : CheckError
199   Description : Checks the error code of NWC24Err-type errors, and if not NWC24_OK, displays the error content.
200 
201   Arguments   : strFunc     - Name of function that returned the error code.
202                 err         - NWC24Err-type error code.
203   Returns     : NWC24Err    -Same value as err.
204  *---------------------------------------------------------------------------*/
CheckError(const char * strFunc,NWC24Err err)205 void CheckError( const char* strFunc, NWC24Err err )
206 {
207     if ( err != NWC24_OK )
208     {
209         OSReport( "%s: error %d\n", strFunc, err );
210         OSHalt( "Failed.\n" );
211     }
212 
213     return;
214 }
215 
216 /*---------------------------------------------------------------------------*
217   Name        : GetMsgIdList
218   Description : Get the total message count and message ID list in the specified message box.
219 
220   Arguments   : mBoxId  - Message box type.
221   Returns     : None.
222  *---------------------------------------------------------------------------*/
GetMsgIdList(NWC24MsgBoxId mBoxId)223 void GetMsgIdList( NWC24MsgBoxId mBoxId )
224 {
225     NWC24Err    err;
226     u32         bufSize;
227     MsgBoxType  mbType  = (mBoxId == NWC24_RECV_BOX) ? MB_TYPE_RECV : MB_TYPE_SEND;
228 
229     err = NWC24GetNumMsgs( mBoxId, &g_numMsgs[mbType] );
230     CheckError( "NWC24GetNumMsgs()", err );
231 
232     if ( g_numMsgs[mbType] == 0 )
233     {
234         g_idListBuf[mbType] = NULL;
235         return;
236     }
237 
238     bufSize = OSRoundUp32B( g_numMsgs[mbType] * sizeof(u32) );
239     g_idListBuf[mbType] = (u32*)MEMAllocFromAllocator( &DemoAllocator1, bufSize );
240     err = NWC24GetMsgIdList( mBoxId, g_idListBuf[mbType], g_numMsgs[mbType] );
241     CheckError( "NWC24GetMsgIdList()", err );
242 
243     return;
244 }
245 
246 /*---------------------------------------------------------------------------*
247   Name        : ReleaseMsgIdList
248   Description : Deallocates the memory used for the message ID list in the specified message box.
249 
250   Arguments   : mBoxId  - Message box type.
251   Returns     : None.
252  *---------------------------------------------------------------------------*/
ReleaseMsgIdList(NWC24MsgBoxId mBoxId)253 void ReleaseMsgIdList( NWC24MsgBoxId mBoxId )
254 {
255     MsgBoxType  mbType  = (mBoxId == NWC24_RECV_BOX) ? MB_TYPE_RECV : MB_TYPE_SEND;
256 
257     if ( g_idListBuf[mbType] )
258     {
259         MEMFreeToAllocator( &DemoAllocator1, g_idListBuf[mbType] );
260         g_idListBuf[mbType] = NULL;
261     }
262 
263     return;
264 }
265 
266 /*---------------------------------------------------------------------------*
267   Name        : ReadSubject
268   Description : Reads the subject from the specified message and copies only the specified length to the buffer.
269 
270   Arguments   : buf     - Buffer to copy to
271                 size    - Maximum size to copy
272                 mBoxId  - Message box type.
273                 msgId   - Message ID.
274   Returns     : BOOL - TRUE if successful.
275  *---------------------------------------------------------------------------*/
ReadSubject(char * buf,u32 size,NWC24MsgBoxId mBoxId,u32 msgId)276 BOOL ReadSubject( char* buf, u32 size, NWC24MsgBoxId mBoxId, u32 msgId )
277 {
278     NWC24Err    err;
279     NWC24MsgObj msgObj;
280     BOOL        result = FALSE;
281     u32         subjectSize;
282     char*       subjectBuf = NULL;
283 
284     err = NWC24GetMsgObj( &msgObj, mBoxId, msgId );
285     if ( err == NWC24_ERR_HIDDEN )
286     {
287         (void)strncpy(buf, HIDDEN_MESSAGE, size);
288         return FALSE;
289     }
290     else
291     {
292         err = NWC24GetMsgSubjectSize( &msgObj, &subjectSize );
293         if ( err != NWC24_OK )
294         {
295             (void)strncpy( buf, BROKEN_MESSAGE, size );
296             return FALSE;
297         }
298 
299         if ( subjectSize < 1 )
300         {
301             subjectSize = 1;
302         }
303 
304         subjectBuf = MEMAllocFromAllocator( &DemoAllocator1, subjectSize );
305         err = NWC24ReadMsgSubject( &msgObj, subjectBuf, subjectSize );
306 
307         if ( err != NWC24_OK )
308         {
309             result = FALSE;
310             (void)strncpy( buf, BROKEN_MESSAGE, size );
311         }
312         else
313         {
314             result = TRUE;
315             (void)strncpy( buf, subjectBuf, size );
316         }
317         MEMFreeToAllocator( &DemoAllocator1, subjectBuf );
318     }
319 
320     return result;
321 }
322 
323 /*---------------------------------------------------------------------------*
324   Name        : GetListedSubjects
325   Description : Gets the title of the message displayed onscreen for the specified message box.
326 
327   Arguments   : mBoxId  - Message box type.
328   Returns     : None.
329  *---------------------------------------------------------------------------*/
GetListedSubjects(NWC24MsgBoxId mBoxId)330 void GetListedSubjects( NWC24MsgBoxId mBoxId )
331 {
332     u32         i;
333     MsgBoxType  mbType  = (mBoxId == NWC24_RECV_BOX) ? MB_TYPE_RECV : MB_TYPE_SEND;
334 
335     g_idxSubjectBufStart[mbType] = 0;
336 
337     for ( i = 0; i < LIST_BOX_ROWS; ++i )
338     {
339         u32     idxIdListBuf    = (u32)(g_idxIdTopOfList[mbType] + i);
340 
341         if ( g_numMsgs[mbType] <= idxIdListBuf )
342         {
343             break;
344         }
345 
346         g_subjectBuf[mbType][i] = MEMAllocFromAllocator( &DemoAllocator1, LEN_SUBJECT_DISP );
347         (void)NETMemSet( g_subjectBuf[mbType][i], 0, LEN_SUBJECT_DISP );
348         (void)ReadSubject( g_subjectBuf[mbType][i], LEN_SUBJECT_DISP-1, mBoxId,
349                            g_idListBuf[mbType][idxIdListBuf] );
350     }
351 
352     return;
353 }
354 
355 /*---------------------------------------------------------------------------*
356   Name        : ReleaseListedSubjects
357   Description : Deallocates the buffer for the title of the message displayed onscreen for the specified message box.
358 
359   Arguments   : mBoxId  - Message box type.
360   Returns     : None.
361  *---------------------------------------------------------------------------*/
ReleaseListedSubjects(NWC24MsgBoxId mBoxId)362 void ReleaseListedSubjects( NWC24MsgBoxId mBoxId )
363 {
364     u32         i;
365     MsgBoxType  mbType  = (mBoxId == NWC24_RECV_BOX) ? MB_TYPE_RECV : MB_TYPE_SEND;
366 
367     for ( i = 0; i < LIST_BOX_ROWS; ++i )
368     {
369         if ( g_subjectBuf[mbType][i] )
370         {
371             MEMFreeToAllocator( &DemoAllocator1, g_subjectBuf[mbType][i] );
372             g_subjectBuf[mbType][i] = NULL;
373         }
374     }
375 
376     return;
377 }
378 
379 /*---------------------------------------------------------------------------*
380   Name        : OpenLib
381   Description : Calls NWC24OpenLib().
382   Arguments   : None.
383   Returns     : None.
384  *---------------------------------------------------------------------------*/
OpenLib(void)385 BOOL OpenLib( void )
386 {
387     NWC24Err    err;
388 
389     err = NWC24OpenLib( s_libWorkMem );
390     if ( err == NWC24_ERR_BUSY ||
391          err == NWC24_ERR_MUTEX ||
392          err == NWC24_ERR_INPROGRESS )
393     {
394         g_errorCode = NWC24GetErrorCode();
395         return FALSE;
396     }
397     if ( err != NWC24_OK )
398     {
399         g_errorCode = NWC24GetErrorCode();
400         g_state     = MB_STATE_ERROR_STOP;
401         return FALSE;
402     }
403 
404     g_errorCode = 0;
405     g_state = MB_STATE_MENU;
406     return TRUE;
407 }
408 
409 /*---------------------------------------------------------------------------*
410   Name        : CloseLib
411   Description : Calls NWC24CloseLib().
412   Arguments   : None.
413   Returns     : None.
414  *---------------------------------------------------------------------------*/
CloseLib(void)415 BOOL CloseLib( void )
416 {
417     NWC24Err    err;
418 
419     err = NWC24CloseLib();
420     if ( err != NWC24_OK )
421     {
422         g_errorCode = NWC24_ERRCODE_UNDEFINED;
423         g_state     = MB_STATE_ERROR_STOP;
424         return FALSE;
425     }
426 
427     g_errorCode = 0;
428     g_state = MB_STATE_LIB_CLOSED;
429     return TRUE;
430 }
431 
432 /*---------------------------------------------------------------------------*
433   Name        : AllocFromPadHeap
434   Description : Dynamically allocates memory for the WPAD library.
435   Arguments   : size    -   Specifies the size of memory to allocate (in bytes).
436   Returns     : void*   - Start address of the allocated memory.
437  *---------------------------------------------------------------------------*/
AllocFromPadHeap(u32 size)438 static void* AllocFromPadHeap( u32 size )
439 {
440     return MEMAllocFromAllocator( &DemoAllocator2, size );
441 }
442 
443 /*---------------------------------------------------------------------------*
444   Name        : FreeToPadHeap
445   Description : Deallocates memory dynamically allocated for the WPAD library.
446   Arguments   : ptr - Start address of the memory to deallocate.
447   Returns     : u8      -   Returns 0 if the attempt to deallocate memory fails.
448  *---------------------------------------------------------------------------*/
FreeToPadHeap(void * ptr)449 static u8 FreeToPadHeap( void* ptr )
450 {
451     if ( !ptr )
452     {
453         return 0;
454     }
455 
456     MEMFreeToAllocator( &DemoAllocator2, ptr );
457     ptr = NULL;
458 
459     return 1;
460 }
461 
462 /*---------------------------------------------------------------------------*
463   Name        : SampleInitialize
464   Description : Initializes the sample program.
465   Arguments   : None.
466   Returns     : None.
467  *---------------------------------------------------------------------------*/
SampleInitialize(void)468 static void SampleInitialize( void )
469 {
470     OSInit();
471 
472     /* Initialize DEMO and GX */
473     {
474         GXRenderModeObj*    renderMode  = NULL;
475 
476         DEMOInit( NULL );
477         g_fontData = DEMOInitROMFont();
478         DEMOSetROMFontSize( FONT_SIZE, 0 );
479         renderMode = DEMOGetRenderModeObj();
480         g_screenWidth = (s16)renderMode->fbWidth;
481         g_screenHeight = (s16)renderMode->efbHeight;
482         DEMOInitCaption( DM_FT_XLU, g_screenWidth, g_screenHeight );
483         GXSetCopyClear( CLR_DARKBLUE, GX_MAX_Z24 );
484         GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO );
485         GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
486         GXSetTevColor( GX_TEVREG0, CLR_WHITE );
487     }
488 
489     /* Initialize NAND */
490     {
491         s32     result;
492 
493         result = NANDInit();
494         if ( result != NAND_RESULT_OK )
495         {
496             OSHalt("NANDInit() failed.\n");
497         }
498     }
499 
500     /* Initialize VF */
501     {
502         VFInit();
503     }
504 
505     /* Initialize KPAD. */
506     {
507         WPADRegisterAllocator( AllocFromPadHeap, FreeToPadHeap );
508         KPADInit();
509     }
510 
511     /* Initialize other applications */
512     {
513         s_libWorkMem = MEMAllocFromAllocator( &DemoAllocator1, NWC24_WORK_MEM_SIZE );
514 
515         /* Fundamentally, NWC24 is left open in this demo */
516         if ( OpenLib() )
517         {
518             /* Initialize message ID list */
519             GetMsgIdList( NWC24_RECV_BOX );
520             GetMsgIdList( NWC24_SEND_BOX );
521 
522             /* Initialize the title buffer of displayed message */
523             GetListedSubjects( NWC24_RECV_BOX );
524             GetListedSubjects( NWC24_SEND_BOX );
525         }
526     }
527 
528     return;
529 }
530 
531 /*---------------------------------------------------------------------------*
532   Name        : SampleFinalize
533   Description : Finalizes the sample program.
534   Arguments   : None.
535   Returns     : None.
536  *---------------------------------------------------------------------------*/
SampleFinalize(void)537 static void SampleFinalize( void )
538 {
539     MEMFreeToAllocator( &DemoAllocator1, s_libWorkMem );
540     ReleaseMsgIdList( NWC24_RECV_BOX );
541     ReleaseMsgIdList( NWC24_SEND_BOX );
542     ReleaseListedSubjects( NWC24_RECV_BOX );
543     ReleaseListedSubjects( NWC24_SEND_BOX );
544     return;
545 }
546 
547 /*======== End of MsgViewer.c ========*/
548