partially working menu
[fceu.git] / drivers / gp2x / 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 #include "minimal.h"
31
32 extern uint8 Exit; // exit emu loop
33
34 extern int swapbuttons;
35 extern int scaled_display;
36 extern int FSkip_setting;
37
38
39
40 /* UsrInputType[] is user-specified.  InputType[] is current
41         (game loading can override user settings)
42 */
43 static int UsrInputType[2]={SI_GAMEPAD,SI_GAMEPAD};
44 static int InputType[2];
45
46 static int UsrInputTypeFC={SI_NONE};
47 static int InputTypeFC;
48
49 static uint32 JSreturn;
50 int NoWaiting=0;
51
52 static int powerpadsc[2][12];
53 static int powerpadside=0;
54
55
56 static uint32 MouseData[3];
57 static uint8 fkbkeys[0x48];
58 unsigned long lastpad=0;
59
60 extern void ResetNES(void);
61 extern void CleanSurface(void);
62
63 char soundvolmeter[21];
64 int soundvolIndex=0;
65 int L_count=0;
66 int R_count=0;
67 extern int CurrentState;
68 int TurboFireOff=1;
69 int TurboFireTop=0;  // 0 is none  // 1 is  A & X turbo  // 2 is Y & B turbo
70 int TurboFireBottom=0;
71 int turbo_toggle_A=0;
72 int turbo_toggle_B=0;
73
74
75 static void setsoundvol(int soundvolume)
76 {
77     //FCEUI_SetSoundVolume(soundvol);
78     // draw on screen :D
79     gp2x_sound_volume(soundvolume, soundvolume);
80     int meterval=soundvolume/5;
81     for (soundvolIndex=0; soundvolIndex < 20; soundvolIndex++)
82     {
83        if (soundvolIndex < meterval)
84        {
85           soundvolmeter[soundvolIndex]='*';
86        }
87        else
88        {
89           soundvolmeter[soundvolIndex]='_';
90        }
91     }
92     soundvolmeter[20]=0;
93     FCEU_DispMessage("|%s|", soundvolmeter);
94 }
95
96
97
98 void FCEUD_UpdateInput(void)
99 {
100   long lastpad2=lastpad;
101   unsigned long pad=gp2x_joystick_read(1); // TODO: USB joys and stuff
102   uint32 JS=0;
103
104 #define down(b) (pad & GP2X_##b)
105 #define last_down(b) (lastpad & GP2X_##b)
106 #define L_down (pad & GP2X_L)
107 #define R_down (pad & GP2X_R)
108 #define last_L_down (lastpad & GP2X_L)
109 #define last_R_down (lastpad & GP2X_R)
110 #define shift      ((pad     & GP2X_PUSH) || ((pad     & (GP2X_VOL_UP|GP2X_VOL_DOWN)) == (GP2X_VOL_UP|GP2X_VOL_DOWN)))
111 #define last_shift ((lastpad & GP2X_PUSH) || ((lastpad & (GP2X_VOL_UP|GP2X_VOL_DOWN)) == (GP2X_VOL_UP|GP2X_VOL_DOWN)))
112
113   if (L_down && R_down && !(pad & GP2X_PUSH) && !(last_R_down && last_L_down))
114   {
115      ResetNES();
116      puts("Reset");
117      goto no_pad;
118   }
119
120   if (down(VOL_UP) && !down(VOL_DOWN))
121   {
122     soundvol+=1;
123     if (soundvol >= 100) soundvol=100;
124     //FCEUI_SetSoundVolume(soundvol);
125     setsoundvol(soundvol);
126   }
127   else if (down(VOL_DOWN) && !down(VOL_UP))
128   {
129     soundvol-=1;
130     if (soundvol < 0) soundvol=0;
131     //FCEUI_SetSoundVolume(soundvol);
132     setsoundvol(soundvol);
133   }
134   else if (down(VOL_DOWN) && down(VOL_UP))
135   {
136     Exit = 1;
137   }
138
139   if (shift)
140   {
141     // only if it's something else then last time, and not moving around the joystick
142     if (!(pad & (GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT)))
143     {
144       if (down(SELECT))
145       {
146         if (last_down(SELECT) && last_shift)
147         {
148           // still pressed down from stretching from last one
149           goto no_pad;
150         }
151         scaled_display = !scaled_display;
152
153         if (scaled_display)
154         {
155           gp2x_video_RGB_setscaling(0, 256, 240);
156         }
157         else
158         {
159           gp2x_video_RGB_setscaling(0, 320, 240);
160         }
161
162         goto no_pad;
163       }
164       else if (L_down && R_down)
165       {
166         FCEUI_CloseGame();
167         puts("Quit");
168         goto no_pad;
169       }
170       else if (R_down && !(last_R_down && last_shift))
171       {
172        FCEUI_LoadState();
173        goto no_pad;
174       }
175       else if (L_down && !(last_L_down && last_shift))
176       {
177        FCEUI_SaveState();
178        goto no_pad;
179       }
180       else if (down(A) && !(last_down(A) && last_shift))
181       {
182        FSkip_setting--;
183        if (FSkip_setting < 0) {
184         FSkip_setting = -1;
185         FCEUI_DispMessage("Auto frameskip");
186        }
187        else
188         FCEUI_DispMessage("Frameskip: %i", FSkip_setting);
189        goto no_pad;
190       }
191       else if (down(Y) && !(last_down(Y) && last_shift))
192       {
193        FSkip_setting++;
194        if (FSkip_setting > 8) FSkip_setting = 8;
195        FCEUI_DispMessage("Frameskip: %i", FSkip_setting);
196        goto no_pad;
197       }
198     }
199   }
200
201   // r is toggle savestate
202   if (R_down)
203   {
204         if (last_R_down)
205         {
206           R_count++;
207       if ((R_count & 31)== 31)
208       {
209                 CurrentState=(CurrentState+1) % 10;
210                 FCEUI_DispMessage("Now Using Save State %d", CurrentState);
211           }
212         }
213   }
214   else
215   {
216     R_count=0;
217   }
218
219   // l is toggle turbo
220   if (L_down)
221   {
222         if (last_L_down)
223         {
224           L_count++;
225       if ((L_count & 31)== 31)
226       {
227        // 0 is none  // 1 is  Y & B turbo  // 2 is X & A turbo
228         if ((!TurboFireTop) && (!TurboFireBottom))
229         {
230                 // was off
231                 TurboFireTop=1;
232                 TurboFireBottom=0;
233                 if (swapbuttons)
234                 {
235                   FCEUI_DispMessage("Turbo A and Y");
236                 }
237                 else
238                 {
239                   FCEUI_DispMessage("Turbo Y and B");
240                 }
241         }
242         else if (TurboFireTop)
243         {
244                 TurboFireTop=0;
245                 TurboFireBottom=1;
246                 if (swapbuttons)
247                 {
248                   FCEUI_DispMessage("Turbo X and B");
249                 }
250                 else
251                 {
252                   FCEUI_DispMessage("Turbo A and X");
253                 }
254         }
255         else
256         {
257                 TurboFireTop=0;
258                 TurboFireBottom=0;
259                 FCEUI_DispMessage("Turbo Off");
260         }
261
262           }
263         }
264   }
265   else
266   {
267     L_count=0;
268   }
269
270   //unsigned long padTmp=0;
271   // shift the bits in
272   // up
273   //padTmp=(pad & GP2X_UP) ;  // 1 is 2^0,
274   JS |= ((pad & GP2X_UP) << (4-0));  // 0x10 is 2^4
275
276   //padTmp=(pad & GP2X_DOWN);  // 0x10 is 2^4,
277   JS |= ((pad & GP2X_DOWN) << (5-4));  // 0x20 is 2^5
278
279   //padTmp=(pad & GP2X_LEFT);  // 0x4 is 2^2,
280   JS |= ((pad & GP2X_LEFT) << (6-2));  // 0x40 is 2^6
281
282   //padTmp=(pad & GP2X_RIGHT);  // 0x40 is 2^6,
283   JS |= ((pad & GP2X_RIGHT) << (7-6));  // 0x80 is 2^7
284
285
286 #define  A_down (pad & GP2X_A)
287 #define  B_down (pad & GP2X_B)
288 #define  X_down (pad & GP2X_X)
289 #define  Y_down (pad & GP2X_Y)
290
291   // should be 2 cycles held, 1 cycle release
292   turbo_toggle_A=(turbo_toggle_A+1) % 3;
293   turbo_toggle_B=(turbo_toggle_B+1) % 3;
294
295    // 0 is none  // 1 is  Y & B turbo  // 2 is X & A turbo
296   // B or X are both considered A
297   //padTmp=B_down >> 13;  // 2^13,
298
299    if (!(TurboFireTop && (!turbo_toggle_A)))
300    {
301     JS |= ((B_down >> 13) << 0);  // 0x1 is 2^0
302    }
303    // A or Y are both considered B
304    //padTmp=A_down >> 12;  // 2^13,
305    if (!(TurboFireBottom && (!turbo_toggle_B)))
306    {
307     JS |= ((A_down >> 12) << 1);  // 0x2 is 2^1
308    }
309
310   if (swapbuttons)
311   {
312    //padTmp=X_down >> 14;  // 2^13,
313    if (!(TurboFireBottom && (!turbo_toggle_A)))
314    {
315 //    JS |= ((X_down >> 14) << 0);  // 0x1 is 2^0
316     JS |= ((Y_down >> 15) << 0);  // 0x1 is 2^0
317    }
318
319    //padTmp=Y_down >> 15;  // 2^13,
320    if (!(TurboFireTop && (!turbo_toggle_B)))
321    {
322     JS |= ((X_down >> 14) << 1);  // 0x2 is 2^1
323    }
324   }
325   else
326   {
327    //padTmp=X_down >> 14;  // 2^13,
328    if (!(TurboFireBottom && (!turbo_toggle_A)))
329    {
330     JS |= ((X_down >> 14) << 0);  // 0x1 is 2^0
331    }
332
333    //padTmp=Y_down >> 15;  // 2^13,
334    if (!(TurboFireTop && (!turbo_toggle_B)))
335    {
336     JS |= ((Y_down >> 15) << 1);  // 0x2 is 2^1
337    }
338   }
339
340   // select
341   //padTmp=(pad & GP2X_SELECT) >> 9;  // 0x40 is 2^9,
342   JS |= (((pad & GP2X_SELECT) >> 9) << 2);  // 0x4 is 2^2
343
344   // start
345   //padTmp=(pad & GP2X_START) >> 8;  //   2^8,
346   JS |= (((pad & GP2X_START) >> 8) << 3);  // 0x8 is 2^3
347
348   JSreturn = JS;
349   lastpad=pad;
350
351   //JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
352
353
354   //  JSreturn=(JSreturn&0xFF000000)|(JSreturn&0xFF)|((JSreturn&0xFF0000)>>8)|((JSreturn&0xFF00)<<8);
355   // TODO: make these bindable, use new interface
356   if(gametype==GIT_FDS)
357   {
358     NoWaiting&=~1;
359         if ((pad & GP2X_PUSH) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_R)) && (!(lastpad2 & GP2X_PUSH)))
360         {
361       DriverInterface(DES_FDSSELECT,0);
362         }
363         else if ((pad & GP2X_L) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_PUSH)) && (!(pad & GP2X_R))&& (!(lastpad2 & GP2X_L)))
364         {
365       DriverInterface(DES_FDSINSERT,0);
366         }
367         else if ((pad & GP2X_R) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_PUSH)) && (!(lastpad2 & GP2X_R)))
368         {
369       DriverInterface(DES_FDSEJECT,0);
370         }
371   }
372   return;
373
374 no_pad:
375   JSreturn=0;
376   lastpad=pad;
377 }
378
379
380 static void InitOtherInput(void)
381 {
382
383    void *InputDPtr;
384
385    int t;
386    int x;
387    int attrib;
388
389    for(t=0,x=0;x<2;x++)
390    {
391     attrib=0;
392     InputDPtr=0;
393     switch(InputType[x])
394     {
395       //case SI_POWERPAD:InputDPtr=&powerpadbuf[x];break;
396      case SI_GAMEPAD:InputDPtr=((uint8 *)&JSreturn)+(x<<1);break;
397      case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
398      case SI_ZAPPER:InputDPtr=MouseData;
399                                 t|=1;
400                                 attrib=1;
401                                 break;
402     }
403     FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
404    }
405
406    attrib=0;
407    InputDPtr=0;
408    switch(InputTypeFC)
409    {
410     case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break;
411     case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
412     case SIFC_FKB:InputDPtr=fkbkeys;break;
413    }
414
415    FCEUI_SetInputFC(InputTypeFC,InputDPtr,attrib);
416    FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
417
418    if(t && !(inited&16))
419    {
420     InitMouse();
421     inited|=16;
422    }
423 }