move 1
[fceu.git] / drivers / pc / input.c
CommitLineData
c62d2810 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
5232c20c 30
31#include "minimal.h"
32extern int swapbuttons;
33extern int stretch_offset;
15300263 34extern int FSkip_setting;
5232c20c 35
15300263 36extern void SetVideoScaling(int pixels,int width,int height);
37INLINE long UpdateGamepadGP2X(void);
5232c20c 38
39
40
c62d2810 41/* UsrInputType[] is user-specified. InputType[] is current
15300263 42 (game loading can override user settings)
c62d2810 43*/
44static int UsrInputType[2]={SI_GAMEPAD,SI_GAMEPAD};
45static int InputType[2];
46
47static int UsrInputTypeFC={SI_NONE};
48static int InputTypeFC;
49
50static uint32 JSreturn;
51int NoWaiting=0;
52
5232c20c 53static int powerpadsc[2][12];
c62d2810 54static int powerpadside=0;
55
5232c20c 56
c62d2810 57static uint32 MouseData[3];
58static uint8 fkbkeys[0x48];
5232c20c 59unsigned long lastpad=0;
c62d2810 60
61void FCEUD_UpdateInput(void)
62{
c62d2810 63 int t=0;
5232c20c 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)
15300263 69 {
5232c20c 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 }
c62d2810 84
5232c20c 85}
86
87
5232c20c 88//#ifdef GP2X
89
90extern void ResetNES(void);
91extern void CleanSurface(void);
92
93char soundvolmeter[21];
94int soundvolIndex=0;
95int L_count=0;
96int R_count=0;
97extern int CurrentState;
98int TurboFireOff=1;
99int TurboFireTop=0; // 0 is none // 1 is A & X turbo // 2 is Y & B turbo
100int TurboFireBottom=0;
101int turbo_toggle_A=0;
102int turbo_toggle_B=0;
103
104static 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
15300263 117 {
5232c20c 118 soundvolmeter[soundvolIndex]='_';
119 }
120 }
121 soundvolmeter[20]=0;
15300263 122 FCEU_DispMessage("|%s|", soundvolmeter);
c62d2810 123}
5232c20c 124/**
125 * GP2x joystick reader
126 *
15300263 127 */
5232c20c 128INLINE long UpdateGamepadGP2X(void)
129{
130 uint32 JS=0;
131
132 unsigned long pad=gp2x_joystick_read();
15300263 133#define down(b) (pad & GP2X_##b)
134#define last_down(b) (lastpad & GP2X_##b)
5232c20c 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)
15300263 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))
5232c20c 143 {
144 ResetNES();
15300263 145 puts("Reset");
146 goto no_pad;
5232c20c 147 }
148
15300263 149 if (down(VOL_UP) && !down(VOL_DOWN))
5232c20c 150 {
151 soundvol+=1;
152 if (soundvol >= 100) soundvol=100;
153 //FCEUI_SetSoundVolume(soundvol);
154 setsoundvol(soundvol);
155 }
15300263 156 else if (down(VOL_DOWN) && !down(VOL_UP))
5232c20c 157 {
158 soundvol-=1;
159 if (soundvol < 0) soundvol=0;
160 //FCEUI_SetSoundVolume(soundvol);
161 setsoundvol(soundvol);
162 }
15300263 163
164 if (shift)
165 {
5232c20c 166 // only if it's something else then last time, and not moving around the joystick
15300263 167 if (!(pad & (GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT)))
5232c20c 168 {
15300263 169 if (down(SELECT))
5232c20c 170 {
15300263 171 if (last_down(SELECT) && last_shift)
5232c20c 172 {
173 // still pressed down from stretching from last one
15300263 174 goto no_pad;
5232c20c 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)
15300263 186 {
5232c20c 187 SetVideoScaling(320, 320, 240);
188 CleanSurface();
189 }
190 else
191 {
192 SetVideoScaling(320, 256, 240);
193 }
194
15300263 195 goto no_pad;
5232c20c 196 }
197 else if (L_down && R_down)
198 {
199 FCEUI_CloseGame();
15300263 200 puts("Quit");
201 goto no_pad;
5232c20c 202 }
15300263 203 else if (R_down && !(last_R_down && last_shift))
5232c20c 204 {
205 FCEUI_LoadState();
15300263 206 goto no_pad;
5232c20c 207 }
15300263 208 else if (L_down && !(last_L_down && last_shift))
5232c20c 209 {
210 FCEUI_SaveState();
15300263 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;
5232c20c 230 }
231 }
232 }
15300263 233
5232c20c 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 }
15300263 251
5232c20c 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;
15300263 265 TurboFireBottom=0;
5232c20c 266 if (swapbuttons)
267 {
15300263 268 FCEUI_DispMessage("Turbo A and Y");
5232c20c 269 }
270 else
271 {
15300263 272 FCEUI_DispMessage("Turbo Y and B");
5232c20c 273 }
274 }
275 else if (TurboFireTop)
276 {
277 TurboFireTop=0;
15300263 278 TurboFireBottom=1;
5232c20c 279 if (swapbuttons)
280 {
15300263 281 FCEUI_DispMessage("Turbo X and B");
5232c20c 282 }
283 else
284 {
15300263 285 FCEUI_DispMessage("Turbo A and X");
5232c20c 286 }
287 }
288 else
289 {
290 TurboFireTop=0;
15300263 291 TurboFireBottom=0;
292 FCEUI_DispMessage("Turbo Off");
5232c20c 293 }
15300263 294
5232c20c 295 }
296 }
297 }
298 else
299 {
300 L_count=0;
301 }
15300263 302
5232c20c 303 //unsigned long padTmp=0;
304 // shift the bits in
305 // up
15300263 306 //padTmp=(pad & GP2X_UP) ; // 1 is 2^0,
5232c20c 307 JS |= ((pad & GP2X_UP) << (4-0)); // 0x10 is 2^4
308
15300263 309 //padTmp=(pad & GP2X_DOWN); // 0x10 is 2^4,
5232c20c 310 JS |= ((pad & GP2X_DOWN) << (5-4)); // 0x20 is 2^5
311
15300263 312 //padTmp=(pad & GP2X_LEFT); // 0x4 is 2^2,
5232c20c 313 JS |= ((pad & GP2X_LEFT) << (6-2)); // 0x40 is 2^6
314
15300263 315 //padTmp=(pad & GP2X_RIGHT); // 0x40 is 2^6,
5232c20c 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;
15300263 327
5232c20c 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,
15300263 331
5232c20c 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
15300263 337 //padTmp=A_down >> 12; // 2^13,
5232c20c 338 if (!(TurboFireBottom && (!turbo_toggle_B)))
339 {
340 JS |= ((A_down >> 12) << 1); // 0x2 is 2^1
341 }
15300263 342
5232c20c 343 if (swapbuttons)
344 {
15300263 345 //padTmp=X_down >> 14; // 2^13,
5232c20c 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
15300263 352 //padTmp=Y_down >> 15; // 2^13,
5232c20c 353 if (!(TurboFireTop && (!turbo_toggle_B)))
354 {
355 JS |= ((X_down >> 14) << 1); // 0x2 is 2^1
356 }
357 }
358 else
15300263 359 {
360 //padTmp=X_down >> 14; // 2^13,
5232c20c 361 if (!(TurboFireBottom && (!turbo_toggle_A)))
362 {
363 JS |= ((X_down >> 14) << 0); // 0x1 is 2^0
364 }
365
15300263 366 //padTmp=Y_down >> 15; // 2^13,
5232c20c 367 if (!(TurboFireTop && (!turbo_toggle_B)))
368 {
369 JS |= ((Y_down >> 15) << 1); // 0x2 is 2^1
370 }
371 }
372
373 // select
15300263 374 //padTmp=(pad & GP2X_SELECT) >> 9; // 0x40 is 2^9,
5232c20c 375 JS |= (((pad & GP2X_SELECT) >> 9) << 2); // 0x4 is 2^2
376
377 // start
15300263 378 //padTmp=(pad & GP2X_START) >> 8; // 2^8,
5232c20c 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);
15300263 387no_pad:
388 JSreturn=0;
389 lastpad=pad;
390 return 0;
5232c20c 391}
392//#endif
393
394
c62d2810 395static void InitOtherInput(void)
396{
5232c20c 397
c62d2810 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 {
5232c20c 410 //case SI_POWERPAD:InputDPtr=&powerpadbuf[x];break;
15300263 411 case SI_GAMEPAD:InputDPtr=((uint8 *)&JSreturn)+(x<<1);break;
c62d2810 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
15300263 433 if(t && !(inited&16))
c62d2810 434 {
435 InitMouse();
436 inited|=16;
437 }
c62d2810 438}