1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - demos - VIB - pulse_vib
3   File:     data.c
4 
5   Copyright 2008 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   $Date:: $
14   $Rev: $
15   $Author: $
16  *---------------------------------------------------------------------------*/
17 #include <nitro.h>
18 #include "char_data.h"
19 
20 /*-----------------------------------------------------------------------*
21                     Type, Constant
22  *-----------------------------------------------------------------------*/
23 
24 // #define USE_BACKUP
25 
26 // Number of pulse state save slot
27 #define SAVE_SLOT_NUM   8
28 
29 // Current scene
30 typedef enum
31 {
32     MM_SET_STATE,
33     MM_SAVE
34 }
35 MenuMode;
36 
37 typedef struct
38 {
39     VIBPulseState pulse_state[SAVE_SLOT_NUM];
40     u32     check_sum;
41 }
42 PulseStateBackup;
43 
44 #define KEY_NUM             14
45 #define KEYREPEAT_FIRST     25         // Key repeat default interval
46 #define KEYREPEAT_INTERVAL  5          // Key repeat interval
47 
48 /*-----------------------------------------------------------------------*
49                     Function prototypes
50  *-----------------------------------------------------------------------*/
51 
52 //--- Auto Function Prototype --- Don't comment here
53 void    NitroMain();
54 void    read_key_data(void);
55 static void go_sleep_if_cover_fold(void);
56 static void VBlankIntr(void);
57 static void set_pulse_state(void);
58 static void save_and_load_pulse_state(void);
59 static void write_pulse_state(VIBPulseState * state);
60 static u32 *get_state_value_from_line(VIBPulseState * state, s32 line);
61 static void write_save_words(void);
62 static void print_message(char *str);
63 static void print_usage(MenuMode mode);
64 static void set_first_state(void);
65 static void read_tp(void);
66 static void cartridge_pullout_callback(void);
67 static u32 calc_sum(void *addr, u32 size);
68 static BOOL start_pulse_vib(VIBPulseState * state);
69 static void stop_pulse_vib(void);
70 //--- End of Auto Function Prototype
71 
72 /*-----------------------------------------------------------------------*
73                     Variables
74  *-----------------------------------------------------------------------*/
75 
76 // Key information
77 static u16 Trg;
78 static u16 Cont;
79 static u16 Rpt;
80 
81 // Touch Panel information
82 static TPData tp_last;
83 static TPData tp_pre;
84 static TPData tp_trg;
85 static TPData tp_uptrg;
86 
87 // Pulse vibration save slot
88 static VIBPulseState save_slot[SAVE_SLOT_NUM];
89 
90 static s32 line;                       // Line number in menu
91 static MenuMode menu_mode;             // Current scene
92 static VIBPulseState pulse_state;      // Current pulse state
93 static s32 cartridge_pullout_flag;     // If TRUE, Game Pak is pulled out
94 
95 static u16 backup_lockid;
96 static BOOL backup_is_enable;
97 
98 /*-----------------------------------------------------------------------*
99                     Global Function Definitions
100  *-----------------------------------------------------------------------*/
101 
NitroMain()102 void NitroMain()
103 {
104     OS_Init();
105     GX_Init();
106 
107     GX_SetPower(GX_POWER_ALL);
108 
109     //---- Set V-Blank interrupt
110     (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
111     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
112     (void)OS_EnableIrq();
113 
114     //---- Clear VRAM
115     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
116     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
117     (void)GX_DisableBankForLCDC();
118 
119     //---- Clear OAM and palette
120     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
121     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
122 
123     // Initialize debug print
124     dp_init();
125 
126     //---- V-Blank interrupt on
127     (void)GX_VBlankIntr(TRUE);
128 
129     read_key_data();
130 
131     {                                  // Initialize Touch Panel
132         TPCalibrateParam calibrate;
133 
134         TP_Init();
135         (void)TP_GetUserInfo(&calibrate);
136         TP_SetCalibrateParam(&calibrate);
137     }
138 
139     dp_write("NRC PULSE TEST  " __DATE__, LCD_TOP, 1, 1);
140     print_usage(MM_SET_STATE);
141 
142     backup_lockid = (u16)OS_GetLockID();
143     backup_is_enable = FALSE;
144 #ifdef USE_BACKUP
145     CARD_LockBackup(backup_lockid);
146     (void)CARD_IdentifyBackup(CARD_BACKUP_TYPE_EEPROM_4KBITS);
147     CARD_UnlockBackup(backup_lockid);
148 #endif
149 
150     // Initialize pulse vib
151     cartridge_pullout_flag = FALSE;
152 
153 
154     if (!VIB_Init())
155     {
156         dp_set_pltt(1);
157         dp_write("NRC NOT INSERTED", LCD_TOP, 1, 20);
158         dp_set_pltt(0);
159     }
160     VIB_SetCartridgePulloutCallback(cartridge_pullout_callback);
161 
162     // Initialize variables
163     set_first_state();
164 
165     //---- Begin display
166     OS_WaitVBlankIntr();
167     GX_DispOn();
168     GXS_DispOn();
169 
170     while (1)
171     {
172         //---- Wait for V-Blank interrupt
173         OS_WaitVBlankIntr();
174 
175         // Main process
176         dp_clear_scr(LCD_BOTTOM);
177 
178         //---- Display message if Game Pak pullout
179         if (cartridge_pullout_flag)
180         {
181             dp_set_pltt(1);
182             dp_write("NRC PULLOUT!!", LCD_TOP, 1, 20);
183             dp_set_pltt(0);
184         }
185 
186         //---- Read pad data
187         read_key_data();
188 
189         //---- Read Touch Panel data
190         read_tp();
191 
192         {                              // Display count up
193             static u8 count;
194             dp_write_byte(count++, LCD_TOP, 29, 1);
195         }
196 
197         //---- Close cover to sleep
198         go_sleep_if_cover_fold();
199 
200         switch (menu_mode)
201         {
202         case MM_SET_STATE:
203             set_pulse_state();
204             break;
205         case MM_SAVE:
206             save_and_load_pulse_state();
207             break;
208         }
209     }
210 }
211 
212 /*-----------------------------------------------------------------------*
213                     Local Function Definition
214  *-----------------------------------------------------------------------*/
215 
go_sleep_if_cover_fold(void)216 static void go_sleep_if_cover_fold(void)
217 {
218 
219     // If wake up at Game Pak pullout, sleep again
220     while (PAD_DetectFold())
221     {
222         stop_pulse_vib();
223         PM_GoSleepMode(PM_TRIGGER_COVER_OPEN | PM_TRIGGER_CARTRIDGE, 0, 0);
224     }
225 }
226 
VBlankIntr(void)227 static void VBlankIntr(void)
228 {
229     dp_flush();                        // Flush debug print
230 
231     //---- Check V-Blank interrupt flag
232     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
233 }
234 
235 // Process of state change scene
set_pulse_state(void)236 static void set_pulse_state(void)
237 {
238 
239     if (Trg & PAD_KEY_UP)
240     {                                  // Select parameter
241         if (line == 0)
242         {
243             line = (s32)(pulse_state.pulse_num * 2 - 1);
244         }
245         else
246         {
247             line--;
248         }
249     }
250     else if (Trg & PAD_KEY_DOWN)
251     {                                  // Select parameter
252         if (line == pulse_state.pulse_num * 2 - 1)
253         {
254             line = 0;
255         }
256         else
257         {
258             line++;
259         }
260     }
261     else if ((Cont & PAD_KEY_LEFT) && (Cont & PAD_BUTTON_R))
262     {                                  // Increase value very fast
263         u32    *num = get_state_value_from_line(&pulse_state, line);
264 
265         if (*num > 101)
266         {
267             *num -= 100;
268         }
269         else
270         {
271             *num = 1;
272         }
273     }
274     else if ((Cont & PAD_KEY_RIGHT) && (Cont & PAD_BUTTON_R))
275     {                                  // Decrease value very fast
276         u32    *num = get_state_value_from_line(&pulse_state, line);
277 
278         if (*num < 99899)
279         {
280             *num += 100;
281         }
282         else
283         {
284             *num = 99999;
285         }
286     }
287     else if ((Cont & PAD_KEY_LEFT) && (Cont & PAD_BUTTON_X))
288     {                                  // Increase value fast
289         u32    *num = get_state_value_from_line(&pulse_state, line);
290 
291         if (*num > 11)
292         {
293             *num -= 10;
294         }
295         else
296         {
297             *num = 1;
298         }
299     }
300     else if ((Cont & PAD_KEY_RIGHT) && (Cont & PAD_BUTTON_X))
301     {                                  // Decrease value fast
302         u32    *num = get_state_value_from_line(&pulse_state, line);
303 
304         if (*num < 99989)
305         {
306             *num += 10;
307         }
308         else
309         {
310             *num = 99999;
311         }
312     }
313     else if ((Trg & PAD_KEY_LEFT) || (Rpt & PAD_KEY_LEFT))
314     {                                  // Increase value
315         u32    *num = get_state_value_from_line(&pulse_state, line);
316 
317         if (*num != 1)
318         {
319             (*num)--;
320         }
321     }
322     else if ((Trg & PAD_KEY_RIGHT) || (Rpt & PAD_KEY_RIGHT))
323     {                                  // Decrease value
324         u32    *num = get_state_value_from_line(&pulse_state, line);
325 
326         if (*num != 99999)
327         {
328             (*num)++;
329         }
330     }
331     else if (Trg & PAD_BUTTON_Y)
332     {                                  // Change pulse num
333         u32     old_pulse_num = pulse_state.pulse_num;
334 
335         if (pulse_state.pulse_num == VIB_PULSE_NUM_MAX)
336         {
337             pulse_state.pulse_num = 1;
338         }
339         else
340         {
341             pulse_state.pulse_num++;
342         }
343         if (line == old_pulse_num * 2 - 1)
344         {
345             line = (s32)(pulse_state.pulse_num * 2 - 1);
346         }
347         else if (line >= pulse_state.pulse_num * 2 - 1)
348         {
349             line = 0;
350         }
351     }
352 
353     if (line == pulse_state.pulse_num * 2 - 1)
354     {                                  // Display cursor
355         dp_write("@", LCD_BOTTOM, 2, 13);
356     }
357     else
358     {
359         dp_write("@", LCD_BOTTOM, 2, line + 1);
360     }
361 
362     write_pulse_state(&pulse_state);   // Display current pulse state
363 
364     if ((Trg & PAD_BUTTON_A) || (tp_trg.touch && tp_trg.x > 128))
365     {                                  // Start pulse vibration
366         print_message("START PULSE VIB");
367         (void)start_pulse_vib(&pulse_state);
368     }
369     else if (tp_trg.touch && tp_trg.x <= 128)
370     {                                  // Start one-time pulse vibration
371         VIBPulseState state_temp = pulse_state;
372         print_message("START ONE TIME PULSE VIB");
373         state_temp.repeat_num = 1;
374         (void)start_pulse_vib(&state_temp);
375     }
376     else if (Trg & PAD_BUTTON_B || tp_uptrg.touch)
377     {                                  // Stop pulse vibration
378         print_message("STOP PULSE VIB");
379         stop_pulse_vib();
380     }
381     if (Trg & PAD_BUTTON_START)
382     {                                  // Move scene to save/load pulse state
383         stop_pulse_vib();
384         dp_clear(LCD_TOP, 0, 22, 32);
385         dp_clear(LCD_TOP, 0, 23, 32);
386         print_usage(MM_SAVE);
387 
388         // Read from backup
389 #ifdef USE_BACKUP
390         CARD_LockBackup(backup_lockid);
391         {
392             PulseStateBackup backup;
393 
394             if (CARD_ReadEeprom(0, &backup, sizeof(PulseStateBackup)))
395             {
396                 u32     check_sum = calc_sum(backup.pulse_state, sizeof(backup.pulse_state));
397                 if (check_sum == backup.check_sum)
398                 {
399                     MI_CpuCopyFast(backup.pulse_state, save_slot, sizeof(backup.pulse_state));
400                     OS_PutString("Read data from EEPROM.\n");
401                     print_message("LOAD DATA FROM BACKUP");
402                 }
403                 else
404                 {
405                     OS_PutString("Read data checksum error.\n");
406                 }
407                 backup_is_enable = TRUE;
408             }
409         }
410         CARD_UnlockBackup(backup_lockid);
411 #endif
412 
413         menu_mode = MM_SAVE;
414         line = 0;
415     }
416 }
417 
418 // Process of save/load state scene
save_and_load_pulse_state(void)419 static void save_and_load_pulse_state(void)
420 {
421 
422     if (Trg & PAD_KEY_UP)
423     {                                  // Choose save/load slot
424         if (line == 0)
425         {
426             line = SAVE_SLOT_NUM;
427         }
428         else
429         {
430             line--;
431         }
432     }
433     else if (Trg & PAD_KEY_DOWN)
434     {                                  // Choose save/load slot
435         if (line == SAVE_SLOT_NUM)
436         {
437             line = 0;
438         }
439         else
440         {
441             line++;
442         }
443     }
444     {
445         VIBPulseState *selected_state;
446 
447         if (line == 0)
448         {
449             selected_state = &pulse_state;
450         }
451         else
452         {
453             selected_state = &save_slot[line - 1];
454         }
455 
456         if (Trg & PAD_BUTTON_SELECT)
457         {                              // Load pulse state
458             if (line != 0)
459             {
460                 if (backup_is_enable)
461                 {
462                     print_message("LOAD DATA FROM BACKUP");
463                     dp_write_dec(line - 1, LCD_TOP, 23, 22);
464                 }
465                 else
466                 {
467                     print_message("LOAD DATA FROM SAVE");
468                     dp_write_dec(line - 1, LCD_TOP, 21, 22);
469                 }
470                 pulse_state = *selected_state;
471             }
472             stop_pulse_vib();
473             menu_mode = MM_SET_STATE;
474             print_usage(MM_SET_STATE);
475             line = 0;
476             return;
477         }
478         else if (Trg & PAD_BUTTON_START)
479         {                              // Save pulse state
480             stop_pulse_vib();
481             dp_clear(LCD_TOP, 0, 22, 32);
482             dp_clear(LCD_TOP, 0, 23, 32);
483             print_usage(MM_SET_STATE);
484 
485             if (line != 0)
486             {
487                 *selected_state = pulse_state;
488 
489                 if (backup_is_enable)
490                 {
491                     PulseStateBackup backup;
492 
493                     MI_CpuCopyFast(save_slot, backup.pulse_state, sizeof(backup.pulse_state));
494                     backup.check_sum = calc_sum(backup.pulse_state, sizeof(backup.pulse_state));
495 
496                     CARD_LockBackup(backup_lockid);
497                     if (CARD_WriteAndVerifyEeprom(0, &backup, sizeof(PulseStateBackup)))
498                     {
499                         OS_PutString("Write data to EEPROM.\n");
500                     }
501                     CARD_UnlockBackup(backup_lockid);
502                     print_message("SAVE CURRENT DATA TO BACKUP");
503                     dp_write_dec(line - 1, LCD_TOP, 29, 22);
504                 }
505                 else
506                 {
507                     print_message("SAVE CURRENT DATA TO SAVE");
508                     dp_write_dec(line - 1, LCD_TOP, 27, 22);
509                 }
510             }
511 
512             menu_mode = MM_SET_STATE;
513             line = 0;
514             return;
515         }
516 
517         if ((Trg & PAD_BUTTON_A) || (tp_trg.touch && tp_trg.x > 128))
518         {                              // Start pulse vibration
519             if (line == 0)
520             {
521                 print_message("START PULSE VIB");
522             }
523             else
524             {
525                 print_message("START PULSE VIB SAVE");
526                 dp_write_dec(line - 1, LCD_TOP, 22, 22);
527             }
528             (void)start_pulse_vib(selected_state);
529         }
530         else if (tp_trg.touch && tp_trg.x <= 128)
531         {                              // Start one-time pulse vibration
532             VIBPulseState state_temp = *selected_state;
533             if (line == 0)
534             {
535                 print_message("START ONE TIME PULSE VIB");
536             }
537             else
538             {
539                 print_message("START ONE TIME PULSE VIB SAVE");
540                 dp_write_dec(line - 1, LCD_TOP, 31, 22);
541             }
542             state_temp.repeat_num = 1;
543             (void)start_pulse_vib(&state_temp);
544         }
545         else if (Trg & PAD_BUTTON_B || (tp_uptrg.touch && tp_uptrg.x > 128))
546         {                              // Stop pulse vibration
547             print_message("STOP PULSE VIB");
548 #ifdef USE_VIB
549             stop_pulse_vib();
550 #endif
551         }
552 
553         write_pulse_state(selected_state);      // Display current pulse state
554     }
555     dp_write("@", LCD_BOTTOM, 20, line + 1);    // Display cursor
556     write_save_words();                // Display save slot words
557 }
558 
559 // Display pulse state
write_pulse_state(VIBPulseState * state)560 static void write_pulse_state(VIBPulseState * state)
561 {
562 
563     s32     i;
564 
565     // Display on/off time length
566     for (i = 0; i < state->pulse_num; i++)
567     {
568         double  time;
569         char    buf[32];
570 
571         time = (double)state->on_time[i];
572         time = time / 10;
573 
574         (void)snprintf(buf, 32, "%6.1f", time);
575 
576         if (state->on_time[i] > VIB_ON_TIME_MAX)
577             dp_set_pltt(1);
578         dp_write(buf, LCD_BOTTOM, 9, i * 2 + 1);
579         if (state->on_time[i] > VIB_ON_TIME_MAX)
580             dp_set_pltt(0);
581 
582         time = (double)state->off_time[i];
583         time = time / 10;
584 
585         (void)snprintf(buf, 32, "%6.1f", time);
586 
587         if (state->on_time[i] > state->off_time[i])
588             dp_set_pltt(1);
589         dp_write(buf, LCD_BOTTOM, 9, i * 2 + 2);
590         if (state->on_time[i] > state->off_time[i])
591             dp_set_pltt(0);
592 
593         dp_write(" ON  :", LCD_BOTTOM, 3, i * 2 + 1);
594         dp_write("OFF  :", LCD_BOTTOM, 3, i * 2 + 2);
595         dp_write_dec(i + 1, LCD_BOTTOM, 7, i * 2 + 1);
596         dp_write_dec(i + 1, LCD_BOTTOM, 7, i * 2 + 2);
597         dp_write("ms", LCD_BOTTOM, 15, i * 2 + 1);
598         dp_write("ms", LCD_BOTTOM, 15, i * 2 + 2);
599     }
600     dp_clear(LCD_BOTTOM, 0, (s32)state->pulse_num * 2, 32);
601 
602     // Display rest time
603     {
604         double  time;
605         char    buf[32];
606 
607         time = (double)state->rest_time;
608         time = time / 10;
609 
610         (void)snprintf(buf, 32, "%6.1f", time);
611 
612         dp_write(" REST:", LCD_BOTTOM, 3, 13);
613         if (state->rest_time < VIB_REST_TIME_MIN)
614             dp_set_pltt(1);
615         dp_write(buf, LCD_BOTTOM, 9, 13);
616         if (state->rest_time < VIB_REST_TIME_MIN)
617             dp_set_pltt(0);
618         dp_write("ms", LCD_BOTTOM, 15, 13);
619     }
620 
621     // Display pulse num
622     dp_write_dec((s32)state->pulse_num, LCD_BOTTOM, 13, 16);
623     dp_write("PULSE NUM:", LCD_BOTTOM, 2, 16);
624 }
625 
626 // Get pointer to pointed parameter by cursor
get_state_value_from_line(VIBPulseState * state,s32 line)627 static u32 *get_state_value_from_line(VIBPulseState * state, s32 line)
628 {
629 
630     if (line == pulse_state.pulse_num * 2 - 1)
631     {
632         return &(state->rest_time);
633     }
634     else
635     {
636         if (line & 1)
637         {
638             return &(state->off_time[line >> 1]);
639         }
640         else
641         {
642             return &(state->on_time[line >> 1]);
643         }
644     }
645 }
646 
647 // Display save slot words
write_save_words(void)648 static void write_save_words(void)
649 {
650 
651     dp_write("CURRENT", LCD_BOTTOM, 22, 1);
652     dp_write("SAVE 0 ", LCD_BOTTOM, 22, 2);
653     dp_write("SAVE 1 ", LCD_BOTTOM, 22, 3);
654     dp_write("SAVE 2 ", LCD_BOTTOM, 22, 4);
655     dp_write("SAVE 3 ", LCD_BOTTOM, 22, 5);
656     dp_write("SAVE 4 ", LCD_BOTTOM, 22, 6);
657     dp_write("SAVE 5 ", LCD_BOTTOM, 22, 7);
658     dp_write("SAVE 6 ", LCD_BOTTOM, 22, 8);
659     dp_write("SAVE 7 ", LCD_BOTTOM, 22, 9);
660 }
661 
662 // Display message text
print_message(char * str)663 static void print_message(char *str)
664 {
665     dp_clear(LCD_TOP, 0, 22, 32);
666     dp_clear(LCD_TOP, 0, 23, 32);
667     dp_write(str, LCD_TOP, 1, 22);
668 }
669 
670 // Display usage
print_usage(MenuMode mode)671 static void print_usage(MenuMode mode)
672 {
673 
674     dp_clear(LCD_TOP, 0, 3, 32 * 10);
675     dp_write("A: START PULSE VIB", LCD_TOP, 1, 3);
676     dp_write("B: STOP PULSE VIB", LCD_TOP, 1, 4);
677 
678     switch (mode)
679     {
680     case MM_SET_STATE:
681         dp_write("Y: CHANGE PULSE NUM", LCD_TOP, 1, 5);
682         dp_write("X: PUSH TO SPEEDUP LEFT/RIGHT", LCD_TOP, 1, 6);
683         dp_write("R: PUSH TO SPEED+++ LEFT/RIGHT", LCD_TOP, 1, 7);
684         dp_write("   UP/DOWN: CHOOSE PARAM", LCD_TOP, 1, 8);
685         dp_write("LEFT/RIGHT: CHANGE PARAM NUM", LCD_TOP, 1, 9);
686         dp_write("     START: ENTER SAVE MENU", LCD_TOP, 1, 10);
687         break;
688     case MM_SAVE:
689         dp_write("UP/DOWN: CHOOSE SAVE SLOT", LCD_TOP, 1, 5);
690         dp_write("  START: SAVE DATA AND EXIT", LCD_TOP, 1, 6);
691         dp_write(" SELECT: LOAD DATA AND EXIT", LCD_TOP, 1, 7);
692         break;
693     }
694 
695     dp_write("TOUCH RIGHT SIDE:", LCD_TOP, 1, 12);
696     dp_write("     CONTINUOUS PULSE VIB", LCD_TOP, 1, 13);
697     dp_write("TOUCH LEFT SIDE:", LCD_TOP, 1, 14);
698     dp_write("     ONE TIME PULSE VIB", LCD_TOP, 1, 15);
699 }
700 
701 // Initialize variables
set_first_state(void)702 static void set_first_state(void)
703 {
704 
705     u32     i;
706 
707     pulse_state.pulse_num = 2;
708     pulse_state.rest_time = 500;
709     pulse_state.repeat_num = 0;
710 
711     pulse_state.on_time[0] = 15;
712     pulse_state.on_time[1] = 15;
713     pulse_state.on_time[2] = 15;
714     pulse_state.on_time[3] = 15;
715     pulse_state.on_time[4] = 15;
716     pulse_state.on_time[5] = 15;
717 
718     pulse_state.off_time[0] = 15;
719     pulse_state.off_time[1] = 15;
720     pulse_state.off_time[2] = 15;
721     pulse_state.off_time[3] = 15;
722     pulse_state.off_time[4] = 15;
723     pulse_state.off_time[5] = 15;
724 
725     MI_CpuClearFast(save_slot, sizeof(save_slot));
726 
727     for (i = 0; i < SAVE_SLOT_NUM; i++)
728     {
729         save_slot[i].pulse_num = VIB_PULSE_NUM_MAX;
730         save_slot[i].rest_time = 100;
731         save_slot[i].repeat_num = 0;
732 
733         save_slot[i].on_time[0] = 10;
734         save_slot[i].on_time[1] = 10;
735         save_slot[i].on_time[2] = 10;
736         save_slot[i].on_time[3] = 10;
737         save_slot[i].on_time[4] = 10;
738         save_slot[i].on_time[5] = 10;
739 
740         save_slot[i].off_time[0] = 10;
741         save_slot[i].off_time[1] = 10;
742         save_slot[i].off_time[2] = 10;
743         save_slot[i].off_time[3] = 10;
744         save_slot[i].off_time[4] = 10;
745         save_slot[i].off_time[5] = 10;
746     }
747 }
748 
749 // Read Touch Panel data
read_tp(void)750 static void read_tp(void)
751 {
752 
753     TPData  tp_raw;
754 
755     tp_pre = tp_last;
756 
757     while (TP_RequestRawSampling(&tp_raw) != 0)
758     {
759     }
760     TP_GetCalibratedPoint(&tp_last, &tp_raw);
761 
762     if (tp_last.validity != TP_VALIDITY_VALID)
763     {
764         tp_last = tp_pre;
765         tp_last.touch = 0;
766     }
767 
768     if (tp_last.touch && (!tp_pre.touch))
769     {
770         tp_trg = tp_last;
771     }
772     else
773     {
774         tp_trg.touch = FALSE;
775     }
776 
777     if ((!tp_last.touch) && tp_pre.touch)
778     {
779         tp_uptrg = tp_pre;
780     }
781     else
782     {
783         tp_uptrg.touch = FALSE;
784     }
785 }
786 
787 // If Game Pak pulled out, display caution and set flag
cartridge_pullout_callback(void)788 static void cartridge_pullout_callback(void)
789 {
790 
791     cartridge_pullout_flag = TRUE;
792 }
793 
calc_sum(void * addr,u32 size)794 static u32 calc_sum(void *addr, u32 size)
795 {
796 
797     u32     i;
798     u32     times = size / 4;
799     u32    *num_by_4byte = addr;
800     u32     sum = 0;
801 
802     for (i = 0; i < times; i++)
803     {
804         sum += *num_by_4byte;
805         num_by_4byte++;
806     }
807 
808     return sum;
809 }
810 
start_pulse_vib(VIBPulseState * state)811 static BOOL start_pulse_vib(VIBPulseState * state)
812 {
813     int     i;
814 
815     /* Does the ON time exceed VIB_ON_TIME_MAX? */
816     for (i = 0; i < state->pulse_num; i++)
817     {
818         if (state->on_time[i] > VIB_ON_TIME_MAX)
819         {
820             VIB_StopPulse();
821             dp_set_pltt(1);
822             dp_write("ON time[", LCD_TOP, 1, 22);
823             dp_write_dec(i + 1, LCD_TOP, 9, 22);
824             dp_write("] is over", LCD_TOP, 10, 22);
825             dp_write("VIB_ON_TIME_MAX", LCD_TOP, 1, 23);
826             dp_set_pltt(0);
827             return FALSE;
828         }
829     }
830     /* Does the OFF time exceed the previous ON time? */
831     for (i = 0; i < state->pulse_num - 1; i++)
832     {
833         if (state->on_time[i] > state->off_time[i])
834         {
835             VIB_StopPulse();
836             dp_set_pltt(1);
837             dp_write("ON time[", LCD_TOP, 1, 22);
838             dp_write_dec(i + 1, LCD_TOP, 9, 22);
839             dp_write("] is over OFF time[", LCD_TOP, 10, 22);
840             dp_write_dec(i + 1, LCD_TOP, 29, 22);
841             dp_write("]", LCD_TOP, 30, 22);
842             dp_set_pltt(0);
843             return FALSE;
844         }
845     }
846     /* Is the REST time less than VIB_REST_TIME_MIN? */
847     if (state->rest_time < VIB_REST_TIME_MIN)
848     {
849         VIB_StopPulse();
850         dp_set_pltt(1);
851         dp_write("REST time is less than", LCD_TOP, 1, 22);
852         dp_write("VIB_REST_TIME_MIN", LCD_TOP, 1, 23);
853         dp_set_pltt(0);
854         return FALSE;
855     }
856 
857     VIB_StartPulse(state);
858     return TRUE;
859 }
860 
stop_pulse_vib(void)861 static void stop_pulse_vib(void)
862 {
863 
864     VIB_StopPulse();
865 }
866 
read_key_data(void)867 void read_key_data(void)
868 {
869 
870     int     i;
871     u16     keyData;
872     u16     bit;
873     static u8 keyrep_count[16];
874 
875     //---- Load pad data
876     keyData = PAD_Read();
877     Trg = (u16)(keyData & (keyData ^ Cont));
878     Cont = keyData;
879     Rpt = 0;
880     for (i = 0; i < KEY_NUM; ++i)
881     {
882         if (!(Cont & (bit = (u16)(PAD_BUTTON_A << i))))
883         {
884             keyrep_count[i] = 0;
885             continue;
886         }
887         keyrep_count[i]++;
888         if (keyrep_count[i] == KEYREPEAT_FIRST)
889         {
890             Rpt |= bit;
891             continue;
892         }
893         if (keyrep_count[i] == KEYREPEAT_FIRST + KEYREPEAT_INTERVAL)
894         {
895             Rpt |= bit;
896             keyrep_count[i] = KEYREPEAT_FIRST;
897         }
898     }
899 }
900