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