1 /*---------------------------------------------------------------------------*
2   Project:     KPAD Sample Program
3   File:        sample.c
4   Programmer:  Keizo Ohta
5                HIRATSU Daisuke
6                Tojo Haruki
7 
8   Copyright 2005-2008 Nintendo. All rights reserved.
9 
10   These coded instructions, statements, and computer programs contain
11   proprietary information of Nintendo of America Inc. and/or Nintendo
12   Company Ltd., and are protected by Federal copyright law. They may
13   not be disclosed to third parties or copied or duplicated in any form,
14   in whole or in part, without the prior written consent of Nintendo.
15  *---------------------------------------------------------------------------*/
16 
17 #include <revolution.h>
18 #include <math.h>
19 #include <stdio.h>
20 
21 #include <revolution/kpad.h>
22 #include "main.h"
23 #include "kfont.h"
24 #include "graphic.h"
25 #include "sample.h"
26 
27 
28 /***************************************************************
29     Definitions
30 ***************************************************************/
31 #define CMD_LEFT        ( (kpads[ 0 ][ 0 ].trig & KPAD_BUTTON_LEFT ) != 0 ) // Cursor movement
32 #define CMD_RIGHT       ( (kpads[ 0 ][ 0 ].trig & KPAD_BUTTON_RIGHT) != 0 )
33 #define CMD_UP          ( (kpads[ 0 ][ 0 ].trig & KPAD_BUTTON_UP   ) != 0 )
34 #define CMD_DOWN        ( (kpads[ 0 ][ 0 ].trig & KPAD_BUTTON_DOWN ) != 0 )
35 
36 #define CMD_INC         ( (kpads[ 0 ][ 0 ].trig & KPAD_BUTTON_A    ) != 0 ) // Increase/decrease values
37 #define CMD_DEC         ( (kpads[ 0 ][ 0 ].trig & KPAD_BUTTON_B    ) != 0 )
38 
39 #define CMD_ENABLE_DPD  ( (kpads[0][0].trig & KPAD_BUTTON_1    ) != 0 ) // DPD ON/OFF
40 #define CMD_DISABLE_DPD ( (kpads[0][0].trig & KPAD_BUTTON_2    ) != 0 )
41 
42 #define BTN_CALIBRATE   ( KPAD_BUTTON_PLUS | KPAD_BUTTON_MINUS )        // Calibration operation
43 #define CMD_CALIBRATE   ( (kpads[0][0].hold & BTN_CALIBRATE) == BTN_CALIBRATE && kpads[0][0].trig )
44 
45 #define CMD_AIMMODE     ( (kpads[ 0 ][ 0 ].trig & KPAD_BUTTON_HOME ) != 0 )
46 
47 #define CMD_STICK_CLAMP_HOLD1 ( ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_FREESTYLE || \
48                                   kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_MPLS_FREESTYLE ) && \
49                                 ( kpads[ 0 ][ 0 ].hold & KPAD_BUTTON_Z ) != 0 )
50 #define CMD_STICK_CLAMP_HOLD2 ( ( ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_CLASSIC ) || \
51                                   ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_GUITAR  ) || \
52                                   ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_DRUM    ) || \
53                                   ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_TAIKO   ) || \
54                                   ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_MPLS_CLASSIC ) ) && \
55                                 ( kpads[ 0 ][ 0 ].ex_status.cl.hold & KPAD_CL_BUTTON_PLUS ) != 0 )
56 
57 #define CMD_STICK_CLAMP_TRIG1 ( ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_FREESTYLE || \
58                                   kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_MPLS_FREESTYLE ) && \
59                                 ( kpads[ 0 ][ 0 ].trig & KPAD_BUTTON_C ) != 0 )
60 #define CMD_STICK_CLAMP_TRIG2 ( ( ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_CLASSIC ) || \
61                                   ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_GUITAR  ) || \
62                                   ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_DRUM    ) || \
63                                   ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_TAIKO   ) || \
64                                   ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_MPLS_CLASSIC ) ) && \
65                                 ( kpads[ 0 ][ 0 ].ex_status.cl.trig & KPAD_CL_BUTTON_MINUS ) != 0 )
66 
67 
68 /***************************************************************
69  Adjustments
70 ***************************************************************/
71 static f32 pointing_scale = 200.0f ; // Screen pointing scale
72 
73 static f32 obj_interval     = 0.20f ; // Distance between TV-side light emitters (in meters)
74 
75 static f32 pos_play_radius  = 0.00f ; // 'pos' sensitivity setting
76 static f32 pos_sensitivity  = 1.00f ;
77 static f32 pos_play_mode    = (f32)KPAD_PLAY_MODE_LOOSE ;
78 static f32 hori_play_radius = 0.00f ; // 'horizon' sensitivity setting
79 static f32 hori_sensitivity = 1.00f ;
80 static f32 hori_play_mode   = (f32)KPAD_PLAY_MODE_LOOSE ;
81 static f32 dist_play_radius = 0.00f ; // 'dist' sensitivity setting
82 static f32 dist_sensitivity = 1.00f ;
83 static f32 dist_play_mode   = KPAD_PLAY_MODE_LOOSE ;
84 static f32 acc_play_radius  = 0.00f ; // 'acc' sensitivity setting
85 static f32 acc_sensitivity  = 1.00f ;
86 static f32 acc_play_mode    = KPAD_PLAY_MODE_LOOSE ;
87 
88 static f32 repeat_delay_sec = 0.75f ; // Key repeat settings
89 static f32 repeat_pulse_sec = 0.25f ;
90 
91 #define EDIT_DATA_MAX 16 // Edit data count
92 
93 typedef struct {
94     f32 *vp ;   // Pointer to the variable
95     f32 min ;   // Variable minimum value
96     f32 max ;   // Variable maximum value
97     u8  y ;     // Y-cursor position
98     u8  x[3] ;  // X-cursor position for each digit
99     f32 v[3] ;  // Value change amount for each digit
100 } EditData ;
101 
102 static EditData  edit_data[ EDIT_DATA_MAX ] = {
103     { &  pointing_scale, 0.0f,900.0f,  3, {10,11,12}, {100.0f, 10.0f, 1.0f} },
104     { &    obj_interval, 0.00f,9.00f,  5, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
105     { & pos_play_radius, 0.00f,9.00f,  8, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
106     { & pos_sensitivity, 0.00f,1.00f,  8, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
107     { & pos_play_mode,   0.00f,1.00f,  8, {14,14,14}, {1.00f, 1.00f, 1.00f} },
108     { &hori_play_radius, 0.00f,9.00f,  9, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
109     { &hori_sensitivity, 0.00f,1.00f,  9, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
110     { &hori_play_mode,   0.00f,1.00f,  9, {14,14,14}, {1.00f, 1.00f, 1.00f} },
111     { &dist_play_radius, 0.00f,9.00f, 10, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
112     { &dist_sensitivity, 0.00f,1.00f, 10, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
113     { &dist_play_mode,   0.00f,1.00f, 10, {14,14,14}, {1.00f, 1.00f, 1.00f} },
114     { & acc_play_radius, 0.00f,9.00f, 11, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
115     { & acc_sensitivity, 0.00f,1.00f, 11, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
116     { & acc_play_mode,   0.00f,1.00f, 11, {14,14,14}, {1.00f, 1.00f, 1.00f} },
117     { &repeat_delay_sec, 0.00f,9.00f, 14, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
118     { &repeat_pulse_sec, 0.00f,9.00f, 14, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
119 } ;
120 
121 
122 /***************************************************************
123  Variables
124 ***************************************************************/
125 static const f32 O1Y = -1.5f;
126 static const f32 O2Y = -0.5f;
127 static const f32 O3Y = -1.0f;
128 static const f32 O4Y = -20.8f;
129 static const f32 O5Y = -20.8f;
130 static const f32 O6Y = -1.0f;
131 
132 
133 static s32 csr_x, csr_y ;   // Value adjustment cursor position
134 static s32 csr_i, csr_k ;   // Position of data index and digit currently being edited
135 static s32 calib_disp_ct ;  // Calibration message display count
136 
137 static f32 dpd_disp_scale = 140.0f ; // DPD object display scale
138 static f32 dpd_disp_ox    = 205.0f ; // DPD object display position
139 static f32 dpd_disp_oy    =  65.0f+O5Y ;
140 
141 static BOOL dpd_mode ;
142 static BOOL aim_mode ;
143 static BOOL stick_clamp_mode ;
144 static BOOL stick_clamp_mode_work ;
145 static BOOL reset_request ;
146 
147 static WPADInfo              wpad_info ;
148 static KPADUnifiedWpadStatus unified_status[ KPAD_BUF_SIZE * 2 ] ;
149 
150 static int rev  ;
151 static int init ;
152 static u8  btn  ;
153 
154 s32              MyCallbackLatestIdx[ MY_CALLBACK_MAX ] = { -1, -1 } ;
155 MyCallbackStatus MyCallbackStatusBuf[ MY_CALLBACK_MAX ][ MY_START_COUNTS_MAX ] ;
156 vu32             MySamplingCount ;
157 char            *MyCbName[ MY_CALLBACK_MAX ] = { "DPDCB", "MPLSCB" } ;
158 
159 
160 /*******************************************************************************
161  Initialization function
162 *******************************************************************************/
init_sample(void)163 void init_sample( void )
164 {
165     //----- Initialize KPAD
166     WPADRegisterAllocator( alloc32, free32 ) ;
167     KPADInit() ;            // Controllers
168     KPADSetControlDpdCallback( 0, dpd_callback ) ;
169     KPADSetControlMplsCallback( 0, mpls_callback ) ;
170     KPADSetSamplingCallback( 0, sampling_callback ) ;
171 
172     //----- Default controller settings
173     KPADReset() ;
174     KPADSetPosParam ( 0,  pos_play_radius,  pos_sensitivity ) ;
175     KPADSetHoriParam( 0, hori_play_radius, hori_sensitivity ) ;
176     KPADSetDistParam( 0, dist_play_radius, dist_sensitivity ) ;
177     KPADSetAccParam ( 0,  acc_play_radius,  acc_sensitivity ) ;
178     KPADSetBtnRepeat( 0, repeat_delay_sec, repeat_pulse_sec ) ;
179 
180     //----- Cursor position initialization
181     csr_i = 0 ;  // Data index being edited
182     csr_k = 2 ;  // Digit being edited
183     csr_x = edit_data[ csr_i ].x[ csr_k ] ;
184     csr_y = edit_data[ csr_i ].y ;
185 
186     //----- Initialize the calibration message count
187     calib_disp_ct = 0 ; // Negative: display failed; 0: not displayed; positive: successful display
188 
189     dpd_mode = TRUE ;
190     aim_mode = TRUE ;
191     stick_clamp_mode = stick_clamp_mode_work = FALSE ;
192 
193     rev  = 0 ;
194     init = 0 ;
195     btn  = KPAD_BUTTON_PROC_MODE_LOOSE ;
196 }
197 
198 
199 /*******************************************************************************
200  Cursor movement
201 *******************************************************************************/
move_cursor(void)202 static void move_cursor( void )
203 {
204     EditData *ep ;
205     s32  vx,vy, wx,wy, fy ;
206     s32  i,w,k, im,wm,km ;
207 
208     /***********************************************************************
209     Cursor movement
210     ***********************************************************************/
211     //------ Temporary movement vector
212     if ( CMD_LEFT ) vx = -1 ;
213     else if ( CMD_RIGHT ) vx = 1 ;
214     else vx = 0 ;
215 
216     if ( CMD_UP ) vy = -1 ;
217     else if ( CMD_DOWN ) vy = 1 ;
218     else vy = 0 ;
219 
220     //------ Move to the nearest digit location using edit data
221     wm = 1 << 30 ;  // Maximum distance
222     i = EDIT_DATA_MAX - 1 ;
223     do {
224         ep = &edit_data[i] ;
225 
226         fy = ( wy = ep->y - csr_y ) * vy ; // Prepare to calculate dot product
227         wy *= wy ;    // Prepare to calculate distance
228         k = 0 ;
229         do {
230             //----- Dot product must be positive
231             wx = ep->x[k] - csr_x ;
232             if ( wx * vx + fy <= 0 ) continue ;
233 
234             //----- Distance must be shortest
235             w = wx * wx + wy ;
236             if ( w >= wm ) continue ;
237 
238             //----- Record candidates
239             wm = w ;
240             im = i ;
241             km = k ;
242         } while ( ++k < 3 ) ;
243     } while ( --i >= 0 ) ;
244 
245     //----- If candidates have been recorded, move cursor
246     if ( wm != 1 << 30 ) {
247         csr_i = im ;
248         csr_k = km ;
249         csr_x = edit_data[ csr_i ].x[ csr_k ] ;
250         csr_y = edit_data[ csr_i ].y ;
251     }
252 }
253 
254 
255 /*******************************************************************************
256  Increasing/decreasing numerical values
257 *******************************************************************************/
push_cursor(void)258 static void push_cursor( void )
259 {
260     EditData *ep = &edit_data[ csr_i ] ;
261 
262     //----- Was a button pressed?
263     if ( CMD_INC ) {
264         *(ep->vp) += ep->v[ csr_k ] ;
265         if ( *(ep->vp) > ep->max ) *(ep->vp) = ep->max ;
266     } else if ( CMD_DEC ) {
267         *(ep->vp) -= ep->v[ csr_k ] ;
268         if ( *(ep->vp) < ep->min ) *(ep->vp) = ep->min ;
269     } else {
270         return ; // No value change
271     }
272 
273     //----- Reset because value has changed
274     if ( csr_i >= 14 ) {
275         KPADSetBtnRepeat( 0, repeat_delay_sec, repeat_pulse_sec ) ;
276     } else if ( csr_i >=11 ) {
277         KPADSetAccParam    ( 0, acc_play_radius,  acc_sensitivity ) ;
278         KPADSetAccPlayMode ( 0, (KPADPlayMode)acc_play_mode ) ;
279     } else if ( csr_i >= 8 ) {
280         KPADSetDistParam   ( 0, dist_play_radius, dist_sensitivity ) ;
281         KPADSetDistPlayMode( 0, (KPADPlayMode)dist_play_mode ) ;
282     } else if ( csr_i >= 5 ) {
283         KPADSetHoriParam   ( 0, hori_play_radius, hori_sensitivity ) ;
284         KPADSetHoriPlayMode( 0, (KPADPlayMode)hori_play_mode ) ;
285     } else if ( csr_i >= 2 ) {
286         KPADSetPosParam    ( 0, pos_play_radius,  pos_sensitivity ) ;
287         KPADSetPosPlayMode ( 0, (KPADPlayMode)pos_play_mode ) ;
288     } else if ( csr_i == 1 ) {
289         KPADSetObjInterval( obj_interval ) ;
290         reset_request = TRUE;
291     }
292 }
293 
294 /*******************************************************************************
295  KPAD Processing Functions
296 *******************************************************************************/
work_kpad(void)297 void work_kpad( void )
298 {
299     //----- Load controller
300     if ( padsTrig[ 0 ].button & PAD_BUTTON_A ) {
301         OSReport("KPADReset() from main()\n") ;
302         KPADReset() ;
303     }
304     if ( pads[ 0 ].button & PAD_BUTTON_B ) {
305         kpad_reads = 0 ;
306     } else {
307         kpad_reads = KPADReadEx( 0, &kpads[ 0 ][ 0 ], (u32)( KPAD_BUF_SIZE * ( init + 1 ) ), &kpad_err ) ;
308         if ( kpad_reads == 0 && kpad_err == KPAD_READ_ERR_NO_DATA ) {
309             // Only the most recent data is maintained
310             kpad_reads = 1 ;
311         }
312     }
313     if ( padsTrig[ 0 ].button & PAD_BUTTON_X ) {
314         rev = ( rev ) ? 0 : 1 ;
315 
316         KPADSetReviseMode( 0, rev ) ;
317     }
318     if ( padsTrig[ 0 ].button & PAD_BUTTON_Y ) {
319         if ( kpad_err == KPAD_READ_ERR_INIT ) {
320             init = ( init ) ? 0 : 1 ;
321             if ( init ) {
322                 KPADInitEx( uniRingBufs, sizeof(uniRingBufs)/sizeof(KPADUnifiedWpadStatus) ) ;
323             } else {
324                 KPADInit() ;
325             }
326             KPADSetControlDpdCallback( 0, dpd_callback ) ;
327             KPADSetSamplingCallback( 0, sampling_callback ) ;
328         } else {
329             KPADShutdown() ;
330         }
331     }
332     if ( padsTrig[ 0 ].button & PAD_TRIGGER_Z ) {
333         btn = (u8)( ( btn == KPAD_BUTTON_PROC_MODE_LOOSE ) ? KPAD_BUTTON_PROC_MODE_TIGHT : KPAD_BUTTON_PROC_MODE_LOOSE ) ;
334 
335         KPADSetButtonProcMode( 0, btn ) ;
336     }
337 }
338 
339 /*******************************************************************************
340  CPU Processing Functions
341 *******************************************************************************/
work_sample(void)342 void work_sample( void )
343 {
344     if ( kpad_reads <= 0 ) {
345         return ;
346     }
347 
348     if ( kpads[ 0 ][ 0 ].hold == 0 && reset_request ) {
349         reset_request = FALSE ;
350         OSReport( "KPADReset() from work_sample()\n" ) ;
351         KPADReset() ;
352         return ;
353     }
354 
355     /***********************************************************************
356     Wii Remote calibration
357     ***********************************************************************/
358     if ( calib_disp_ct < 0 ) ++ calib_disp_ct ;
359     else if ( calib_disp_ct ) -- calib_disp_ct ;
360 
361     if ( CMD_CALIBRATE ) {
362         if ( KPADCalibrateDPD( 0 ) == 2 ) {
363             calib_disp_ct = 180 ; // Succeeded
364         } else {
365             calib_disp_ct = -180 ; // Failed
366         }
367     }
368 
369     /***********************************************************************
370     DPD ON/OFF
371     ***********************************************************************/
372     if ( CMD_ENABLE_DPD ) {
373         KPADEnableDPD( 0 ) ;
374     }
375     if ( CMD_DISABLE_DPD ) {
376         KPADDisableDPD( 0 ) ;
377     }
378 
379     /***********************************************************************
380     AIMMODE ON/OFF
381     ***********************************************************************/
382     if ( CMD_AIMMODE ) {
383         aim_mode = (aim_mode) ? FALSE : TRUE;
384         if( aim_mode ) {
385             KPADEnableAimingMode( 0 );
386         }
387         else {
388             KPADDisableAimingMode( 0 );
389         }
390     }
391 
392     /***********************************************************************
393     Stick Clamp Mode ON/OFF
394     ***********************************************************************/
395     if ( CMD_STICK_CLAMP_TRIG1 || CMD_STICK_CLAMP_TRIG2 ) {
396         stick_clamp_mode_work = (stick_clamp_mode_work) ? FALSE : TRUE;
397     }
398     if ( CMD_STICK_CLAMP_HOLD1 || CMD_STICK_CLAMP_HOLD2 ) {
399         stick_clamp_mode = (stick_clamp_mode_work) ? FALSE : TRUE;
400     } else {
401         stick_clamp_mode = stick_clamp_mode_work;
402     }
403     if ( stick_clamp_mode ) {
404         KPADEnableStickCrossClamp();
405     } else {
406         KPADDisableStickCrossClamp();
407     }
408 
409     /***********************************************************************
410     Value Editing
411     ***********************************************************************/
412     move_cursor() ;  // Cursor movement
413     push_cursor() ;  // Increasing/decreasing numerical values
414 }
415 
416 
417 /*******************************************************************************
418  Render pointing scale frame
419 *******************************************************************************/
draw_pointing_frame(void)420 static void draw_pointing_frame( void )
421 {
422     draw_line( -pointing_scale,-pointing_scale, pointing_scale,-pointing_scale, blue_clr, 2.5f ) ;
423     draw_line(  pointing_scale,-pointing_scale, pointing_scale, pointing_scale, blue_clr, 2.5f ) ;
424     draw_line(  pointing_scale, pointing_scale,-pointing_scale, pointing_scale, blue_clr, 2.5f ) ;
425     draw_line( -pointing_scale, pointing_scale,-pointing_scale,-pointing_scale, blue_clr, 2.5f ) ;
426 }
427 
428 
429 /*******************************************************************************
430  Render pointing coordinates
431 *******************************************************************************/
draw_position(KPADStatus * sp)432 static void draw_position( KPADStatus *sp )
433 {
434     Vec2  pos, vec ;
435     f32  scale ;
436 
437     if (sp->dpd_valid_fg <= 0) {
438         return;
439     }
440     switch (sp->data_format) {
441       case WPAD_FMT_CORE_ACC_DPD :
442       case WPAD_FMT_FREESTYLE_ACC_DPD :
443       case WPAD_FMT_CLASSIC_ACC_DPD :
444       case WPAD_FMT_GUITAR :
445       case WPAD_FMT_DRUM :
446       case WPAD_FMT_TAIKO :
447         break;
448 
449       default:
450         return;
451     }
452 
453     //------ Crosshair
454     pos.x = pointing_scale * sp->pos.x ; // Center coordinate
455     pos.y = pointing_scale * sp->pos.y ;
456 
457     scale = 72.0f ;
458     vec.x = scale * sp->horizon.x ;  // Vector pointing right
459     vec.y = scale * sp->horizon.y ;
460     draw_line( pos.x-vec.x,pos.y-vec.y, pos.x+vec.x,pos.y+vec.y, yellow_clr, 3 ) ;
461 
462     scale = 28.0f ;
463     vec.x = scale * -sp->horizon.y ; // Vector pointing down
464     vec.y = scale *  sp->horizon.x ;
465     draw_arrow( pos.x+vec.x,pos.y+vec.y, pos.x-vec.x,pos.y-vec.y, silver_clr, 3 ) ;
466 
467     //------ Center point
468     draw_point( pos.x,pos.y, black_clr, 11 ) ;
469     draw_point( pos.x,pos.y,  cyan_clr,  9 ) ;
470 }
471 
472 
473 /*******************************************************************************
474  Render Grids
475 *******************************************************************************/
draw_grid(f32 ox,f32 oy,f32 radius,GXColor clr)476 static void draw_grid( f32 ox, f32 oy, f32 radius, GXColor clr )
477 {
478     f32  r = radius * 1.4f ; // Crosshair length
479 
480     draw_arrow( ox-r,oy, ox+r,oy, clr, 3 ) ; // Horizontal line
481     draw_arrow( ox,oy+r, ox,oy-r, clr, 3 ) ; // Vertical line
482     draw_circle( ox,oy, radius, clr, 3 ) ;  // Circle
483 }
484 
485 
486 /*******************************************************************************
487  Render Acceleration
488 *******************************************************************************/
draw_acc(f32 ox,f32 oy,f32 radius,f32 ax,f32 ay,GXColor clr,BOOL dashed)489 static void draw_acc( f32 ox, f32 oy, f32 radius, f32 ax, f32 ay, GXColor clr, BOOL dashed )
490 {
491     f32  px = ax * radius + ox ;
492     f32  py = ay * radius + oy ;
493 
494     if ( dashed ) {
495         draw_dashed_arrow( ox,oy, px,py, clr, 4 ) ;
496     } else {
497         draw_arrow( ox,oy, px,py, clr, 4 ) ;
498     }
499     draw_point( px,py, white_clr, 4 ) ;
500 }
501 
502 /*******************************************************************************
503  Render analog stick
504 *******************************************************************************/
draw_stick(f32 ox,f32 oy,f32 radius,f32 sx,f32 sy,GXColor clr,BOOL dashed)505 static void draw_stick( f32 ox, f32 oy, f32 radius, f32 sx, f32 sy, GXColor clr, BOOL dashed )
506 {
507     f32 px = sx * radius + ox;
508     f32 py = sy * radius + oy;
509 
510     if ( dashed ) {
511         draw_dashed_arrow( ox,oy, px,py, clr, 4 ) ;
512     } else {
513         draw_arrow( ox,oy, px,py, clr, 4 ) ;
514     }
515     draw_point( px,py, white_clr, 4 ) ;
516 }
517 
518 /*******************************************************************************
519  Render analog trigger
520 *******************************************************************************/
draw_box(f32 ox,f32 oy,f32 width,f32 height,GXColor clr)521 static void draw_box( f32 ox, f32 oy, f32 width, f32 height, GXColor clr )
522 {
523     f32  x1,y1, x2,y2 ;
524 
525     x1 = ox ;
526     x2 = ox - width ;
527     y1 = oy ;
528     y2 = oy - height ;
529 
530     GXSetTevColor( GX_TEVREG0, clr ) ;
531 
532     GXBegin( GX_QUADS, GX_VTXFMT0, 4 ) ;
533       GXPosition2f32( x1, y1 ) ;
534       GXPosition2f32( x2, y1 ) ;
535       GXPosition2f32( x2, y2 ) ;
536       GXPosition2f32( x1, y2 ) ;
537     GXEnd() ;
538 }
539 
540 /*******************************************************************************
541  Render value adjustment cursor
542 *******************************************************************************/
draw_cursor(void)543 static void draw_cursor( void )
544 {
545     f32  x1,y1, x2,y2 ;
546 
547     x1 = calc_kfont_x1( (f32)csr_x ) ;
548     y1 = calc_kfont_y1( csr_y+O1Y ) ;
549     y2 = calc_kfont_y2( csr_y+O1Y ) - 1.0f ;
550     if ( csr_x > 12 ) {
551         x2 = calc_kfont_x2( csr_x + 4.0f ) - 1.0f ;
552     } else {
553         x2 = calc_kfont_x2( (f32)csr_x ) - 1.0f ;
554     }
555     draw_line( x1,y1, x2,y1, white_clr, 2 ) ;
556     draw_line( x2,y1, x2,y2, white_clr, 2 ) ;
557     draw_line( x2,y2, x1,y2, white_clr, 2 ) ;
558     draw_line( x1,y2, x1,y1, white_clr, 2 ) ;
559 }
560 
561 
562 /*******************************************************************************
563  Render DPD Sensor Frame
564 *******************************************************************************/
draw_dpd_frame(void)565 static void draw_dpd_frame( void )
566 {
567     f32  rx,ry, x1,y1, x2,y2 ;
568 
569     rx = dpd_disp_scale * 0.5f ;
570     ry = rx * (f32)WPAD_DPD_IMG_RESO_WY / (f32)WPAD_DPD_IMG_RESO_WX ;
571     x1 = dpd_disp_ox - rx ;
572     y1 = dpd_disp_oy - ry ;
573     x2 = dpd_disp_ox + rx ;
574     y2 = dpd_disp_oy + ry ;
575 
576     GXSetTevColor( GX_TEVREG0, smoke_clr ) ;
577 
578     GXBegin( GX_QUADS, GX_VTXFMT0, 4 ) ;
579       GXPosition2f32( x1, y1 ) ;
580       GXPosition2f32( x2, y1 ) ;
581       GXPosition2f32( x2, y2 ) ;
582       GXPosition2f32( x1, y2 ) ;
583     GXEnd() ;
584 }
585 
586 
587 /*******************************************************************************
588  Render DPD objects
589 *******************************************************************************/
draw_object(void)590 static void draw_object( void )
591 {
592     DPDObject              *op, *op1 ;
593     f32                     px,py, scale, ofx,ofy ;
594     s32                     n;
595     KPADUnifiedWpadStatus  *up;
596 
597     // Note: The return value of KPADRead() (the number of samples) is not the same as the number of valid samples inside unified_status[].
598     //
599     //
600     // Also, the KPADGetUnifiedWpadStatus function gets the most recent data at the time it is run.
601     // Accordingly, buffer content is not the same as data retrieved inside the KPADRead function.
602     //
603     //
604     // To get exactly the same data as that obtained within KPADRead(), successively call KPADRead(), then KPADGetUnifiedWpadStatus() with interrupts disabled.
605     // However, doing this makes the period during which interrupts are disabled become longer.
606     //
607 
608     // This sample program uses 'kpad_reads' for the number of samples and renders simplified DPD objects without rigorously synchronizing data.
609     //
610     n = kpad_reads ;   // Current sampling count
611     if (n <= 0) {
612         return;
613     }
614 
615     KPADGetUnifiedWpadStatus( 0, unified_status, (u32)n );
616 
617     //----- Calculate display position
618     scale = dpd_disp_scale / (f32)WPAD_DPD_IMG_RESO_WX ;
619     ofx = dpd_disp_scale * -0.5f ;
620     ofy = ofx * (f32)WPAD_DPD_IMG_RESO_WY / (f32)WPAD_DPD_IMG_RESO_WX ;
621     ofx += dpd_disp_ox ;
622     ofy += dpd_disp_oy ;
623 
624     //----- Display all values sampled at 200 Hz
625         // Render starting from older items
626 
627     while ( --n >= 0 ) {
628         up = &unified_status[n];
629         if (up->u.core.err == WPAD_ERR_NONE) {
630             switch (up->fmt) {
631               case WPAD_FMT_CORE_ACC :
632               case WPAD_FMT_CORE_ACC_DPD :
633               case WPAD_FMT_FREESTYLE_ACC :
634               case WPAD_FMT_FREESTYLE_ACC_DPD :
635               case WPAD_FMT_CLASSIC_ACC :
636               case WPAD_FMT_CLASSIC_ACC_DPD :
637               case WPAD_FMT_GUITAR :
638               case WPAD_FMT_DRUM :
639               case WPAD_FMT_TAIKO :
640                 op1 = up->u.core.obj ;
641                 break;
642 
643               default:
644                 op1 = NULL;
645                 break;
646             }
647             if (op1) {
648                 op = op1 + (WPAD_DPD_MAX_OBJECTS - 1);
649                 do {
650                     if ( op->size == 0 ) continue ;
651 
652                     //----- Change to screen coordinates
653                     px = (f32)op->x * scale + ofx ;
654                     py = (f32)op->y * scale + ofy ;
655 
656                     //----- Render objects
657                     draw_point( px,py, white_clr, 5 ) ;
658                     draw_circle( px,py, 5, black_clr, 2 ) ;
659                     draw_circle( px,py, 4, smoke_clr, 2 ) ;
660                     draw_circle( px,py, 3,  gray_clr, 2 ) ;
661                 } while ( --op >= op1 ) ;
662             }
663         }
664     }
665 }
666 
667 /*******************************************************************************
668  Render the sampling rate
669 *******************************************************************************/
draw_sampling_rate(void)670 static void draw_sampling_rate( void )
671 {
672     static OSTime time ;
673     static u32 countDisp ;
674     BOOL enabled ;
675     OSTime t ;
676 
677     t = OSGetTime() ;
678     if ( OSTicksToSeconds((OSTime)(t - time)) > 0 ) {
679         time = t ;
680         enabled = OSDisableInterrupts() ;
681         countDisp = MySamplingCount ;
682         MySamplingCount = 0 ;
683         (void)OSRestoreInterrupts( enabled ) ;
684     }
685 
686     draw_kfont_letter( 0,17+O6Y, gray_clr, "SMP.RATE" ) ;
687     (void)draw_kfont_s32( 14,17+O6Y, white_clr, (s32)countDisp ) ;
688 }
689 
690 /*******************************************************************************
691  Render remaining battery life
692 *******************************************************************************/
draw_battery_level(void)693 static void draw_battery_level( void )
694 {
695     static OSTime time ;
696     static u8 level ;
697     OSTime t ;
698     int i ;
699     f32 x ;
700     f32 y ;
701 
702     t = OSGetTime() ;
703     if ( OSTicksToSeconds((OSTime)(t - time)) > 0 ) {
704         time = t ;
705         WPADGetInfoAsync( 0, &wpad_info, NULL ) ;
706     }
707 
708     draw_kfont_letter( 20.0f,17+O6Y, gray_clr, "BAT" ) ;
709 
710     x = 40.0f ;
711     y = 96.0f ;
712     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
713     for ( i = 0 ; i < 4 ; i++ ) {
714         if ( i < wpad_info.battery ) {
715             draw_box( x + i * 20.0f, y, 15.0f, 15.0f, cyan_clr ) ;
716         } else {
717             draw_box( x + i * 20.0f, y, 15.0f, 15.0f, gray_clr ) ;
718         }
719     }
720 }
721 
722 /*******************************************************************************
723  Render callback
724 *******************************************************************************/
draw_callback_status(void)725 static void draw_callback_status( void )
726 {
727     u32 i ;
728     MyCallbackStatus buf[ MY_START_COUNTS_MAX ] ;
729     BOOL enabled ;
730     char str[ 32 ] ;
731     s32  latestIdx ;
732 
733     enabled = OSDisableInterrupts() ;
734     for ( i = 0; i < MY_START_COUNTS_MAX; i++ ) {
735         if ( MyCallbackStatusBuf[ 0 ][ i ].count ) {
736             MyCallbackStatusBuf[ 0 ][ i ].count-- ;
737         }
738         buf[ i ] = MyCallbackStatusBuf[ 0 ][ i ] ;
739     }
740     latestIdx = MyCallbackLatestIdx[ 0 ] ;
741     (void)OSRestoreInterrupts( enabled ) ;
742 
743     for ( i = 0; i < MY_START_COUNTS_MAX; i++ ) {
744         if ( (s32)i == latestIdx ||
745             buf[ i ].count ) {
746             GXColor clr ;
747 
748             if ( buf[ i ].reason == 0 ) {
749                 clr = gray_clr ;
750             } else {
751                 clr = white_clr ;
752             }
753             sprintf(str, "%s %d", MyCbName[ 0 ], buf[ i ].reason ) ;
754             draw_kfont_letter( 0.0f, buf[ i ].count * 0.05f + 0.5f, clr, str );
755         }
756     }
757 }
758 
759 
760 /*******************************************************************************
761  Rendering Functions
762 *******************************************************************************/
draw_sample(void)763 void draw_sample( void )
764 {
765     s32     cx,cy ;
766     f32     x1,x2, y, r ;
767     u32     hold, trig, release ;
768     u32     flag ;
769     GXColor clr ;
770 
771     /***********************************************************************
772         Pointing Scale Frame
773     ***********************************************************************/
774     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
775     draw_pointing_frame() ;
776 
777     /***********************************************************************
778         Adjustments
779     ***********************************************************************/
780     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 15.6f, 20.8f ) ;
781     cx = 0 ;
782     cy = 3 ;
783     draw_kfont_letter( (f32)cx,cy+O1Y, gray_clr, "POINTING") ;
784     (void)draw_kfont_s32( (f32)(cx+12),cy+O1Y, blue_clr, (s32)pointing_scale ) ;
785     cy += 2 ;
786     draw_kfont_letter( (f32)cx,cy+O1Y, gray_clr, "INTERVAL") ;
787     (void)draw_kfont_f32( (f32)(cx+9),cy+O1Y, peagreen_clr, obj_interval, 2 ) ;
788     cy += 2 ;
789     draw_kfont_letter( (f32)cx,cy+O1Y, gray_clr, "    PLAY SENS MODE") ;
790     ++ cy ;
791     draw_kfont_letter( (f32)cx,cy+O1Y, gray_clr, "POS" ) ;
792     (void)draw_kfont_f32   ( (f32)(cx+ 4),cy+O1Y,   cyan_clr,  pos_play_radius, 2 ) ;
793     (void)draw_kfont_f32   ( (f32)(cx+ 9),cy+O1Y,   cyan_clr,  pos_sensitivity, 2 ) ;
794     (void)draw_kfont_letter( (f32)(cx+14),cy+O1Y,   cyan_clr, (pos_play_mode) ? "TIGHT" : "LOOSE" ) ;
795     ++ cy ;
796     draw_kfont_letter( (f32)cx,cy+O1Y, gray_clr, "HOR" ) ;
797     (void)draw_kfont_f32   ( (f32)(cx+ 4),cy+O1Y, yellow_clr, hori_play_radius, 2 ) ;
798     (void)draw_kfont_f32   ( (f32)(cx+ 9),cy+O1Y, yellow_clr, hori_sensitivity, 2 ) ;
799     (void)draw_kfont_letter( (f32)(cx+14),cy+O1Y, yellow_clr,(hori_play_mode) ? "TIGHT" : "LOOSE" ) ;
800     ++ cy ;
801     draw_kfont_letter( (f32)cx,cy+O1Y, gray_clr, "DIS" ) ;
802     (void)draw_kfont_f32   ( (f32)(cx+ 4),cy+O1Y,  green_clr, dist_play_radius, 2 ) ;
803     (void)draw_kfont_f32   ( (f32)(cx+ 9),cy+O1Y,  green_clr, dist_sensitivity, 2 ) ;
804     (void)draw_kfont_letter( (f32)(cx+14),cy+O1Y,  green_clr,(dist_play_mode) ? "TIGHT" : "LOOSE" ) ;
805     ++ cy ;
806     draw_kfont_letter( (f32)cx,cy+O1Y, gray_clr, "ACC" ) ;
807     (void)draw_kfont_f32   ( (f32)(cx+ 4),cy+O1Y,    red_clr,  acc_play_radius, 2 ) ;
808     (void)draw_kfont_f32   ( (f32)(cx+ 9),cy+O1Y,    red_clr,  acc_sensitivity, 2 ) ;
809     (void)draw_kfont_letter( (f32)(cx+14),cy+O1Y,    red_clr, (acc_play_mode) ? "TIGHT" : "LOOSE" ) ;
810     cy += 2 ;
811     draw_kfont_letter( (f32)cx,cy+O1Y, gray_clr, "    DLAY PULS") ;
812     ++ cy ;
813     draw_kfont_letter( (f32)cx,cy+O1Y, gray_clr, "RPT") ;
814     (void)draw_kfont_f32( (f32)(cx+4),cy+O1Y, orange_clr, repeat_delay_sec, 2 ) ;
815     (void)draw_kfont_f32( (f32)(cx+9),cy+O1Y, orange_clr, repeat_pulse_sec, 2 ) ;
816 
817     //----- Various data titles
818     draw_kfont_letter( 28.0f, 3.0f+O6Y, gray_clr, "ACC"  ) ;  // Acceleration Information
819     draw_kfont_letter( 15.2f,12.5f+O6Y, gray_clr, "VALID") ;  // DPD enable flag
820     draw_kfont_letter( 23.0f,12.5f+O6Y, gray_clr, "DIST" ) ;  // Distance information
821     draw_kfont_letter( 33.8f,10.1f+O6Y, gray_clr, "OBJ"  ) ;  // Object
822 
823     /***********************************************************************
824         Value Adjustment Cursor
825     ***********************************************************************/
826     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
827     draw_cursor() ;
828 
829     /***********************************************************************
830         DPD Enable Flag and Distance Information
831     ***********************************************************************/
832     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 28.5f, 38.0f ) ;
833     (void)draw_kfont_s32(  9.0f,7.5f+O2Y, violet_clr, kpads[ 0 ][ 0 ].dpd_valid_fg ) ;
834     (void)draw_kfont_f32( 11.5f,7.5f+O2Y,  green_clr, kpads[ 0 ][ 0 ].dist, 2 ) ;
835 
836     /***********************************************************************
837         Battery Level
838     ***********************************************************************/
839     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 14.0f, 18.8f ) ;
840     draw_battery_level() ;
841 
842     /***********************************************************************
843         Sampling Rate
844     ***********************************************************************/
845     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 14.0f, 18.8f ) ;
846     draw_sampling_rate() ;
847 
848     /***********************************************************************
849         Button Bitflags
850     ***********************************************************************/
851     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 14.0f, 18.8f ) ;
852     cx =  0 ;
853     cy =  18 ;
854 
855     hold    = kpads[ 0 ][ 0 ].hold;
856     trig    = kpads[ 0 ][ 0 ].trig;
857     release = kpads[ 0 ][ 0 ].release;
858 
859     draw_kfont_letter( (f32)cx,cy+O6Y, gray_clr, "HLD") ;
860     if (kpad_reads > 0) {
861         draw_kfont_bit( (f32)(cx+39),cy+O6Y, orange_clr, hold   , 32 ) ;
862     }
863     ++ cy ;
864     draw_kfont_letter( (f32)cx,cy+O6Y, gray_clr, "TRG") ;
865     if (kpad_reads > 0) {
866         draw_kfont_bit( (f32)(cx+39),cy+O6Y, orange_clr, trig   , 32 ) ;
867     }
868     ++ cy ;
869     draw_kfont_letter( (f32)cx,cy+O6Y, gray_clr, "REL") ;
870     if (kpad_reads > 0) {
871         draw_kfont_bit( (f32)(cx+39),cy+O6Y, orange_clr, release, 32 ) ;
872     }
873 
874     if (kpad_reads > 0) {
875         if ( kpads[ 0 ][ 0 ].wpad_err == WPAD_ERR_NONE &&
876              ( kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_CLASSIC ||
877                kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_GUITAR ||
878                kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_DRUM ||
879                kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_TAIKO ||
880                kpads[ 0 ][ 0 ].dev_type == WPAD_DEV_TRAIN ) ) {
881 
882             hold    = kpads[ 0 ][ 0 ].ex_status.cl.hold ;
883             trig    = kpads[ 0 ][ 0 ].ex_status.cl.trig ;
884             release = kpads[ 0 ][ 0 ].ex_status.cl.release ;
885 
886             switch( kpads[ 0 ][ 0 ].dev_type ) {
887               case WPAD_DEV_CLASSIC :       clr = peagreen_clr ;  break ;
888               case WPAD_DEV_GUITAR :        clr =     cyan_clr ;  break ;
889               case WPAD_DEV_DRUM :          clr =    green_clr ;  break ;
890               case WPAD_DEV_TRAIN :         clr =   yellow_clr ;  break ;
891               case WPAD_DEV_TAIKO :         clr =   violet_clr ;  break ;
892             }
893 
894             ++ cy ;
895             draw_kfont_letter( (f32)cx,cy+O6Y, gray_clr, "HLD") ;
896             draw_kfont_bit( (f32)(cx+39),cy+O6Y, clr, hold   , 32 ) ;
897             ++ cy ;
898             draw_kfont_letter( (f32)cx,cy+O6Y, gray_clr, "TRG") ;
899             draw_kfont_bit( (f32)(cx+39),cy+O6Y, clr, trig   , 32 ) ;
900             ++ cy ;
901             draw_kfont_letter( (f32)cx,cy+O6Y, gray_clr, "REL") ;
902             draw_kfont_bit( (f32)(cx+39),cy+O6Y, clr, release, 32 ) ;
903         }
904     } else {
905         switch ( kpad_err ) {
906           case KPAD_READ_ERR_INIT :
907           case KPAD_READ_ERR_SETUP :
908             cy -= 2 ;
909             draw_kfont_letter( (f32)(cx+8),cy+O6Y, white_clr, "WPAD OR KPAD IS NOT INITIALIZED.") ;
910             cy += 2 ;
911             // break through
912           case KPAD_READ_ERR_NO_CONTROLLER :
913             cy -= 1 ;
914             draw_kfont_letter( (f32)(cx+8),cy+O6Y, white_clr, "  OTHER TESTS BY GC CONT. 1P") ;
915             ++ cy ;
916             draw_kfont_letter( (f32)(cx+8),cy+O6Y, white_clr, "   A BUTTON - KPADRESET") ;
917             ++ cy ;
918             draw_kfont_letter( (f32)(cx+8),cy+O6Y, white_clr, "   B BUTTON - SKIP KPADREAD") ;
919             ++ cy ;
920             draw_kfont_letter( (f32)(cx+8),cy+O6Y, white_clr, "   X BUTTON - CHANGE REVISE MODE") ;
921             ++ cy ;
922             draw_kfont_letter( (f32)(cx+8),cy+O6Y, white_clr, "   Y BUTTON - KPADINIT/KPADSHUTDOWN") ;
923             ++ cy ;
924             draw_kfont_letter( (f32)(cx+8),cy+O6Y, white_clr, "   Z BUTTON - CHANGE BUTTON PROC MODE") ;
925             break ;
926         }
927     }
928 
929     /***********************************************************************
930         Acceleration Information
931     ***********************************************************************/
932     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 15.0f, 20.0f ) ;
933     draw_kfont_letter( 25.0f,2.5f+O3Y, smoke_clr, "Y            Y") ;
934     draw_kfont_letter( 29.0f,6.5f+O3Y, smoke_clr, "X            Z") ;
935 
936     x1 =   35.0f ;      // X-coordinate of left grid
937     x2 =  210.0f ;      // X-coordinate of right grid
938     y  = -100.0f+O4Y ;  // Common y-coordinate
939     r  =   60.0f ;      // Common radius
940 
941     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
942     draw_grid( x1, y, r, smoke_clr ) ;
943     draw_grid( x2, y, r, smoke_clr ) ;
944 
945     cx = kpad_reads ;
946     while ( --cx >= 0 ) {
947         if ( kpads[ 0 ][ cx ].wpad_err == WPAD_ERR_NONE ) {
948             switch ( kpads[ 0 ][ cx ].data_format ) {
949               case WPAD_FMT_CORE_ACC :
950               case WPAD_FMT_CORE_ACC_DPD :
951               case WPAD_FMT_CLASSIC_ACC :
952               case WPAD_FMT_CLASSIC_ACC_DPD :
953               case WPAD_FMT_GUITAR :
954               case WPAD_FMT_DRUM :
955               case WPAD_FMT_TAIKO :
956                 flag = 0x01 ;
957                 break ;
958 
959               case WPAD_FMT_FREESTYLE_ACC :
960               case WPAD_FMT_FREESTYLE_ACC_DPD :
961                 flag = 0x03 ;
962                 break ;
963 
964               default :
965                 flag = 0x00 ;
966                 break ;
967             }
968 
969             if ( flag & 0x01 ) {
970                 draw_acc( x1, y, r, kpads[ 0 ][ cx ].acc.x, -kpads[ 0 ][ cx ].acc.y, red_clr, FALSE ) ;
971                 draw_acc( x2, y, r, kpads[ 0 ][ cx ].acc.z, -kpads[ 0 ][ cx ].acc.y, red_clr, FALSE ) ;
972             }
973             if ( flag & 0x02 ) {
974                 draw_acc( x1, y, r, kpads[ 0 ][ cx ].ex_status.fs.acc.x, -kpads[ 0 ][ cx ].ex_status.fs.acc.y, orange_clr, FALSE ) ;
975                 draw_acc( x2, y, r, kpads[ 0 ][ cx ].ex_status.fs.acc.z, -kpads[ 0 ][ cx ].ex_status.fs.acc.y, orange_clr, FALSE ) ;
976             }
977         }
978     }
979 
980     /***********************************************************************
981         Control Stick Information
982     ***********************************************************************/
983     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
984     cx = kpad_reads ;
985     while ( --cx >= 0 ) {
986         if ( kpads[ 0 ][ cx ].wpad_err == WPAD_ERR_NONE ) {
987             if( kpads[ 0 ][ cx ].dev_type == WPAD_DEV_FREESTYLE ) {
988                 draw_stick( x1, y, r, kpads[ 0 ][ cx ].ex_status.fs.stick.x, -kpads[ 0 ][ cx ].ex_status.fs.stick.y, orange_clr, TRUE ) ;
989             } else if ( kpads[ 0 ][ cx ].dev_type == WPAD_DEV_CLASSIC ||
990                         kpads[ 0 ][ cx ].dev_type == WPAD_DEV_GUITAR ||
991                         kpads[ 0 ][ cx ].dev_type == WPAD_DEV_DRUM ||
992                         kpads[ 0 ][ cx ].dev_type == WPAD_DEV_TAIKO ||
993                         kpads[ 0 ][ cx ].dev_type == WPAD_DEV_TRAIN ) {
994 
995                 switch ( kpads[ 0 ][ cx ].dev_type ) {
996                   case WPAD_DEV_CLASSIC :      clr =  peagreen_clr ;  break ;
997                   case WPAD_DEV_GUITAR :       clr =      cyan_clr ;  break ;
998                   case WPAD_DEV_DRUM :         clr =     green_clr ;  break ;
999                   case WPAD_DEV_TRAIN :        clr =    yellow_clr ;  break ;
1000                   case WPAD_DEV_TAIKO :        clr =    violet_clr ;  break ;
1001                 }
1002                 draw_stick( x1, y, r, kpads[ 0 ][ cx ].ex_status.cl.lstick.x, -kpads[ 0 ][ cx ].ex_status.cl.lstick.y, clr, FALSE ) ;
1003                 draw_stick( x2, y, r, kpads[ 0 ][ cx ].ex_status.cl.rstick.x, -kpads[ 0 ][ cx ].ex_status.cl.rstick.y, clr, FALSE ) ;
1004             }
1005         }
1006     }
1007 
1008     /***********************************************************************
1009         Trigger Information
1010     ***********************************************************************/
1011 
1012     x1 = 245.0f ;
1013     x2 = 275.0f ;
1014     y  = 215.0f ;
1015 
1016 
1017     cx = kpad_reads ;
1018     while ( --cx >= 0 ) {
1019         if ( kpads[ 0 ][ cx ].dev_type == WPAD_DEV_CLASSIC ||
1020              kpads[ 0 ][ cx ].dev_type == WPAD_DEV_GUITAR ||
1021              kpads[ 0 ][ cx ].dev_type == WPAD_DEV_DRUM ||
1022              kpads[ 0 ][ cx ].dev_type == WPAD_DEV_TAIKO ||
1023              kpads[ 0 ][ cx ].dev_type == WPAD_DEV_TRAIN ) {
1024 
1025             init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 15.6f, 20.8f ) ;
1026             draw_kfont_letter( 36.2f,17.8f+O6Y, gray_clr, "TRIG"  ) ; // Trigger
1027 
1028             init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
1029             draw_box( x1, y, 20.0f, 55.0f, smoke_clr ) ;
1030             draw_box( x2, y, 20.0f, 55.0f, smoke_clr ) ;
1031 
1032             if ( kpads[ 0 ][ cx ].wpad_err == WPAD_ERR_NONE ) {
1033                 switch ( kpads[ 0 ][ cx ].dev_type ) {
1034                   case WPAD_DEV_CLASSIC :      clr =  peagreen_clr ;  break ;
1035                   case WPAD_DEV_GUITAR :       clr =      cyan_clr ;  break ;
1036                   case WPAD_DEV_DRUM :         clr =     green_clr ;  break ;
1037                   case WPAD_DEV_TRAIN :        clr =    yellow_clr ;  break ;
1038                   case WPAD_DEV_TAIKO :        clr =    violet_clr ;  break ;
1039                 }
1040 
1041                 draw_box( x1, y, 20.0f, 55.0f * kpads[ 0 ][ cx ].ex_status.cl.ltrigger, clr ) ;
1042                 draw_box( x2, y, 20.0f, 55.0f * kpads[ 0 ][ cx ].ex_status.cl.rtrigger, clr ) ;
1043             }
1044 
1045         }
1046     }
1047 
1048     /***********************************************************************
1049         DPD Object Display
1050     ***********************************************************************/
1051     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
1052     draw_dpd_frame() ;
1053     draw_object() ;
1054 
1055     /***********************************************************************
1056         Pointing Cursor
1057     ***********************************************************************/
1058     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
1059     cx = kpad_reads ;
1060     while ( --cx >= 0 ) {
1061         draw_position( &kpads[ 0 ][ cx ] ) ;
1062     }
1063 
1064     /***********************************************************************
1065         Calibration Messages
1066     ***********************************************************************/
1067     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 60.0f, 80.0f ) ;
1068     if ( calib_disp_ct < 0 ) {
1069         draw_kfont_letter( 0.5f,1.4f, magenta_clr, "  ERROR  ") ; // Fail message
1070     } else if ( calib_disp_ct ) {
1071         draw_kfont_letter( 0.5f,1.4f, magenta_clr, "CALIBRATE") ; // Success message
1072     }
1073 
1074     /***********************************************************************
1075         KPAD Callback
1076     ***********************************************************************/
1077     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 15.0f, 20.0f ) ;
1078     draw_callback_status() ;
1079 
1080     /***********************************************************************
1081         Display for Clamp Processing and Sensor Bar Position Correction
1082     ***********************************************************************/
1083     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 15.0f, 20.0f ) ;
1084     draw_kfont_letter( 20.0f,0.5f, white_clr, aim_mode ? "AIM ON" : "AIM OFF");
1085     draw_kfont_letter( 30.0f,0.5f, white_clr, stick_clamp_mode ? "CROSS CLAMP" : "CIRCLE CLAMP");
1086 }
1087 
1088