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