1 /*---------------------------------------------------------------------------*
2   Project:    WPAD demo program
3   File:       simple.c
4   Programmer: HIRATSU Daisuke
5 
6   Copyright (C) 2005-2006 Nintendo.  All rights reserved.
7 
8   These coded instructions, statements, and computer programs contain
9   proprietary information of Nintendo of America Inc. and/or Nintendo
10   Company Ltd., and are protected by Federal copyright law.  They may
11   not be disclosed to third parties or copied or duplicated in any form,
12   in whole or in part, without the prior written consent of Nintendo.
13 
14   $Log: simple.c,v $
15   Revision 1.19  08/11/2006 09:33:13  tojo
16   (none)
17 
18   Revision 1.18  08/03/2006 13:33:02  tojo
19   Removed old APIs.
20 
21   Revision 1.17  07/20/2006 06:40:35  tojo
22   (none)
23 
24   Revision 1.16  06/16/2006 14:10:56  ekwon
25   Ensured that WPADProbe() is used to check channel status and to update device type.
26 
27   Revision 1.15  06/13/2006 04:54:59  tojo
28   (none)
29 
30   Revision 1.14  06/13/2006 01:57:26  ekwon
31   Minor cleanup.
32 
33   Revision 1.13  06/12/2006 12:03:28  ekwon
34   Fixes for querying DPD status before enabling DPD.
35 
36   Revision 1.12  06/12/2006 08:22:11  ekwon
37   Added some comments.
38 
39   Revision 1.11  06/12/2006 07:18:02  ekwon
40   Initial check-in for WPAD SIMPLE demo. Revised to support new WPAD driver.
41 
42   Revision 1.1  06/01/2006 00:40:11  hiratsu
43   Moved from $(SDK)/build/demos/wpaddemo
44 
45   Revision 1.9  2006/03/13 12:18:57  yasuh-to
46   Added comment for how to use demo.
47 
48   Revision 1.8  2006/03/13 02:10:46  yasuh-to
49   Modified copyright.
50 
51  *---------------------------------------------------------------------------*/
52 
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stddef.h>
56 #include <stdarg.h>
57 #include <stdio.h>
58 #include <ctype.h>
59 
60 #include <revolution.h>
61 #include <revolution/wpad.h>
62 
63 #define DEMO_USE_MEMLIB=1 // This turns on the DEMO library's MEM heaps.
64 #include <demo.h>
65 
66 
67 
68 #define SCREEN_WIDTH  320
69 #define SCREEN_HEIGHT 240
70 
71 
72 
73 // MEM2 memory allocation routines. The application must provide these to
74 // WPAD, so it can setup the data transfer buffer. This buffer must reside
75 // in MEM2.
76 static void *myAlloc                 (u32 size);
77 static u8    myFree                  (void *ptr);
78 
79 static void  initialize              ( void );
80 static void  renderLuminousSources   ( WPADStatus *stat );
81 static void  renderStatus            ( WPADStatus *stat );
82 
83 
84 /*===========================================================================*
85  *                   F U N C T I O N    D E F I N I T I O N S
86  *===========================================================================*/
87 
88 
89 /*---------------------------------------------------------------------------*
90  * Name        : main()
91  * Description :
92  * Arguments   : None.
93  * Returns     : None.
94  *---------------------------------------------------------------------------*/
main(void)95 int main( void )
96 {
97     WPADStatus wpad;
98 
99     s32 wpad_state;
100 
101     s32 status;
102     u32 type;
103 
104         initialize();
105 
106         // we should clear the WPADStatus block returned by
107         // WPADRead(), because if no channel is connected, nothing
108         // is copied. So we would be staring at garbage data.
109         memset( (void *)(&wpad), 0, sizeof(WPADStatus));
110 
111         // - We must now register memory allocation/free functions
112         //   for MEM2.
113         // - WPAD requires some memory in MEM2 for data transfers
114         //   between the controller and WPAD driver stack.
115         // - Memory allocation only occurs once, at the initialization.
116         // - Memory usage is on the order of 1KB.
117         // - NOTE: We are using the MEM library allocators defined by
118         //   the DEMO library.
119         //
120         WPADRegisterAllocator(myAlloc, myFree);
121 
122 
123         // Initialize WPAD!
124         WPADInit();
125 
126 
127         // The WPAD initialization process is asynchronous.
128         // So we should wait until it's completed.
129         do
130         {
131             wpad_state = WPADGetStatus();
132 
133         } while (WPAD_STATE_SETUP != wpad_state);
134 
135 
136         // Main loop
137         while(1)
138         {
139 
140 
141             // We should probe the channel first
142             status = WPADProbe(WPAD_CHAN0, &type);
143 
144             // is a controller connected?
145             if(WPAD_ERR_NONE == status)
146             {
147 
148                 // Read data/status from channel 0.
149                 WPADRead( WPAD_CHAN0, &wpad );
150 
151 
152                 // Note: If the controller has disconnected and re-connected,
153                 // we need to reset and re-enable the DPD and accelerometers.
154                 // But we have to ensure that the device type is correct, because
155                 // it's possible a different type of device has connected on channel 0.
156                 if ((WPAD_DEV_CORE == type) || (WPAD_DEV_FREESTYLE == type))
157                 {
158 
159                     // Are the DPD and Accelerometers enabled?
160                     if (FALSE == WPADIsDpdEnabled(WPAD_CHAN0))
161                     {
162                         // if not, then set the format and turn on DPD and accelerometer
163                         WPADControlDpd(WPAD_CHAN0, WPAD_DPD_EXP, NULL);
164                         WPADSetDataFormat(WPAD_CHAN0, WPAD_FMT_CORE_ACC_DPD);
165                     }
166 
167                     if( wpad.button & WPAD_BUTTON_A )
168                     {
169                         WPADStartMotor( WPAD_CHAN0 );
170                     }
171                     if( wpad.button & WPAD_BUTTON_B )
172                     {
173                         WPADStopMotor( WPAD_CHAN0 );
174                     }
175 
176                 } // if device type is correct...
177 
178             } // if no error...
179 
180 
181             DEMOBeforeRender();
182             renderLuminousSources( &wpad );
183             renderStatus( &wpad );
184 
185             DEMOPrintf( 16, 184, 0, "press     A: Start Motor\n");
186             DEMOPrintf( 16, 200, 0, "press     B: Stop  Motor\n");
187 
188             DEMODoneRender();
189 
190         } // while
191 
192         return 0;
193 
194 } // end main
195 
196 /*---------------------------------------------------------------------------*
197  * Name        : myAlloc()
198  * Description : Callback needed by WPAD to allocate mem from MEM2 heap
199  * Arguments   : size of block, in bytes.
200  * Returns     : pointer to allocated block.
201  *---------------------------------------------------------------------------*/
myAlloc(u32 size)202 static void *myAlloc(u32 size)
203 {
204     void *ptr;
205 
206     ptr = MEMAllocFromAllocator(&DemoAllocator2, size);
207     ASSERTMSG(ptr, "Memory allocation failed\n");
208 
209     return(ptr);
210 
211 } // myAlloc()
212 
213 /*---------------------------------------------------------------------------*
214  * Name        : myFree()
215  * Description : Callback needed by WPAD to free mem from MEM2 heap
216  * Arguments   : None.
217  * Returns     : Always 1.
218  *---------------------------------------------------------------------------*/
myFree(void * ptr)219 static u8 myFree(void *ptr)
220 {
221 
222     MEMFreeToAllocator(&DemoAllocator2, ptr);
223 
224     // we should ensure that memory is free'd properly, but oh well
225     return(1);
226 
227 } // myFree()
228 
229 /*---------------------------------------------------------------------------*
230  * Name        : initialize()
231  * Description : Performs basic system initialization.
232  * Arguments   : None.
233  * Returns     : None.
234  *---------------------------------------------------------------------------*/
235 
initialize(void)236 static void initialize( void )
237 {
238     const GXColor DARKBLUE = { 0, 0, 40, 255 };
239 
240         OSInit();
241 
242         DEMOInit( &GXNtsc480IntDf );
243 
244         GXSetCopyClear( DARKBLUE, GX_MAX_Z24 );
245         GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
246         DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT );
247         GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE );                       // Set pixel processing mode
248         GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );    // Translucent mode
249 
250 } // end
251 
252 /*---------------------------------------------------------------------------*
253  * Name        : renderLuminousSources()
254  * Description : Draws sources as "seen" by controller.
255  * Arguments   : Pointer to current WPADStatus.
256  * Returns     : None.
257  *---------------------------------------------------------------------------*/
renderLuminousSources(WPADStatus * stat)258 static void renderLuminousSources( WPADStatus *stat )
259 {
260     int i = 0;
261 
262         // we'll pay attention to the first 2 sources
263         for( i = 0; i < 2; ++i )
264         {
265             s16 x = (s16)( stat->obj[i].x*SCREEN_WIDTH/WPAD_DPD_IMG_RESO_WX  );
266             s16 y = (s16)( stat->obj[i].y*SCREEN_HEIGHT/WPAD_DPD_IMG_RESO_WY );
267             DEMOPrintf( x, y, 0, "*" );
268         }
269 
270 } // end
271 
272 /*---------------------------------------------------------------------------*
273  * Name        : renderStatus()
274  * Description : Prints interesting data from WPADStatus.
275  * Arguments   : Pointer to current WPADStatus.
276  * Returns     : None.
277  *---------------------------------------------------------------------------*/
278 
renderStatus(WPADStatus * stat)279 static void renderStatus( WPADStatus *stat )
280 {
281     const int FONT_HEIGHT = 8;
282     char buf[] = "___________";
283     s16 x = FONT_HEIGHT;
284     s16 y = FONT_HEIGHT;
285     int i = 0;
286 
287         // just print accelerometer data
288         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "accX   :  %d", stat->accX );
289         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "accY   :  %d", stat->accY );
290         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "accZ   :  %d", stat->accZ );
291 
292         if( stat->button & WPAD_BUTTON_RIGHT  ) buf[0] = '>';
293         if( stat->button & WPAD_BUTTON_DOWN   ) buf[1] = 'v';
294         if( stat->button & WPAD_BUTTON_UP     ) buf[2] = '^';
295         if( stat->button & WPAD_BUTTON_LEFT   ) buf[3] = '<';
296         if( stat->button & WPAD_BUTTON_START  ) buf[4] = 'S';
297         if( stat->button & WPAD_BUTTON_SELECT ) buf[5] = 'T';
298         if( stat->button & WPAD_BUTTON_A      ) buf[7] = 'A';
299         if( stat->button & WPAD_BUTTON_B      ) buf[6] = 'B';
300         if( stat->button & WPAD_BUTTON_SMALL_A) buf[8] = 'a';
301         if( stat->button & WPAD_BUTTON_SMALL_B) buf[9] = 'b';
302         if( stat->button & WPAD_BUTTON_HOME   ) buf[10]= 'H';
303 
304         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "Buttons: [%s]",buf);
305         y+=FONT_HEIGHT;
306         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "DPD-ID     X    Y SIZE");
307 
308         for( i=0; i<WPAD_DPD_MAX_OBJECTS; ++i )
309         {
310             const DPDObject *p = &( stat->obj[i] );
311 
312 
313                 DEMOPrintf( x, y+=FONT_HEIGHT, 0, "%1d       %4d %4d  %3d", p->traceId, p->x, p->y, p->size );
314 
315         }
316 
317 
318         y+=FONT_HEIGHT;
319         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "Controller Type: %d", stat->dev );
320         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "ERROR Info     : %d", stat->err );
321 
322         if (WPAD_ERR_NO_CONTROLLER == stat->err)
323         {
324             y+=FONT_HEIGHT;
325             y+=FONT_HEIGHT;
326             DEMOPrintf(x, y+=FONT_HEIGHT, 0, ">> No controller is connected!");
327             DEMOPrintf(x, y+=FONT_HEIGHT, 0, ">> Please press a button on a paired");
328             DEMOPrintf(x, y+=FONT_HEIGHT, 0, ">> controller to connect.");
329         }
330 
331 
332 
333 } // end
334