1 /*---------------------------------------------------------------------------*
2   Project:    WPAD demo program
3   File:       memory.c
4 
5   Copyright (C) 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: memory.c,v $
14   Revision 1.12  2008/12/24 06:28:46  tojo
15   (none)
16 
17   Revision 1.11  2008/12/24 06:23:49  tojo
18   Modified the error handling of controller data.
19 
20   Revision 1.10  2007/04/23 09:02:52  tojo
21   (none)
22 
23   Revision 1.9  2006/10/23 01:06:36  tojo
24   Called WPADSetConnectCallback before initialization complete.
25 
26   Revision 1.8  2006/09/28 10:52:25  tojo
27   (none)
28 
29   Revision 1.7  2006/09/23 07:13:15  tojo
30   Changed api names
31 
32   Revision 1.6  2006/09/08 09:00:28  tojo
33   (none)
34 
35   Revision 1.5  2006/09/05 11:30:09  tojo
36   (none)
37 
38   Revision 1.4  2006/09/05 02:49:10  tojo
39   (none)
40 
41   Revision 1.3  2006/09/05 02:38:35  tojo
42   (none)
43 
44   Revision 1.2  2006/08/31 12:44:19  tojo
45   (none)
46 
47   Revision 1.1  2006/08/16 05:05:30  tojo
48   Initial check in.
49 
50 
51  *---------------------------------------------------------------------------*/
52 #define DEMO_USE_MEMLIB = 1
53 #include <revolution.h>
54 #include <revolution/wpad.h>
55 #include <revolution/enc.h>
56 #include <demo.h>
57 #include <string.h>
58 
59 #define WDATA       0
60 #define RDATA       1
61 
62 u8 txBuf[WPAD_MAX_CONTROLLERS][WPAD_MEM_GAMEDATA_LEN];
63 u8 rxBuf[WPAD_MAX_CONTROLLERS][WPAD_MEM_GAMEDATA_LEN];
64 
65 OSTime start[WPAD_MAX_CONTROLLERS];
66 OSTime end[WPAD_MAX_CONTROLLERS];
67 
68 static void memory( s32 chan, u32 cmd, void *p_buf, u16 len );
69 
70 /*---------------------------------------------------------------------------*
71  * For WPAD testing
72  *---------------------------------------------------------------------------*/
73 void *myAlloc( u32 size  );
74 u8    myFree ( void *ptr );
75 
76 /*---------------------------------------------------------------------------*
77  * Name        : myAlloc
78  * Description : Callback needed by WPAD to allocate mem from MEM2 heap
79  * Arguments   : size of block, in bytes.
80  * Returns     : pointer to allocated block.
81  *---------------------------------------------------------------------------*/
myAlloc(u32 size)82 void *myAlloc( u32 size )
83 {
84     void *ptr;
85 
86     ptr = MEMAllocFromAllocator(&DemoAllocator2, size);
87     ASSERTMSG(ptr, "Memory allocation failed\n");
88 
89     return(ptr);
90 }
91 
92 /*---------------------------------------------------------------------------*
93  * Name        : myFree
94  * Description : Callback needed by WPAD to free mem from MEM2 heap
95  * Arguments   : point to the block that should be freed.
96  * Returns     : Always 1.
97  *---------------------------------------------------------------------------*/
myFree(void * ptr)98 u8 myFree( void *ptr )
99 {
100     MEMFreeToAllocator(&DemoAllocator2, ptr);
101 
102     return(1);
103 }
104 
105 /*---------------------------------------------------------------------------*
106  * Name        : ExtensionCallback
107  * Description : Callback called when extension is installed/detached
108  * Arguments   : chan           controller channel
109                  result         device type
110  * Returns     : None.
111  *---------------------------------------------------------------------------*/
ExtensionCallback(s32 chan,s32 result)112 static void ExtensionCallback( s32 chan, s32 result )
113 {
114     const u32 dpd[] = {WPAD_DPD_EXP,          WPAD_DPD_STD,               WPAD_DPD_STD};
115     const u32 fmt[] = {WPAD_FMT_CORE_ACC_DPD, WPAD_FMT_FREESTYLE_ACC_DPD, WPAD_FMT_CLASSIC_ACC_DPD};
116 
117     if (result == WPAD_DEV_CORE || result == WPAD_DEV_FREESTYLE || result == WPAD_DEV_CLASSIC)
118     {
119         WPADControlDpd   (chan, dpd[result], NULL);
120         WPADSetDataFormat(chan, fmt[result]);
121     }
122 }
123 
124 /*---------------------------------------------------------------------------*
125  * Name        : ConnectCallback
126  * Description : Callback called when a controller connects/disconnects
127  * Arguments   : chan           controller channel
128                  reason         WPAD_ERR_NONE if open
129                                 WPAD_ERR_NO_CONTROLLER if close
130  * Returns     : None.
131  *---------------------------------------------------------------------------*/
ConnectCallback(s32 chan,s32 reason)132 static void ConnectCallback( s32 chan, s32 reason )
133 {
134     OSReport("ConnectCallback(%d) : %s\n", chan, (reason < 0) ? "disconnect" : "connect");
135 
136     if (reason == WPAD_ERR_NONE)
137     {
138         WPADSetExtensionCallback( chan, ExtensionCallback );
139         WPADControlDpd(chan, WPAD_DPD_EXP, NULL);
140         WPADSetDataFormat(chan, WPAD_FMT_CORE_ACC_DPD);
141     }
142 }
143 
144 
145 /*---------------------------------------------------------------------------*
146  * Name        : ReadCallback
147  * Description : Callback called when reading is done.
148  * Arguments   : chan           controller channel
149                  result         result code
150  * Returns     : None.
151  *---------------------------------------------------------------------------*/
ReadCallback(s32 chan,s32 result)152 static void ReadCallback( s32 chan, s32 result )
153 {
154     u32 ms;
155     OSTime t;
156     OSCalendarTime ct;
157     const u16 *p_name;
158     u8 title[16];
159     s32 len = 16;
160 
161     end[chan] = OSGetTime();
162     ms  = OSTicksToMilliseconds(OSDiffTick(end[chan], start[chan]));
163     OSReport("chan[%d] result ==> err = %d, bytes: %d, time(ms): %d\n", chan, result, WPAD_MEM_GAMEDATA_LEN, ms);
164 
165     WPADGetGameTitleUtf16(chan, &p_name);
166     WPADGetGameDataTimeStamp(chan, &t);
167     ENCConvertStringUtf16ToUtf8(title, &len, p_name, &len);
168 
169     OSTicksToCalendarTime(t, &ct);
170     OSReport("Title : %s, TimeStamp : %d/%d/%d %02d:%02d:%02d\n", title, ct.year, ct.mon+1, ct.mday, ct.hour, ct.min, ct.sec);
171 
172     if (!memcmp(txBuf[chan], rxBuf[chan], WPAD_MEM_GAMEDATA_LEN))
173     {
174         OSReport("\n == OK == \n\n");
175     }
176     else
177     {
178         OSReport("\n == NG == \n\n");
179     }
180 }
181 
182 /*---------------------------------------------------------------------------*
183  * Name        : WriteCallback
184  * Description : Callback called when writing is done.
185  * Arguments   : chan           controller channel
186                  result         result code
187  * Returns     : None.
188  *---------------------------------------------------------------------------*/
WriteCallback(s32 chan,s32 result)189 static void WriteCallback( s32 chan, s32 result )
190 {
191     u32 ms;
192 
193     end[chan] = OSGetTime();
194     ms  = OSTicksToMilliseconds(OSDiffTick(end[chan], start[chan]));
195     OSReport("chan[%d] result ==> err = %d, bytes: %d, time(ms): %d\n", chan, result, WPAD_MEM_GAMEDATA_LEN, ms);
196 
197     memory(chan, RDATA, rxBuf[chan], WPAD_MEM_GAMEDATA_LEN);
198 
199 }
200 
201 /*---------------------------------------------------------------------------*
202  * Name        : memory
203  * Description : Performs reading/writing user data
204  * Arguments   : chan           controller channel
205                  cmd            read or write
206                  p_buf          point to the data buffer
207                  len            data length
208  * Returns     : None.
209  *---------------------------------------------------------------------------*/
memory(s32 chan,u32 cmd,void * p_buf,u16 len)210 static void memory( s32 chan, u32 cmd, void *p_buf, u16 len )
211 {
212     s32 result;
213     const char *funcName[] = {
214         "WPADWriteGameData",
215         "WPADReadGameData",
216     };
217 
218     switch(cmd)
219     {
220         case WDATA: result = WPADWriteGameData(chan, p_buf, len, 0, WriteCallback);   break;
221         case RDATA: result = WPADReadGameData (chan, p_buf, len, 0, ReadCallback);    break;
222     }
223     if (result == WPAD_ERR_NONE)
224     {
225         start[chan] = OSGetTime();
226     }
227 
228     OSReport("chan[%d] %s : %d\n", chan, funcName[cmd], result);
229 }
230 
231 /*---------------------------------------------------------------------------*
232  * Name        : PrintIntro
233  * Description : Print introduction
234  * Arguments   : None.
235  * Returns     : None.
236  *---------------------------------------------------------------------------*/
PrintIntro(void)237 static void PrintIntro( void )
238 {
239     OSReport("+------------ WPADMEM Sample Demo Program ------------+\n");
240     OSReport(" This is a demo program to access embedded memory    \n");
241     OSReport(" of Wii remote controller assigned to WPAD_CHAN0.    \n");
242     OSReport("+-----------------------------------------------------+\n");
243     OSReport(" MENU:                                               \n");
244     OSReport(" A button: Write game data to   Wii remote controller\n");
245     OSReport(" B button: Read  game data from Wii remote controller\n");
246     OSReport("+-----------------------------------------------------+\n");
247 }
248 
249 
250 /*---------------------------------------------------------------------------*
251  * Name        : main
252  * Description :
253  * Arguments   : None.
254  * Returns     : None.
255  *---------------------------------------------------------------------------*/
main(void)256 void main( void )
257 {
258     s32 bb_stat;
259     u32 type;
260     s32 chan;
261     int i;
262     u16 curr[WPAD_MAX_CONTROLLERS] = {0, 0, 0, 0};
263     u16 prev[WPAD_MAX_CONTROLLERS] = {0, 0, 0, 0};
264     WPADStatus status[WPAD_MAX_CONTROLLERS];
265 
266     const char *utf8_title = { "Wii Sample Demo" };  // UTF-8
267     u16 utf16_title[16];
268     s32 len  = (s32)strlen(utf8_title);
269 
270     OSInit();
271     DEMOInit( NULL );
272 
273     // register allocator for stack before WPADInit().
274     WPADRegisterAllocator(myAlloc, myFree);
275     // Initialize WPAD.
276     WPADInit();
277 
278     for(i=0;i<WPAD_MAX_CONTROLLERS; i++)
279     {
280         WPADSetConnectCallback(i, ConnectCallback);
281     }
282 
283     // wait that BT stack is enabled
284     do {
285         bb_stat = WPADGetStatus();
286     } while (bb_stat != WPAD_STATE_SETUP);
287 
288     // create data
289     for(chan=0; chan<WPAD_MAX_CONTROLLERS; chan++)
290     {
291         for(i=0; i<WPAD_MEM_GAMEDATA_LEN; i++)
292         {
293             txBuf[chan][i] = (u8)(i+chan);
294         }
295     }
296 
297     // set game title
298     memset(utf16_title, 0, sizeof(utf16_title));
299     ENCConvertStringUtf8ToUtf16(utf16_title, &len, (const u8*)utf8_title, &len);
300     WPADSetGameTitleUtf16(utf16_title);
301 
302     // display menu
303     PrintIntro();
304 
305     // main loop
306     while( 1 )
307     {
308         for(chan=0; chan<WPAD_MAX_CONTROLLERS; chan++)
309         {
310             if (WPADProbe(chan, &type) != WPAD_ERR_NO_CONTROLLER)
311             {
312                 WPADRead(chan, &status[chan]);
313                 if (status[chan].err == WPAD_ERR_NONE
314                 ||  status[chan].err == WPAD_ERR_CORRUPTED)
315                 {
316                     curr[chan] = status[chan].button;
317                 }
318             }
319 
320             if (WPADButtonDown(prev[chan], curr[chan]) & WPAD_BUTTON_A)
321             {
322                 memory(chan, WDATA, txBuf[chan], WPAD_MEM_GAMEDATA_LEN);
323             }
324             if (WPADButtonDown(prev[chan], curr[chan]) & WPAD_BUTTON_B)
325             {
326                 memory(chan, RDATA, rxBuf[chan], WPAD_MEM_GAMEDATA_LEN);
327             }
328             prev[chan] = curr[chan];
329         }
330     }
331 
332 }
333 
334 
335