1 /*---------------------------------------------------------------------------*
2   Project:    WPAD demo program
3   File:       pointing.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: pointing.c,v $
15   Revision 1.8  06/16/2006 14:10:56  ekwon
16   Ensured that WPADProbe() is used to check channel status and to update device type.
17 
18   Revision 1.7  06/13/2006 04:55:58  tojo
19   (none)
20 
21   Revision 1.6  06/13/2006 01:57:12  ekwon
22   Pointing demo.
23 
24   Revision 1.1  06/01/2006 00:40:11  hiratsu
25   Moved from $(SDK)/build/demos/wpaddemo
26 
27   Revision 1.4  2006/03/13 02:10:46  yasuh-to
28   Modified copyright.
29 
30  *---------------------------------------------------------------------------*/
31 
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stddef.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <ctype.h>
38 
39 #include <revolution.h>
40 #include <revolution/wpad.h>
41 
42 #define DEMO_USE_MEMLIB=1 // This turns on the DEMO library's MEM heaps.
43 #include <demo.h>
44 
45 
46 
47 #define SCREEN_WIDTH  320
48 #define SCREEN_HEIGHT 240
49 
50 
51 
52 // MEM2 memory allocation routines. The application must provide these to
53 // WPAD, so it can setup the data transfer buffer. This buffer must reside
54 // in MEM2.
55 static void *myAlloc                 (u32 size);
56 static u8    myFree                  (void *ptr);
57 
58 static void initialize            (void);
59 static void renderLuminousSources (const WPADStatus *stat);
60 static void renderStatus          (const WPADStatus *stat);
61 static void renderAiming          (const WPADStatus *stat);
62 static void getMidpoint           (const WPADStatus *stat, s16 *x, s16 *y );
63 
64 
65 
66 /*===========================================================================*
67  *                   F U N C T I O N    D E F I N I T I O N S
68  *===========================================================================*/
69 
70 
71 /*---------------------------------------------------------------------------*
72  * Name        : main()
73  * Description :
74  * Arguments   : None.
75  * Returns     : None.
76  *---------------------------------------------------------------------------*/
77 
main(void)78 int main( void )
79 {
80 
81     WPADStatus wpad;
82 
83     s32 wpad_state;
84 
85     s32 status;
86     u32 type;
87 
88 
89         initialize();
90 
91         // we should clear the WPADStatus block returned by
92         // WPADRead(), because if no channel is connected, nothing
93         // is copied. So we would be staring at garbage data.
94         memset( (void *)(&wpad), 0, sizeof(WPADStatus));
95 
96         // - We must now register memory allocation/free functions
97         //   for MEM2.
98         // - WPAD requires some memory in MEM2 for data transfers
99         //   between the controller and WPAD driver stack.
100         // - Memory allocation only occurs once, at the initialization.
101         // - Memory usage is on the order of 1KB.
102         // - NOTE: We are using the MEM library allocators defined by
103         //   the DEMO library.
104         //
105         WPADRegisterAllocator(myAlloc, myFree);
106 
107 
108         // Initialize WPAD!
109         WPADInit();
110 
111         // The WPAD initialization process is asynchronous.
112         // So we should wait until it's completed.
113         do
114         {
115             wpad_state = WPADGetStatus();
116 
117         } while (WPAD_STATE_SETUP != wpad_state);
118 
119 
120 
121         // Main loop
122         while( 1 )
123         {
124 
125             status = WPADProbe(WPAD_CHAN0, &type);
126 
127             WPADRead( WPAD_CHAN0, &wpad );
128 
129             if (WPAD_ERR_NONE == status)
130             {
131 
132                 // A controller is connected. Is it the correct type?
133                 if ((WPAD_DEV_CORE == type) || (WPAD_DEV_FREESTYLE == type))
134                 {
135                     // yes, it's the right kind of controller.
136                     // now check if DPD/ACC are enabled...
137                     if (FALSE == WPADIsDpdEnabled(WPAD_CHAN0))
138                     {
139                         // if not, then set the format and turn on DPD and accelerometer
140                         WPADControlDpd(WPAD_CHAN0, WPAD_DPD_EXP, NULL);
141                         WPADSetDataFormat(WPAD_CHAN0, WPAD_FMT_CORE_ACC_DPD);
142 
143                     } // if DPD enabled...
144 
145                 } // if correct device type
146 
147             } // if controller is connected ok
148 
149 
150             DEMOBeforeRender();
151             renderLuminousSources( &wpad );
152             renderStatus( &wpad );
153             renderAiming( &wpad );
154             DEMODoneRender();
155 
156         } // while(1)
157 
158 
159         return 0;
160 
161 } // end
162 
163 
164 /*---------------------------------------------------------------------------*
165  * Name        : myAlloc()
166  * Description : Callback needed by WPAD to allocate mem from MEM2 heap
167  * Arguments   : size of block, in bytes.
168  * Returns     : pointer to allocated block.
169  *---------------------------------------------------------------------------*/
myAlloc(u32 size)170 static void *myAlloc(u32 size)
171 {
172     void *ptr;
173 
174     ptr = MEMAllocFromAllocator(&DemoAllocator2, size);
175     ASSERTMSG(ptr, "Memory allocation failed\n");
176 
177     return(ptr);
178 
179 } // myAlloc()
180 
181 /*---------------------------------------------------------------------------*
182  * Name        : myFree()
183  * Description : Callback needed by WPAD to free mem from MEM2 heap
184  * Arguments   : None.
185  * Returns     : Always 1.
186  *---------------------------------------------------------------------------*/
myFree(void * ptr)187 static u8 myFree(void *ptr)
188 {
189 
190     MEMFreeToAllocator(&DemoAllocator2, ptr);
191 
192     // we should ensure that memory is free'd properly, but oh well
193     return(1);
194 
195 } // myFree()
196 
197 /*---------------------------------------------------------------------------*
198  * Name        : initialize()
199  * Description :
200  * Arguments   : None.
201  * Returns     : None.
202  *---------------------------------------------------------------------------*/
initialize(void)203 static void initialize( void )
204 {
205     const GXColor DARKBLUE = { 0, 0, 40, 255 };
206 
207 
208         OSInit();
209 
210         DEMOInit( &GXNtsc480IntDf );
211         GXSetCopyClear( DARKBLUE, GX_MAX_Z24 );
212         GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
213         DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT );
214         GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE );                       // Set pixel processing mode
215         GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );    // Translucent mode
216 
217 } // end
218 
219 /*---------------------------------------------------------------------------*
220  * Name        : renderLuminousSources()
221  * Description :
222  * Arguments   : None.
223  * Returns     : None.
224  *---------------------------------------------------------------------------*/
renderLuminousSources(const WPADStatus * stat)225 static void renderLuminousSources(const WPADStatus *stat)
226 {
227     int i;
228 
229         for( i = 0; i < 2; ++i )
230         {
231             s16 x = (s16)( stat->obj[i].x*SCREEN_WIDTH/WPAD_DPD_IMG_RESO_WX  );
232             s16 y = (s16)( stat->obj[i].y*SCREEN_HEIGHT/WPAD_DPD_IMG_RESO_WY );
233             DEMOPrintf( x, y, 0, "O" );
234         }
235 
236 } // end
237 
238 /*---------------------------------------------------------------------------*
239  * Name        : renderStatus()
240  * Description :
241  * Arguments   : None.
242  * Returns     : None.
243  *---------------------------------------------------------------------------*/
renderStatus(const WPADStatus * stat)244 static void renderStatus(const WPADStatus *stat)
245 {
246     const int FONT_HEIGHT = 8;
247     s16 x = FONT_HEIGHT;
248     s16 y = FONT_HEIGHT;
249     int i;
250 
251         y+=FONT_HEIGHT;
252         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "DPD-ID     X    Y SIZE");
253 
254         for( i=0; i<WPAD_DPD_MAX_OBJECTS; ++i )
255         {
256             const DPDObject *p = &( stat->obj[i] );
257 
258 
259                 DEMOPrintf( x, y+=FONT_HEIGHT, 0, "%1d       %4d %4d  %3d", p->traceId, p->x, p->y, p->size );
260 
261         }
262 
263         y+=FONT_HEIGHT;
264         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "Controller Type: %d", stat->dev );
265         DEMOPrintf( x, y+=FONT_HEIGHT, 0, "ERROR Info     : %d", stat->err );
266 
267         if (WPAD_ERR_NO_CONTROLLER == stat->err)
268         {
269             y+=FONT_HEIGHT;
270             y+=FONT_HEIGHT;
271             DEMOPrintf(x, y+=FONT_HEIGHT, 0, ">> No controller is connected!");
272             DEMOPrintf(x, y+=FONT_HEIGHT, 0, ">> Please press a button on a paired");
273             DEMOPrintf(x, y+=FONT_HEIGHT, 0, ">> controller to connect.");
274         }
275 
276 
277 } // end
278 
279 /*---------------------------------------------------------------------------*
280  * Name        : renderAiming()
281  * Description :
282  * Arguments   : Pointer to latest WPADStatus block.
283  * Returns     : None.
284  *---------------------------------------------------------------------------*/
285 
renderAiming(const WPADStatus * stat)286 static void renderAiming( const WPADStatus *stat )
287 {
288 	s16 x;
289 	s16 y;
290 
291 
292 	    getMidpoint( stat, &x, &y );
293 
294 	    x=(s16)((WPAD_DPD_IMG_RESO_WX - x)*SCREEN_WIDTH /WPAD_DPD_IMG_RESO_WX);
295 	    y=(s16)((WPAD_DPD_IMG_RESO_WY - y)*SCREEN_HEIGHT/WPAD_DPD_IMG_RESO_WY);
296 
297         DEMOPrintf( x, y, 0, "+" );
298 
299 
300 } // end
301 
302 /*---------------------------------------------------------------------------*
303  * Name        : getMidpoint()
304  * Description :
305  * Arguments   : Pointer to latest WPADStatus block.
306  *               Pointer to X value.
307  *               Pointer to Y value.
308  * Returns     : None.
309  *---------------------------------------------------------------------------*/
310 
getMidpoint(const WPADStatus * stat,s16 * x,s16 * y)311 static void getMidpoint( const WPADStatus *stat, s16 *x, s16 *y )
312 {
313 	static int s_prevX[2];
314 	static int s_prevY[2];
315 	static int s_width;
316 
317     // Compute pointing position from obj data
318     // We assume [0] means left, [1] means right.
319     int cx[2];
320     int cy[2];
321     int i;
322 
323 
324         if((stat->obj[0].size > 0) && (stat->obj[1].size > 0))
325         {
326             for(i=0; i<2; ++i)
327             {
328                 cx[i]=stat->obj[i].x;
329                 cy[i]=stat->obj[i].y;
330             }
331 
332             // swap.
333             if(cx[0] > cx[1])
334             {
335                 int tmp=cx[0];
336                 cx[0]=cx[1];
337                 cx[1]=tmp;
338                 tmp=cy[0];
339                 cy[0]=cy[1];
340                 cy[1]=tmp;
341             }
342 
343             for(i=0; i<2; ++i)
344             {
345                 s_prevX[i]=cx[i];
346                 s_prevY[i]=cy[i];
347             }
348             s_width=cx[1]-cx[0];
349         }
350         else if(stat->obj[0].size > 1)
351         {
352             int x0=stat->obj[0].x;
353             int y0=stat->obj[0].y;
354             f32 diff0=(s_prevX[0]-x0)*(s_prevX[0]-x0)+(s_prevY[0]-y0)*(s_prevY[0]-y0);
355             f32 diff1=(s_prevX[1]-x0)*(s_prevX[1]-x0)+(s_prevY[1]-y0)*(s_prevY[1]-y0);
356             if(diff0 < diff1)
357             {
358                 // current [0] is previous [0].  We create [1] data by computation.
359                 cx[0]=x0;
360                 cy[0]=y0;
361                 cx[1]=cx[0]+s_width;
362                 cy[1]=s_prevY[1];
363                 for(i=0; i<2; ++i){
364                     s_prevX[i]=cx[i];
365                     s_prevY[i]=cy[i];
366                 }
367             }
368             else
369             {
370                 // current [0] is previous [1].
371                 cx[1]=x0;
372                 cy[1]=y0;
373                 cx[0]=cx[1]-s_width;
374                 cy[0]=s_prevY[1];
375                 for(i=0; i<2; ++i){
376                     s_prevX[i]=cx[i];
377                     s_prevY[i]=cy[i];
378                 }
379             }
380         }
381         else
382         {
383             for(i=0; i<2; ++i)
384             {
385                 cx[i]=s_prevX[i];
386                 cy[i]=s_prevY[i];
387             }
388         }
389 
390    	    *x = (s16)((cx[0]+cx[1])/2);
391    	    *y = (s16)((cy[0]+cy[1])/2);
392 
393 } // end
394