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