b946c5bb2df7a9a9a7797364f1e648315146175c
[fceu.git] / drivers / cli / 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 static void UpdateFKB(void);
31
32 /* UsrInputType[] is user-specified.  InputType[] is current
33         (game loading can override user settings) 
34 */
35 static int UsrInputType[2]={SI_GAMEPAD,SI_GAMEPAD};
36 static int InputType[2];
37
38 static int UsrInputTypeFC={SI_NONE};
39 static int InputTypeFC;
40
41 static uint32 JSreturn;
42 int NoWaiting=0;
43
44 static void DoCheatSeq(void)
45 {
46  #if defined(DOS) || defined(SDL)
47  if(inited&1)
48   SilenceSound(1);
49  #endif
50  KillKeyboard();
51  KillVideo();
52
53  DoConsoleCheatConfig();
54  InitVideo();
55  InitKeyboard();
56  #if defined(DOS) || defined(SDL)
57  if(inited&1)
58   SilenceSound(0);
59  #endif
60 }
61
62 #include "keyscan.h"
63 static char *keys;
64 static int DIPS=0;
65 static uint8 keyonce[MK_COUNT];
66 #define KEY(__a) keys[MK(__a)]
67 #define keyonly(__a,__z) {if(KEY(__a)){if(!keyonce[MK(__a)]) {keyonce[MK(__a)]=1;__z}}else{keyonce[MK(__a)]=0;}}
68 static int JoySwap=0;
69 static int cidisabled=0;
70 static int KeyboardUpdate(void)
71 {
72
73  if(!UpdateKeyboard())
74    if(keys)
75     return 0;
76
77   keys=GetKeyboard(); 
78
79   if(InputTypeFC==SIFC_FKB)
80   {
81    keyonly(SCROLLLOCK,cidisabled^=1;
82     FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis");)
83    #ifdef SDL
84    SDL_WM_GrabInput(cidisabled?SDL_GRAB_ON:SDL_GRAB_OFF);
85    #endif
86    if(cidisabled) return(1);
87   }
88   #ifdef SVGALIB
89   keyonly(F3,LockConsole();)  
90   keyonly(F4,UnlockConsole();)
91   #elif SDL
92   keyonly(F4,ToggleFS();)
93   #endif
94   NoWaiting&=~1;
95   if(KEY(GRAVE))
96    NoWaiting|=1;
97
98   if(gametype==GIT_FDS)
99   {
100    keyonly(S,DriverInterface(DES_FDSSELECT,0);)
101    keyonly(I,DriverInterface(DES_FDSINSERT,0);)
102    keyonly(E,DriverInterface(DES_FDSEJECT,0);)
103   }
104
105  keyonly(F9,FCEUI_SaveSnapshot();)
106  if(gametype!=GIT_NSF)
107  {
108   keyonly(F2,DoCheatSeq();)
109   keyonly(F5,FCEUI_SaveState();)
110   keyonly(F7,FCEUI_LoadState();)
111  }
112  else
113  {
114   keyonly(CURSORLEFT,DriverInterface(DES_NSFDEC,0);)
115   keyonly(CURSORRIGHT,DriverInterface(DES_NSFINC,0);)
116   if( KEY(ENTER)) DriverInterface(DES_NSFRES,0);
117   if( KEY(CURSORUP)) DriverInterface(DES_NSFINC,0);
118   if( KEY(CURSORDOWN)) DriverInterface(DES_NSFDEC,0);
119  }
120
121  keyonly(F10,DriverInterface(DES_RESET,0);)
122  keyonly(F11,DriverInterface(DES_POWER,0);)
123  if(KEY(F12) || KEY(ESCAPE)) FCEUI_CloseGame();
124
125  if(gametype==GIT_VSUNI)
126  {
127    keyonly(C,DriverInterface(DES_VSUNICOIN,0);)
128    keyonly(V,DIPS^=1;DriverInterface(DES_VSUNITOGGLEDIPVIEW,0);)
129    if(!(DIPS&1)) goto DIPSless;
130    keyonly(1,DriverInterface(DES_VSUNIDIPSET,(void *)1);)
131    keyonly(2,DriverInterface(DES_VSUNIDIPSET,(void *)2);)
132    keyonly(3,DriverInterface(DES_VSUNIDIPSET,(void *)3);)
133    keyonly(4,DriverInterface(DES_VSUNIDIPSET,(void *)4);)
134    keyonly(5,DriverInterface(DES_VSUNIDIPSET,(void *)5);)
135    keyonly(6,DriverInterface(DES_VSUNIDIPSET,(void *)6);)
136    keyonly(7,DriverInterface(DES_VSUNIDIPSET,(void *)7);)
137    keyonly(8,DriverInterface(DES_VSUNIDIPSET,(void *)8);)
138  }
139  else
140  {
141   keyonly(H,DriverInterface(DES_NTSCSELHUE,0);)
142   keyonly(T,DriverInterface(DES_NTSCSELTINT,0);)
143   if(KEY(KP_MINUS) || KEY(MINUS)) DriverInterface(DES_NTSCDEC,0);
144   if(KEY(KP_PLUS) || KEY(EQUAL)) DriverInterface(DES_NTSCINC,0);
145
146   DIPSless:
147   keyonly(0,FCEUI_SelectState(0);)
148   keyonly(1,FCEUI_SelectState(1);)
149   keyonly(2,FCEUI_SelectState(2);)
150   keyonly(3,FCEUI_SelectState(3);)
151   keyonly(4,FCEUI_SelectState(4);)
152   keyonly(5,FCEUI_SelectState(5);)
153   keyonly(6,FCEUI_SelectState(6);)
154   keyonly(7,FCEUI_SelectState(7);)
155   keyonly(8,FCEUI_SelectState(8);)
156   keyonly(9,FCEUI_SelectState(9);)
157  }
158  return 1;
159 }
160
161 static uint32 KeyboardDodo(void)
162 {
163  uint32 JS=0;
164
165  if(gametype!=GIT_NSF)
166  {
167   int x,y;
168   x=y=0;
169   keyonly(CAPSLOCK,
170                    {
171                     char tmp[64];
172                     JoySwap=(JoySwap+8)%32;
173                     sprintf(tmp,"Joystick %d selected.",(JoySwap>>3)+1);
174                     FCEUI_DispMessage(tmp);
175                    })
176
177   if(KEY(LEFTALT) || KEY(X))        JS|=JOY_A<<JoySwap;
178   if(KEY(LEFTCONTROL) || KEY(SPACE) || KEY(Z) ) JS |=JOY_B<<JoySwap;
179   if(KEY(ENTER))       JS |= JOY_START<<JoySwap;
180   if(KEY(TAB))         JS |= JOY_SELECT<<JoySwap;
181   if(KEY(CURSORDOWN))  y|= JOY_DOWN;
182   if(KEY(CURSORUP))    y|= JOY_UP;
183   if(KEY(CURSORLEFT))  x|= JOY_LEFT;
184   if(KEY(CURSORRIGHT)) x|= JOY_RIGHT;
185   if(y!=(JOY_DOWN|JOY_UP)) JS|=y<<JoySwap;
186   if(x!=(JOY_LEFT|JOY_RIGHT)) JS|=x<<JoySwap;
187  }
188  return JS;
189 }
190
191 static int powerpadsc[2][12]={
192                               {
193                                MK(O),MK(P),MK(BRACKET_LEFT),
194                                MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
195                                 MK(APOSTROPHE),
196                                MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
197                               },
198                               {
199                                MK(O),MK(P),MK(BRACKET_LEFT),
200                                MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
201                                 MK(APOSTROPHE),
202                                MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
203                               }
204                              };
205
206 static uint32 powerpadbuf[2];
207 static int powerpadside=0;
208
209 static uint32 UpdatePPadData(int w)
210 {
211  static const char shifttableA[12]={8,9,0,1,11,7,4,2,10,6,5,3};
212  static const char shifttableB[12]={1,0,9,8,2,4,7,11,3,5,6,10};
213  uint32 r=0;
214  int *ppadtsc=powerpadsc[w];
215  int x;
216
217  if(powerpadside&(1<<w))
218  {
219   for(x=0;x<12;x++)
220    if(keys[ppadtsc[x]]) r|=1<<shifttableA[x];
221  }
222  else
223  {
224   for(x=0;x<12;x++)
225    if(keys[ppadtsc[x]]) r|=1<<shifttableB[x];
226  }
227  return r;
228 }
229
230 static uint32 MouseData[3];
231 static uint8 fkbkeys[0x48];
232
233 void FCEUD_UpdateInput(void)
234 {
235   int x;
236   int t=0;
237   static uint32 KeyBJS=0;
238   uint32 JS;
239   int b;
240
241   b=KeyboardUpdate();
242
243   for(x=0;x<2;x++)
244    switch(InputType[x])
245    {
246     case SI_GAMEPAD:t|=1;break;
247     case SI_ARKANOID:t|=2;break;
248     case SI_ZAPPER:t|=2;break;
249     case SI_POWERPAD:powerpadbuf[x]=UpdatePPadData(x);break;
250    }
251
252   switch(InputTypeFC)
253   {
254    case SIFC_ARKANOID:t|=2;break;
255    case SIFC_SHADOW:t|=2;break;
256    case SIFC_FKB:if(cidisabled) UpdateFKB();break;
257   }
258
259   if(t&1)
260   {
261    if(b)
262     KeyBJS=KeyboardDodo();
263    JS=KeyBJS;
264    JS|=(uint32)GetJSOr();
265    JSreturn=(JS&0xFF000000)|(JS&0xFF)|((JS&0xFF0000)>>8)|((JS&0xFF00)<<8);
266   }
267   if(t&2)
268    GetMouseData(MouseData);
269 }
270
271 static void InitOtherInput(void)
272 {
273    void *InputDPtr;
274
275    int t;
276    int x;
277    int attrib;
278
279    for(t=0,x=0;x<2;x++)
280    {
281     attrib=0;
282     InputDPtr=0;
283     switch(InputType[x])
284     {
285      case SI_POWERPAD:InputDPtr=&powerpadbuf[x];break;
286      case SI_GAMEPAD:InputDPtr=((uint8 *)&JSreturn)+(x<<1);break;     
287      case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
288      case SI_ZAPPER:InputDPtr=MouseData;
289                                 t|=1;
290                                 attrib=1;
291                                 break;
292     }
293     FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
294    }
295
296    attrib=0;
297    InputDPtr=0;
298    switch(InputTypeFC)
299    {
300     case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break;
301     case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
302     case SIFC_FKB:InputDPtr=fkbkeys;break;
303    }
304
305    FCEUI_SetInputFC(InputTypeFC,InputDPtr,attrib);
306    FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
307
308    if(t && !(inited&16)) 
309    {
310     InitMouse();
311     inited|=16;
312    }
313 }
314
315 int fkbmap[0x48]=
316 {
317  MK(F1),MK(F2),MK(F3),MK(F4),MK(F5),MK(F6),MK(F7),MK(F8),
318  MK(1),MK(2),MK(3),MK(4),MK(5),MK(6),MK(7),MK(8),MK(9),MK(0),
319         MK(MINUS),MK(EQUAL),MK(BACKSLASH),MK(BACKSPACE),
320  MK(ESCAPE),MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I),MK(O),
321         MK(P),MK(GRAVE),MK(BRACKET_LEFT),MK(ENTER),
322  MK(LEFTCONTROL),MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),
323         MK(L),MK(SEMICOLON),MK(APOSTROPHE),MK(BRACKET_RIGHT),MK(INSERT),
324  MK(LEFTSHIFT),MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M),MK(COMMA),
325         MK(PERIOD),MK(SLASH),MK(RIGHTALT),MK(RIGHTSHIFT),MK(LEFTALT),MK(SPACE),
326  MK(DELETE),MK(END),MK(PAGEDOWN),
327  MK(CURSORUP),MK(CURSORLEFT),MK(CURSORRIGHT),MK(CURSORDOWN)
328 };
329
330 static void UpdateFKB(void)
331 {
332  int x;
333
334  for(x=0;x<0x48;x++)
335  {
336   fkbkeys[x]=0;
337   if(keys[fkbmap[x]])
338    fkbkeys[x]=1;
339  }
340 }