cleanups, savestates, input (combos), menu
[fceu.git] / drivers / gp2x / input.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17
18 #include "../../state.h"
19 #include "../../general.h"
20
21 /* UsrInputType[] is user-specified.  InputType[] is current
22        (game loading can override user settings)
23 */
24 static int UsrInputType[2]={SI_GAMEPAD,SI_GAMEPAD};
25 static int UsrInputTypeFC={SI_NONE};
26
27 static int InputType[2];
28 static int InputTypeFC;
29
30 static uint32 JSreturn;
31
32 static int powerpadsc[2][12];
33 static int powerpadside=0;
34
35 static uint32 MouseData[3];
36 static uint8 fkbkeys[0x48];
37
38 static uint32 combo_acts = 0, combo_keys = 0;
39 static uint32 prev_emu_acts = 0;
40
41
42 static void setsoundvol(int soundvolume)
43 {
44         int soundvolIndex;
45         static char soundvolmeter[24];
46
47         // draw on screen :D
48         gp2x_sound_volume(soundvolume, soundvolume);
49         int meterval=soundvolume/5;
50         for (soundvolIndex = 0; soundvolIndex < 20; soundvolIndex++)
51         {
52                 if (soundvolIndex < meterval)
53                 {
54                         soundvolmeter[soundvolIndex]='*';
55                 }
56                 else
57                 {
58                         soundvolmeter[soundvolIndex]='_';
59                 }
60         }
61         soundvolmeter[20]=0;
62         FCEU_DispMessage("|%s|", soundvolmeter);
63 }
64
65
66 static void do_emu_acts(uint32 acts)
67 {
68         uint32 actsc = acts;
69         acts &= acts ^ prev_emu_acts;
70         prev_emu_acts = actsc;
71
72         if (acts & (3 << 30))
73         {
74                 if (acts & (1 << 30))
75                 {
76                         FCEUI_LoadState();
77                 }
78                 else
79                 {
80                         FCEUI_SaveState();
81                 }
82         }
83         else if (acts & (1 << 29))
84         {
85                 FILE *st;
86                 char *fname;
87
88                 CurrentState++;
89                 if (CurrentState > 9) CurrentState = 0;
90
91                 fname = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0);
92                 st=fopen(fname,"rb");
93                 free(fname);
94                 FCEU_DispMessage("[%s] State Slot %i", st ? "USED" : "FREE", CurrentState);
95                 if (st) fclose(st);
96         }
97 }
98
99
100 void FCEUD_UpdateInput(void)
101 {
102         static int volpushed_frames = 0;
103         static int turbo_rate_cnt_a = 0, turbo_rate_cnt_b = 0;
104         unsigned long keys = gp2x_joystick_read(0);
105         uint32 all_acts = 0;
106         int i;
107
108         #define down(b) (keys & GP2X_##b)
109         if ((down(VOL_DOWN) && down(VOL_UP)) || (keys & (GP2X_L|GP2X_L|GP2X_START)) == (GP2X_L|GP2X_L|GP2X_START))
110         {
111                 Exit = 1;
112                 return;
113         }
114         else if (down(VOL_UP))
115         {
116                 /* wait for at least 10 updates, because user may be just trying to enter menu */
117                 if (volpushed_frames++ > 10) {
118                         soundvol++;
119                         if (soundvol > 100) soundvol=100;
120                         //FCEUI_SetSoundVolume(soundvol);
121                         setsoundvol(soundvol);
122                 }
123         }
124         else if (down(VOL_DOWN))
125         {
126                 if (volpushed_frames++ > 10) {
127                         soundvol-=1;
128                         if (soundvol < 0) soundvol=0;
129                         //FCEUI_SetSoundVolume(soundvol);
130                         setsoundvol(soundvol);
131                 }
132         }
133         else
134         {
135                 volpushed_frames = 0;
136         }
137
138
139         JSreturn = 0; // RLDU SEBA
140
141         for (i = 0; i < 32; i++)
142         {
143                 if (keys & (1 << i))
144                 {
145                         uint32 acts, u = 32;
146                         acts = Settings.KeyBinds[i];
147                         if (!acts) continue;
148                         if ((1 << i) & combo_keys)
149                         {
150                                 // combo key detected, try to find if other is pressed
151                                 for (u = i+1; u < 32; u++)
152                                 {
153                                         if ((keys & (1 << u)) && (Settings.KeyBinds[u] & acts))
154                                         {
155                                                 keys &= ~(1 << u);
156                                                 break;
157                                         }
158                                 }
159                         }
160                         if (u != 32) acts &=  combo_acts; // other combo key pressed
161                         else         acts &= ~combo_acts;
162                         all_acts |= acts;
163                 }
164         }
165
166         JSreturn |= all_acts & 0xff;
167         if (all_acts & 0x100) {         // A turbo
168                 turbo_rate_cnt_a += Settings.turbo_rate_add;
169                 JSreturn |= (turbo_rate_cnt_a >> 24) & 1;
170         }
171         if (all_acts & 0x200) {         // B turbo
172                 turbo_rate_cnt_b += Settings.turbo_rate_add;
173                 JSreturn |= (turbo_rate_cnt_b >> 23) & 2;
174         }
175
176         do_emu_acts(all_acts);
177
178
179         //JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
180
181   //  JSreturn=(JSreturn&0xFF000000)|(JSreturn&0xFF)|((JSreturn&0xFF0000)>>8)|((JSreturn&0xFF00)<<8);
182   // TODO: make these bindable, use new interface
183   /*
184   if(gametype==GIT_FDS)
185   {
186         if ((pad & GP2X_PUSH) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_R)) && (!(lastpad2 & GP2X_PUSH)))
187         {
188       DriverInterface(DES_FDSSELECT,0);
189         }
190         else if ((pad & GP2X_L) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_PUSH)) && (!(pad & GP2X_R))&& (!(lastpad2 & GP2X_L)))
191         {
192       DriverInterface(DES_FDSINSERT,0);
193         }
194         else if ((pad & GP2X_R) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_PUSH)) && (!(lastpad2 & GP2X_R)))
195         {
196       DriverInterface(DES_FDSEJECT,0);
197         }
198   }
199   return;
200   */
201 }
202
203
204 static void InitOtherInput(void)
205 {
206
207    void *InputDPtr;
208
209    int t;
210    int x;
211    int attrib;
212
213    for(t=0,x=0;x<2;x++)
214    {
215     attrib=0;
216     InputDPtr=0;
217     switch(InputType[x])
218     {
219       //case SI_POWERPAD:InputDPtr=&powerpadbuf[x];break;
220      case SI_GAMEPAD:InputDPtr=((uint8 *)&JSreturn)+(x<<1);break;
221      case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
222      case SI_ZAPPER:InputDPtr=MouseData;
223                                 t|=1;
224                                 attrib=1;
225                                 break;
226     }
227     FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
228    }
229
230    attrib=0;
231    InputDPtr=0;
232    switch(InputTypeFC)
233    {
234     case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break;
235     case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
236     case SIFC_FKB:InputDPtr=fkbkeys;break;
237    }
238
239    FCEUI_SetInputFC(InputTypeFC,InputDPtr,attrib);
240    FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
241
242    inited|=16;
243 }
244
245
246 static void PrepareOtherInput(void)
247 {
248         uint32 act, key, seen_acts;
249
250         combo_acts = combo_keys = prev_emu_acts = seen_acts = 0;
251
252         // find combo_acts
253         for (act = 1; act; act <<= 1)
254         {
255                 for (key = 1; key < 32; key++)
256                 {
257                         if (Settings.KeyBinds[key] & act)
258                         {
259                                 if (seen_acts & act) combo_acts |= act;
260                                 else seen_acts |= act;
261                         }
262                 }
263         }
264
265         // find combo_keys
266         for (act = 1; act; act <<= 1)
267         {
268                 for (key = 0; key < 32; key++)
269                 {
270                         if (Settings.KeyBinds[key] & combo_acts)
271                         {
272                                 combo_keys |= 1 << key;
273                         }
274                 }
275         }
276
277         printf("generated combo_acts: %08x, combo_keys: %08x\n", combo_acts, combo_keys);
278 }
279