1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 2002 Ben Parnell
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.
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.
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
28 #define JOY_RIGHT 0x80
32 extern int swapbuttons;
33 extern int stretch_offset;
34 extern void SetVideoScaling(int pixels,int width,int height);
35 long UpdateGamepadGP2X(void);
41 static void UpdateFKB(void);
47 /* UsrInputType[] is user-specified. InputType[] is current
48 (game loading can override user settings)
50 static int UsrInputType[2]={SI_GAMEPAD,SI_GAMEPAD};
51 static int InputType[2];
53 static int UsrInputTypeFC={SI_NONE};
54 static int InputTypeFC;
56 static uint32 JSreturn;
59 static void DoCheatSeq(void)
61 #if defined(DOS) || defined(SDL)
68 DoConsoleCheatConfig();
71 #if defined(DOS) || defined(SDL)
81 static uint8 keyonce[MK_COUNT];
82 #define KEY(__a) keys[MK(__a)]
83 #define keyonly(__a,__z) {if(KEY(__a)){if(!keyonce[MK(__a)]) {keyonce[MK(__a)]=1;__z}}else{keyonce[MK(__a)]=0;}}
87 static int cidisabled=0;
88 static int KeyboardUpdate(void)
97 if(InputTypeFC==SIFC_FKB)
99 keyonly(SCROLLLOCK,cidisabled^=1;
100 FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis");)
102 SDL_WM_GrabInput(cidisabled?SDL_GRAB_ON:SDL_GRAB_OFF);
104 if(cidisabled) return(1);
107 keyonly(F3,LockConsole();)
108 keyonly(F4,UnlockConsole();)
110 keyonly(F4,ToggleFS();)
116 if(gametype==GIT_FDS)
118 keyonly(S,DriverInterface(DES_FDSSELECT,0);)
119 keyonly(I,DriverInterface(DES_FDSINSERT,0);)
120 keyonly(E,DriverInterface(DES_FDSEJECT,0);)
123 keyonly(F9,FCEUI_SaveSnapshot();)
124 if(gametype!=GIT_NSF)
126 keyonly(F2,DoCheatSeq();)
127 keyonly(F5,FCEUI_SaveState();)
128 keyonly(F7,FCEUI_LoadState();)
132 keyonly(CURSORLEFT,DriverInterface(DES_NSFDEC,0);)
133 keyonly(CURSORRIGHT,DriverInterface(DES_NSFINC,0);)
134 if( KEY(ENTER)) DriverInterface(DES_NSFRES,0);
135 if( KEY(CURSORUP)) DriverInterface(DES_NSFINC,0);
136 if( KEY(CURSORDOWN)) DriverInterface(DES_NSFDEC,0);
139 keyonly(F10,DriverInterface(DES_RESET,0);)
140 keyonly(F11,DriverInterface(DES_POWER,0);)
141 if(KEY(F12) || KEY(ESCAPE)) FCEUI_CloseGame();
143 if(gametype==GIT_VSUNI)
145 keyonly(C,DriverInterface(DES_VSUNICOIN,0);)
146 keyonly(V,DIPS^=1;DriverInterface(DES_VSUNITOGGLEDIPVIEW,0);)
147 if(!(DIPS&1)) goto DIPSless;
148 keyonly(1,DriverInterface(DES_VSUNIDIPSET,(void *)1);)
149 keyonly(2,DriverInterface(DES_VSUNIDIPSET,(void *)2);)
150 keyonly(3,DriverInterface(DES_VSUNIDIPSET,(void *)3);)
151 keyonly(4,DriverInterface(DES_VSUNIDIPSET,(void *)4);)
152 keyonly(5,DriverInterface(DES_VSUNIDIPSET,(void *)5);)
153 keyonly(6,DriverInterface(DES_VSUNIDIPSET,(void *)6);)
154 keyonly(7,DriverInterface(DES_VSUNIDIPSET,(void *)7);)
155 keyonly(8,DriverInterface(DES_VSUNIDIPSET,(void *)8);)
159 keyonly(H,DriverInterface(DES_NTSCSELHUE,0);)
160 keyonly(T,DriverInterface(DES_NTSCSELTINT,0);)
161 if(KEY(KP_MINUS) || KEY(MINUS)) DriverInterface(DES_NTSCDEC,0);
162 if(KEY(KP_PLUS) || KEY(EQUAL)) DriverInterface(DES_NTSCINC,0);
165 keyonly(0,FCEUI_SelectState(0);)
166 keyonly(1,FCEUI_SelectState(1);)
167 keyonly(2,FCEUI_SelectState(2);)
168 keyonly(3,FCEUI_SelectState(3);)
169 keyonly(4,FCEUI_SelectState(4);)
170 keyonly(5,FCEUI_SelectState(5);)
171 keyonly(6,FCEUI_SelectState(6);)
172 keyonly(7,FCEUI_SelectState(7);)
173 keyonly(8,FCEUI_SelectState(8);)
174 keyonly(9,FCEUI_SelectState(9);)
182 static uint32 KeyboardDodo(void)
187 if(gametype!=GIT_NSF)
194 JoySwap=(JoySwap+8)%32;
195 sprintf(tmp,"Joystick %d selected.",(JoySwap>>3)+1);
196 FCEUI_DispMessage(tmp);
199 if(KEY(LEFTALT) || KEY(X)) JS|=JOY_A<<JoySwap;
200 if(KEY(LEFTCONTROL) || KEY(SPACE) || KEY(Z) ) JS |=JOY_B<<JoySwap;
201 if(KEY(ENTER)) JS |= JOY_START<<JoySwap;
202 if(KEY(TAB)) JS |= JOY_SELECT<<JoySwap;
203 if(KEY(CURSORDOWN)) y|= JOY_DOWN;
204 if(KEY(CURSORUP)) y|= JOY_UP;
205 if(KEY(CURSORLEFT)) x|= JOY_LEFT;
206 if(KEY(CURSORRIGHT)) x|= JOY_RIGHT;
207 if(y!=(JOY_DOWN|JOY_UP)) JS|=y<<JoySwap;
208 if(x!=(JOY_LEFT|JOY_RIGHT)) JS|=x<<JoySwap;
217 static int powerpadsc[2][12]={
219 MK(O),MK(P),MK(BRACKET_LEFT),
220 MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
222 MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
225 MK(O),MK(P),MK(BRACKET_LEFT),
226 MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
228 MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
232 static uint32 powerpadbuf[2];
234 static int powerpadsc[2][12];
236 static int powerpadside=0;
239 static uint32 UpdatePPadData(int w)
242 static const char shifttableA[12]={8,9,0,1,11,7,4,2,10,6,5,3};
243 static const char shifttableB[12]={1,0,9,8,2,4,7,11,3,5,6,10};
245 int *ppadtsc=powerpadsc[w];
248 if(powerpadside&(1<<w))
251 if(keys[ppadtsc[x]]) r|=1<<shifttableA[x];
256 if(keys[ppadtsc[x]]) r|=1<<shifttableB[x];
263 static uint32 MouseData[3];
264 static uint8 fkbkeys[0x48];
265 unsigned long lastpad=0;
267 void FCEUD_UpdateInput(void)
272 static uint32 KeyBJS=0;
277 long lastpad2=lastpad;
278 long pad = UpdateGamepadGP2X();
280 // JSreturn=(JSreturn&0xFF000000)|(JSreturn&0xFF)|((JSreturn&0xFF0000)>>8)|((JSreturn&0xFF00)<<8);
281 if(gametype==GIT_FDS)
284 if ((pad & GP2X_PUSH) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_R)) && (!(lastpad2 & GP2X_PUSH)))
286 DriverInterface(DES_FDSSELECT,0);
288 else if ((pad & GP2X_L) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_PUSH)) && (!(pad & GP2X_R))&& (!(lastpad2 & GP2X_L)))
290 DriverInterface(DES_FDSINSERT,0);
292 else if ((pad & GP2X_R) && (!(pad & GP2X_SELECT)) && (!(pad & GP2X_L)) && (!(pad & GP2X_PUSH)) && (!(lastpad2 & GP2X_R)))
294 DriverInterface(DES_FDSEJECT,0);
305 case SI_GAMEPAD:t|=1;break;
306 case SI_ARKANOID:t|=2;break;
307 case SI_ZAPPER:t|=2;break;
308 case SI_POWERPAD:powerpadbuf[x]=UpdatePPadData(x);break;
313 case SIFC_ARKANOID:t|=2;break;
314 case SIFC_SHADOW:t|=2;break;
315 case SIFC_FKB:if(cidisabled) UpdateFKB();break;
321 KeyBJS=KeyboardDodo();
323 JS|=(uint32)GetJSOr();
324 JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
327 GetMouseData(MouseData);
338 extern void ResetNES(void);
339 extern void CleanSurface(void);
341 char soundvolmeter[21];
345 extern int CurrentState;
347 int TurboFireTop=0; // 0 is none // 1 is A & X turbo // 2 is Y & B turbo
348 int TurboFireBottom=0;
349 int turbo_toggle_A=0;
350 int turbo_toggle_B=0;
352 static void setsoundvol(int soundvolume)
354 //FCEUI_SetSoundVolume(soundvol);
356 gp2x_sound_volume(soundvolume, soundvolume);
357 int meterval=soundvolume/5;
358 for (soundvolIndex=0; soundvolIndex < 20; soundvolIndex++)
360 if (soundvolIndex < meterval)
362 soundvolmeter[soundvolIndex]='*';
366 soundvolmeter[soundvolIndex]='_';
370 FCEU_DispMessage("|%s|", soundvolmeter);
373 * GP2x joystick reader
376 INLINE long UpdateGamepadGP2X(void)
380 unsigned long pad=gp2x_joystick_read();
381 #define L_down (pad & GP2X_L)
382 #define R_down (pad & GP2X_R)
383 #define last_L_down (lastpad & GP2X_L)
384 #define last_R_down (lastpad & GP2X_R)
386 if (L_down && R_down && (!(pad & GP2X_PUSH))
387 && (!(last_R_down && last_L_down)))
399 if (pad & GP2X_VOL_UP)
402 if (soundvol >= 100) soundvol=100;
403 //FCEUI_SetSoundVolume(soundvol);
404 setsoundvol(soundvol);
406 if (pad & GP2X_VOL_DOWN)
409 if (soundvol < 0) soundvol=0;
410 //FCEUI_SetSoundVolume(soundvol);
411 setsoundvol(soundvol);
415 // only if it's something else then last time, and not moving around the joystick
416 if (!((pad & GP2X_UP) ||(pad & GP2X_DOWN) || (pad & GP2X_LEFT) || (pad & GP2X_RIGHT)))
418 if (pad & GP2X_SELECT)
420 if ((lastpad & GP2X_SELECT) && (lastpad & GP2X_PUSH))
422 // still pressed down from stretching from last one
427 if (stretch_offset == 32)
436 if (stretch_offset == 32)
438 SetVideoScaling(320, 320, 240);
443 SetVideoScaling(320, 256, 240);
450 else if (L_down && R_down)
457 else if (R_down && (!((lastpad & GP2X_R) && (lastpad & GP2X_PUSH))))
464 else if (L_down && (!((lastpad & GP2X_L) && (lastpad & GP2X_PUSH))))
474 // r is toggle savestate
480 if ((R_count & 31)== 31)
482 CurrentState=(CurrentState+1) % 10;
483 FCEUI_DispMessage("Now Using Save State %d", CurrentState);
498 if ((L_count & 31)== 31)
500 // 0 is none // 1 is Y & B turbo // 2 is X & A turbo
501 if ((!TurboFireTop) && (!TurboFireBottom))
508 FCEUI_DispMessage("Turbo A and Y");
512 FCEUI_DispMessage("Turbo Y and B");
515 else if (TurboFireTop)
521 FCEUI_DispMessage("Turbo X and B");
525 FCEUI_DispMessage("Turbo A and X");
532 FCEUI_DispMessage("Turbo Off");
545 //unsigned long padTmp=0;
548 //padTmp=(pad & GP2X_UP) ; // 1 is 2^0,
549 JS |= ((pad & GP2X_UP) << (4-0)); // 0x10 is 2^4
551 //padTmp=(pad & GP2X_DOWN); // 0x10 is 2^4,
552 JS |= ((pad & GP2X_DOWN) << (5-4)); // 0x20 is 2^5
554 //padTmp=(pad & GP2X_LEFT); // 0x4 is 2^2,
555 JS |= ((pad & GP2X_LEFT) << (6-2)); // 0x40 is 2^6
557 //padTmp=(pad & GP2X_RIGHT); // 0x40 is 2^6,
558 JS |= ((pad & GP2X_RIGHT) << (7-6)); // 0x80 is 2^7
561 #define A_down (pad & GP2X_A)
562 #define B_down (pad & GP2X_B)
563 #define X_down (pad & GP2X_X)
564 #define Y_down (pad & GP2X_Y)
566 // should be 2 cycles held, 1 cycle release
567 turbo_toggle_A=(turbo_toggle_A+1) % 3;
568 turbo_toggle_B=(turbo_toggle_B+1) % 3;
570 // 0 is none // 1 is Y & B turbo // 2 is X & A turbo
571 // B or X are both considered A
572 //padTmp=B_down >> 13; // 2^13,
574 if (!(TurboFireTop && (!turbo_toggle_A)))
576 JS |= ((B_down >> 13) << 0); // 0x1 is 2^0
578 // A or Y are both considered B
579 //padTmp=A_down >> 12; // 2^13,
580 if (!(TurboFireBottom && (!turbo_toggle_B)))
582 JS |= ((A_down >> 12) << 1); // 0x2 is 2^1
587 //padTmp=X_down >> 14; // 2^13,
588 if (!(TurboFireBottom && (!turbo_toggle_A)))
590 // JS |= ((X_down >> 14) << 0); // 0x1 is 2^0
591 JS |= ((Y_down >> 15) << 0); // 0x1 is 2^0
594 //padTmp=Y_down >> 15; // 2^13,
595 if (!(TurboFireTop && (!turbo_toggle_B)))
597 JS |= ((X_down >> 14) << 1); // 0x2 is 2^1
602 //padTmp=X_down >> 14; // 2^13,
603 if (!(TurboFireBottom && (!turbo_toggle_A)))
605 JS |= ((X_down >> 14) << 0); // 0x1 is 2^0
608 //padTmp=Y_down >> 15; // 2^13,
609 if (!(TurboFireTop && (!turbo_toggle_B)))
611 JS |= ((Y_down >> 15) << 1); // 0x2 is 2^1
616 //padTmp=(pad & GP2X_SELECT) >> 9; // 0x40 is 2^9,
617 JS |= (((pad & GP2X_SELECT) >> 9) << 2); // 0x4 is 2^2
620 //padTmp=(pad & GP2X_START) >> 8; // 2^8,
621 JS |= (((pad & GP2X_START) >> 8) << 3); // 0x8 is 2^3
628 //JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
645 static void InitOtherInput(void)
660 //case SI_POWERPAD:InputDPtr=&powerpadbuf[x];break;
661 case SI_GAMEPAD:InputDPtr=((uint8 *)&JSreturn)+(x<<1);break;
662 case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
663 case SI_ZAPPER:InputDPtr=MouseData;
668 FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
675 case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break;
676 case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
677 case SIFC_FKB:InputDPtr=fkbkeys;break;
680 FCEUI_SetInputFC(InputTypeFC,InputDPtr,attrib);
681 FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
683 if(t && !(inited&16))
693 MK(F1),MK(F2),MK(F3),MK(F4),MK(F5),MK(F6),MK(F7),MK(F8),
694 MK(1),MK(2),MK(3),MK(4),MK(5),MK(6),MK(7),MK(8),MK(9),MK(0),
695 MK(MINUS),MK(EQUAL),MK(BACKSLASH),MK(BACKSPACE),
696 MK(ESCAPE),MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I),MK(O),
697 MK(P),MK(GRAVE),MK(BRACKET_LEFT),MK(ENTER),
698 MK(LEFTCONTROL),MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),
699 MK(L),MK(SEMICOLON),MK(APOSTROPHE),MK(BRACKET_RIGHT),MK(INSERT),
700 MK(LEFTSHIFT),MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M),MK(COMMA),
701 MK(PERIOD),MK(SLASH),MK(RIGHTALT),MK(RIGHTSHIFT),MK(LEFTALT),MK(SPACE),
702 MK(DELETE),MK(END),MK(PAGEDOWN),
703 MK(CURSORUP),MK(CURSORLEFT),MK(CURSORRIGHT),MK(CURSORDOWN)
707 static void UpdateFKB(void)