gpfce patch part2
[fceu.git] / drivers / cli / input.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define JOY_A   1
22 #define JOY_B   2
23 #define JOY_SELECT      4
24 #define JOY_START       8
25 #define JOY_UP  0x10
26 #define JOY_DOWN        0x20
27 #define JOY_LEFT        0x40
28 #define JOY_RIGHT       0x80
29
30
31 #include "minimal.h"
32 extern int swapbuttons;
33 extern int stretch_offset;
34 extern void SetVideoScaling(int pixels,int width,int height);
35 long UpdateGamepadGP2X(void);
36
37
38
39
40
41 static void UpdateFKB(void);
42
43
44
45
46
47 /* UsrInputType[] is user-specified.  InputType[] is current
48         (game loading can override user settings) 
49 */
50 static int UsrInputType[2]={SI_GAMEPAD,SI_GAMEPAD};
51 static int InputType[2];
52
53 static int UsrInputTypeFC={SI_NONE};
54 static int InputTypeFC;
55
56 static uint32 JSreturn;
57 int NoWaiting=0;
58
59 static void DoCheatSeq(void)
60 {
61  #if defined(DOS) || defined(SDL)
62  if(inited&1)
63   SilenceSound(1);
64  #endif
65  KillKeyboard();
66  KillVideo();
67
68  DoConsoleCheatConfig();
69  InitVideo();
70  InitKeyboard();
71  #if defined(DOS) || defined(SDL)
72  if(inited&1)
73   SilenceSound(0);
74  #endif
75 }
76
77 #include "keyscan.h"
78 static char *keys;
79 static int DIPS=0;
80 #ifndef GP2X
81 static uint8 keyonce[MK_COUNT];
82 #define KEY(__a) keys[MK(__a)]
83 #define keyonly(__a,__z) {if(KEY(__a)){if(!keyonce[MK(__a)]) {keyonce[MK(__a)]=1;__z}}else{keyonce[MK(__a)]=0;}}
84 #endif
85
86 static int JoySwap=0;
87 static int cidisabled=0;
88 static int KeyboardUpdate(void)
89 {
90 #ifndef GP2X
91  if(!UpdateKeyboard())
92    if(keys)
93     return 0;
94
95   keys=GetKeyboard(); 
96
97   if(InputTypeFC==SIFC_FKB)
98   {
99    keyonly(SCROLLLOCK,cidisabled^=1;
100     FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis");)
101    #ifdef SDL
102    SDL_WM_GrabInput(cidisabled?SDL_GRAB_ON:SDL_GRAB_OFF);
103    #endif
104    if(cidisabled) return(1);
105   }
106   #ifdef SVGALIB
107   keyonly(F3,LockConsole();)  
108   keyonly(F4,UnlockConsole();)
109   #elif SDL
110   keyonly(F4,ToggleFS();)
111   #endif
112   NoWaiting&=~1;
113   if(KEY(GRAVE))
114    NoWaiting|=1;
115
116   if(gametype==GIT_FDS)
117   {
118    keyonly(S,DriverInterface(DES_FDSSELECT,0);)
119    keyonly(I,DriverInterface(DES_FDSINSERT,0);)
120    keyonly(E,DriverInterface(DES_FDSEJECT,0);)
121   }
122
123  keyonly(F9,FCEUI_SaveSnapshot();)
124  if(gametype!=GIT_NSF)
125  {
126   keyonly(F2,DoCheatSeq();)
127   keyonly(F5,FCEUI_SaveState();)
128   keyonly(F7,FCEUI_LoadState();)
129  }
130  else
131  {
132   keyonly(CURSORLEFT,DriverInterface(DES_NSFDEC,0);)
133   keyonly(CURSORRIGHT,DriverInterface(DES_NSFINC,0);)
134   if( KEY(ENTER)) DriverInterface(DES_NSFRES,0);
135   if( KEY(CURSORUP)) DriverInterface(DES_NSFINC,0);
136   if( KEY(CURSORDOWN)) DriverInterface(DES_NSFDEC,0);
137  }
138
139  keyonly(F10,DriverInterface(DES_RESET,0);)
140  keyonly(F11,DriverInterface(DES_POWER,0);)
141  if(KEY(F12) || KEY(ESCAPE)) FCEUI_CloseGame();
142
143  if(gametype==GIT_VSUNI)
144  {
145    keyonly(C,DriverInterface(DES_VSUNICOIN,0);)
146    keyonly(V,DIPS^=1;DriverInterface(DES_VSUNITOGGLEDIPVIEW,0);)
147    if(!(DIPS&1)) goto DIPSless;
148    keyonly(1,DriverInterface(DES_VSUNIDIPSET,(void *)1);)
149    keyonly(2,DriverInterface(DES_VSUNIDIPSET,(void *)2);)
150    keyonly(3,DriverInterface(DES_VSUNIDIPSET,(void *)3);)
151    keyonly(4,DriverInterface(DES_VSUNIDIPSET,(void *)4);)
152    keyonly(5,DriverInterface(DES_VSUNIDIPSET,(void *)5);)
153    keyonly(6,DriverInterface(DES_VSUNIDIPSET,(void *)6);)
154    keyonly(7,DriverInterface(DES_VSUNIDIPSET,(void *)7);)
155    keyonly(8,DriverInterface(DES_VSUNIDIPSET,(void *)8);)
156  }
157  else
158  {
159   keyonly(H,DriverInterface(DES_NTSCSELHUE,0);)
160   keyonly(T,DriverInterface(DES_NTSCSELTINT,0);)
161   if(KEY(KP_MINUS) || KEY(MINUS)) DriverInterface(DES_NTSCDEC,0);
162   if(KEY(KP_PLUS) || KEY(EQUAL)) DriverInterface(DES_NTSCINC,0);
163
164   DIPSless:
165   keyonly(0,FCEUI_SelectState(0);)
166   keyonly(1,FCEUI_SelectState(1);)
167   keyonly(2,FCEUI_SelectState(2);)
168   keyonly(3,FCEUI_SelectState(3);)
169   keyonly(4,FCEUI_SelectState(4);)
170   keyonly(5,FCEUI_SelectState(5);)
171   keyonly(6,FCEUI_SelectState(6);)
172   keyonly(7,FCEUI_SelectState(7);)
173   keyonly(8,FCEUI_SelectState(8);)
174   keyonly(9,FCEUI_SelectState(9);)
175  }
176  return 1;
177 #else
178  return 1;
179 #endif
180 }
181
182 static uint32 KeyboardDodo(void)
183 {
184 #ifndef GP2X
185  uint32 JS=0;
186
187  if(gametype!=GIT_NSF)
188  {
189   int x,y;
190   x=y=0;
191   keyonly(CAPSLOCK,
192                    {
193                     char tmp[64];
194                     JoySwap=(JoySwap+8)%32;
195                     sprintf(tmp,"Joystick %d selected.",(JoySwap>>3)+1);
196                     FCEUI_DispMessage(tmp);
197                    })
198
199   if(KEY(LEFTALT) || KEY(X))        JS|=JOY_A<<JoySwap;
200   if(KEY(LEFTCONTROL) || KEY(SPACE) || KEY(Z) ) JS |=JOY_B<<JoySwap;
201   if(KEY(ENTER))       JS |= JOY_START<<JoySwap;
202   if(KEY(TAB))         JS |= JOY_SELECT<<JoySwap;
203   if(KEY(CURSORDOWN))  y|= JOY_DOWN;
204   if(KEY(CURSORUP))    y|= JOY_UP;
205   if(KEY(CURSORLEFT))  x|= JOY_LEFT;
206   if(KEY(CURSORRIGHT)) x|= JOY_RIGHT;
207   if(y!=(JOY_DOWN|JOY_UP)) JS|=y<<JoySwap;
208   if(x!=(JOY_LEFT|JOY_RIGHT)) JS|=x<<JoySwap;
209  }
210  return JS;
211 #else
212  return 0;
213 #endif
214 }
215
216 #ifndef GP2X
217 static int powerpadsc[2][12]={
218                               {
219                                MK(O),MK(P),MK(BRACKET_LEFT),
220                                MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
221                                 MK(APOSTROPHE),
222                                MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
223                               },
224                               {
225                                MK(O),MK(P),MK(BRACKET_LEFT),
226                                MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
227                                 MK(APOSTROPHE),
228                                MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
229                               }
230                              };
231
232 static uint32 powerpadbuf[2];
233 #else
234 static int powerpadsc[2][12];
235 #endif
236 static int powerpadside=0;
237
238
239 static uint32 UpdatePPadData(int w)
240 {
241 #ifndef GP2X
242  static const char shifttableA[12]={8,9,0,1,11,7,4,2,10,6,5,3};
243  static const char shifttableB[12]={1,0,9,8,2,4,7,11,3,5,6,10};
244  uint32 r=0;
245  int *ppadtsc=powerpadsc[w];
246  int x;
247
248  if(powerpadside&(1<<w))
249  {
250   for(x=0;x<12;x++)
251    if(keys[ppadtsc[x]]) r|=1<<shifttableA[x];
252  }
253  else
254  {
255   for(x=0;x<12;x++)
256    if(keys[ppadtsc[x]]) r|=1<<shifttableB[x];
257  }
258  return r;
259 #endif
260  return 0;
261 }
262
263 static uint32 MouseData[3];
264 static uint8 fkbkeys[0x48];
265 unsigned long lastpad=0;
266
267 void FCEUD_UpdateInput(void)
268 {
269   int t=0;
270 #ifndef GP2X    
271   int x;
272   static uint32 KeyBJS=0;
273   uint32 JS;
274   int b;
275 #endif 
276 #ifdef GP2X
277   long lastpad2=lastpad;
278   long pad = UpdateGamepadGP2X();
279   t=1;
280   //  JSreturn=(JSreturn&0xFF000000)|(JSreturn&0xFF)|((JSreturn&0xFF0000)>>8)|((JSreturn&0xFF00)<<8);
281   if(gametype==GIT_FDS)
282   {     
283     NoWaiting&=~1;
284         if ((pad & GP2X_PUSH) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_R)) && (!(lastpad2 & GP2X_PUSH)))
285         {
286       DriverInterface(DES_FDSSELECT,0);
287         }
288         else if ((pad & GP2X_L) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_PUSH)) && (!(pad & GP2X_R))&& (!(lastpad2 & GP2X_L)))
289         {
290       DriverInterface(DES_FDSINSERT,0);
291         }
292         else if ((pad & GP2X_R) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_PUSH)) && (!(lastpad2 & GP2X_R)))
293         {
294       DriverInterface(DES_FDSEJECT,0);
295         }
296   }
297
298 #else
299   UpdateGamepadGP2X();
300   b=KeyboardUpdate();
301
302   for(x=0;x<2;x++)
303    switch(InputType[x])
304    {
305     case SI_GAMEPAD:t|=1;break;
306     case SI_ARKANOID:t|=2;break;
307     case SI_ZAPPER:t|=2;break;
308     case SI_POWERPAD:powerpadbuf[x]=UpdatePPadData(x);break;
309    }
310
311   switch(InputTypeFC)
312   {
313    case SIFC_ARKANOID:t|=2;break;
314    case SIFC_SHADOW:t|=2;break;
315    case SIFC_FKB:if(cidisabled) UpdateFKB();break;
316   }
317
318   if(t&1)
319   {
320    if(b)
321     KeyBJS=KeyboardDodo();
322    JS=KeyBJS;
323    JS|=(uint32)GetJSOr();
324    JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
325   }
326   if(t&2)
327    GetMouseData(MouseData);
328    
329 #endif
330 }
331
332
333
334
335
336 //#ifdef GP2X
337
338 extern void ResetNES(void);
339 extern void CleanSurface(void);
340
341 char soundvolmeter[21];
342 int soundvolIndex=0;
343 int L_count=0;
344 int R_count=0;
345 extern int CurrentState;
346 int TurboFireOff=1;
347 int TurboFireTop=0;  // 0 is none  // 1 is  A & X turbo  // 2 is Y & B turbo
348 int TurboFireBottom=0;
349 int turbo_toggle_A=0;
350 int turbo_toggle_B=0;
351
352 static void setsoundvol(int soundvolume)
353 {
354     //FCEUI_SetSoundVolume(soundvol);
355     // draw on screen :D
356     gp2x_sound_volume(soundvolume, soundvolume);
357     int meterval=soundvolume/5;
358     for (soundvolIndex=0; soundvolIndex < 20; soundvolIndex++)
359     {
360        if (soundvolIndex < meterval)
361        {
362           soundvolmeter[soundvolIndex]='*';
363        }
364        else
365        { 
366           soundvolmeter[soundvolIndex]='_';
367        }
368     }
369     soundvolmeter[20]=0;
370     FCEU_DispMessage("|%s|", soundvolmeter);    
371 }
372 /**
373  * GP2x joystick reader
374  *
375  */ 
376 INLINE long UpdateGamepadGP2X(void)
377 {
378   uint32 JS=0;
379
380   unsigned long pad=gp2x_joystick_read();
381 #define L_down (pad & GP2X_L)
382 #define R_down (pad & GP2X_R)
383 #define last_L_down (lastpad & GP2X_L)
384 #define last_R_down (lastpad & GP2X_R)
385   
386   if (L_down && R_down && (!(pad & GP2X_PUSH))
387       && (!(last_R_down && last_L_down)))
388   {
389      ResetNES();
390      puts("Reset"); 
391      JSreturn=0;
392      lastpad=pad;
393      return pad;
394   }
395
396
397
398   
399   if (pad & GP2X_VOL_UP)
400   {
401     soundvol+=1;
402     if (soundvol >= 100) soundvol=100;
403     //FCEUI_SetSoundVolume(soundvol);
404     setsoundvol(soundvol);
405   }
406   if (pad & GP2X_VOL_DOWN)
407   {
408     soundvol-=1;
409     if (soundvol < 0) soundvol=0;
410     //FCEUI_SetSoundVolume(soundvol);
411     setsoundvol(soundvol);
412   }
413   if (pad & GP2X_PUSH)
414   {    
415     // only if it's something else then last time, and not moving around the joystick
416     if (!((pad & GP2X_UP) ||(pad & GP2X_DOWN) || (pad & GP2X_LEFT) || (pad & GP2X_RIGHT)))
417     {
418       if (pad & GP2X_SELECT)
419       {
420         if ((lastpad & GP2X_SELECT) && (lastpad & GP2X_PUSH))
421         {
422           // still pressed down from stretching from last one
423           JSreturn=0; 
424           lastpad=pad;
425           return 0;
426         }
427         if (stretch_offset == 32)
428         {
429           stretch_offset=0;
430         }
431         else
432         {
433           stretch_offset=32;
434         }
435
436         if (stretch_offset == 32)
437         {          
438           SetVideoScaling(320, 320, 240);
439           CleanSurface();
440         }
441         else
442         {
443           SetVideoScaling(320, 256, 240);
444         }
445
446         JSreturn=0;
447         lastpad=pad;
448         return pad;
449       }
450       else if (L_down && R_down)
451       {
452         FCEUI_CloseGame();
453         puts("Quit"); 
454         JSreturn=0;
455         return 0;
456       }
457       else if (R_down && (!((lastpad & GP2X_R) && (lastpad & GP2X_PUSH))))
458       {
459        FCEUI_LoadState();
460        JSreturn=0;
461        lastpad=pad;
462        return 0;
463       }
464       else if (L_down && (!((lastpad & GP2X_L) && (lastpad & GP2X_PUSH))))
465       {
466        FCEUI_SaveState();
467        JSreturn=0;
468        lastpad=pad;
469        return 0;
470       }
471     }
472   }
473   
474   // r is toggle savestate
475   if (R_down)
476   {
477         if (last_R_down)
478         {
479           R_count++;
480       if ((R_count & 31)== 31)
481       {
482                 CurrentState=(CurrentState+1) % 10;
483                 FCEUI_DispMessage("Now Using Save State %d", CurrentState);
484           }
485         }
486   }
487   else
488   {
489     R_count=0;
490   }
491   
492   // l is toggle turbo
493   if (L_down)
494   {
495         if (last_L_down)
496         {
497           L_count++;
498       if ((L_count & 31)== 31)
499       {
500        // 0 is none  // 1 is  Y & B turbo  // 2 is X & A turbo
501         if ((!TurboFireTop) && (!TurboFireBottom))
502         {
503                 // was off
504                 TurboFireTop=1;
505                 TurboFireBottom=0;              
506                 if (swapbuttons)
507                 {
508                   FCEUI_DispMessage("Turbo A and Y");           
509                 }
510                 else
511                 {
512                   FCEUI_DispMessage("Turbo Y and B");           
513                 }
514         }
515         else if (TurboFireTop)
516         {
517                 TurboFireTop=0;
518                 TurboFireBottom=1;              
519                 if (swapbuttons)
520                 {
521                   FCEUI_DispMessage("Turbo X and B");           
522                 }
523                 else
524                 {
525                   FCEUI_DispMessage("Turbo A and X");           
526                 }
527         }
528         else
529         {
530                 TurboFireTop=0;
531                 TurboFireBottom=0;              
532                 FCEUI_DispMessage("Turbo Off");         
533         }
534         
535           }
536         }
537   }
538   else
539   {
540     L_count=0;
541   }
542   
543   
544   
545   //unsigned long padTmp=0;
546   // shift the bits in
547   // up
548   //padTmp=(pad & GP2X_UP) ;  // 1 is 2^0, 
549   JS |= ((pad & GP2X_UP) << (4-0));  // 0x10 is 2^4
550
551   //padTmp=(pad & GP2X_DOWN);  // 0x10 is 2^4, 
552   JS |= ((pad & GP2X_DOWN) << (5-4));  // 0x20 is 2^5
553
554   //padTmp=(pad & GP2X_LEFT);  // 0x4 is 2^2, 
555   JS |= ((pad & GP2X_LEFT) << (6-2));  // 0x40 is 2^6
556
557   //padTmp=(pad & GP2X_RIGHT);  // 0x40 is 2^6,  
558   JS |= ((pad & GP2X_RIGHT) << (7-6));  // 0x80 is 2^7
559
560
561 #define  A_down (pad & GP2X_A)
562 #define  B_down (pad & GP2X_B)
563 #define  X_down (pad & GP2X_X)
564 #define  Y_down (pad & GP2X_Y)
565
566   // should be 2 cycles held, 1 cycle release
567   turbo_toggle_A=(turbo_toggle_A+1) % 3;
568   turbo_toggle_B=(turbo_toggle_B+1) % 3;
569  
570    // 0 is none  // 1 is  Y & B turbo  // 2 is X & A turbo
571   // B or X are both considered A
572   //padTmp=B_down >> 13;  // 2^13,
573   
574    if (!(TurboFireTop && (!turbo_toggle_A)))
575    {
576     JS |= ((B_down >> 13) << 0);  // 0x1 is 2^0
577    }
578    // A or Y are both considered B
579    //padTmp=A_down >> 12;  // 2^13,  
580    if (!(TurboFireBottom && (!turbo_toggle_B)))
581    {
582     JS |= ((A_down >> 12) << 1);  // 0x2 is 2^1
583    }
584   
585   if (swapbuttons)
586   {
587    //padTmp=X_down >> 14;  // 2^13,  
588    if (!(TurboFireBottom && (!turbo_toggle_A)))
589    {
590 //    JS |= ((X_down >> 14) << 0);  // 0x1 is 2^0
591     JS |= ((Y_down >> 15) << 0);  // 0x1 is 2^0
592    }
593
594    //padTmp=Y_down >> 15;  // 2^13,  
595    if (!(TurboFireTop && (!turbo_toggle_B)))
596    {
597     JS |= ((X_down >> 14) << 1);  // 0x2 is 2^1
598    }
599   }
600   else
601   {  
602    //padTmp=X_down >> 14;  // 2^13,  
603    if (!(TurboFireBottom && (!turbo_toggle_A)))
604    {
605     JS |= ((X_down >> 14) << 0);  // 0x1 is 2^0
606    }
607
608    //padTmp=Y_down >> 15;  // 2^13,  
609    if (!(TurboFireTop && (!turbo_toggle_B)))
610    {
611     JS |= ((Y_down >> 15) << 1);  // 0x2 is 2^1
612    }
613   }
614
615   // select
616   //padTmp=(pad & GP2X_SELECT) >> 9;  // 0x40 is 2^9,  
617   JS |= (((pad & GP2X_SELECT) >> 9) << 2);  // 0x4 is 2^2
618
619   // start
620   //padTmp=(pad & GP2X_START) >> 8;  //   2^8,  
621   JS |= (((pad & GP2X_START) >> 8) << 3);  // 0x8 is 2^3
622
623
624   JSreturn = JS;
625   lastpad=pad;
626
627   return pad;
628   //JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
629 }
630 //#endif
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645 static void InitOtherInput(void)
646 {
647
648    void *InputDPtr;
649
650    int t;
651    int x;
652    int attrib;
653
654    for(t=0,x=0;x<2;x++)
655    {
656     attrib=0;
657     InputDPtr=0;
658     switch(InputType[x])
659     {
660       //case SI_POWERPAD:InputDPtr=&powerpadbuf[x];break;
661      case SI_GAMEPAD:InputDPtr=((uint8 *)&JSreturn)+(x<<1);break;     
662      case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
663      case SI_ZAPPER:InputDPtr=MouseData;
664                                 t|=1;
665                                 attrib=1;
666                                 break;
667     }
668     FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
669    }
670
671    attrib=0;
672    InputDPtr=0;
673    switch(InputTypeFC)
674    {
675     case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break;
676     case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
677     case SIFC_FKB:InputDPtr=fkbkeys;break;
678    }
679
680    FCEUI_SetInputFC(InputTypeFC,InputDPtr,attrib);
681    FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
682
683    if(t && !(inited&16)) 
684    {
685     InitMouse();
686     inited|=16;
687    }
688
689 }
690 #ifndef GP2X
691 int fkbmap[0x48]=
692 {
693  MK(F1),MK(F2),MK(F3),MK(F4),MK(F5),MK(F6),MK(F7),MK(F8),
694  MK(1),MK(2),MK(3),MK(4),MK(5),MK(6),MK(7),MK(8),MK(9),MK(0),
695         MK(MINUS),MK(EQUAL),MK(BACKSLASH),MK(BACKSPACE),
696  MK(ESCAPE),MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I),MK(O),
697         MK(P),MK(GRAVE),MK(BRACKET_LEFT),MK(ENTER),
698  MK(LEFTCONTROL),MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),
699         MK(L),MK(SEMICOLON),MK(APOSTROPHE),MK(BRACKET_RIGHT),MK(INSERT),
700  MK(LEFTSHIFT),MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M),MK(COMMA),
701         MK(PERIOD),MK(SLASH),MK(RIGHTALT),MK(RIGHTSHIFT),MK(LEFTALT),MK(SPACE),
702  MK(DELETE),MK(END),MK(PAGEDOWN),
703  MK(CURSORUP),MK(CURSORLEFT),MK(CURSORRIGHT),MK(CURSORDOWN)
704 };
705 #endif
706
707 static void UpdateFKB(void)
708 {
709 #ifndef GP2X
710  int x;
711
712  for(x=0;x<0x48;x++)
713  {
714   fkbkeys[x]=0;
715   if(keys[fkbmap[x]])
716    fkbkeys[x]=1;
717  }
718 #endif
719 }