gpfce patch
[fceu.git] / drivers / win / keyboard.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#include "common.h"
22#include <dinput.h>
23
24
25#include "input.h"
26#include "keyboard.h"
27
28#include "keyscan.h"
29
30
31HRESULT ddrval;
32
33static LPDIRECTINPUTDEVICE7 lpdid=0;
34static int porttemp;
35
36
37int keyBMap[4][8]={
38 {SCAN_LEFTALT,SCAN_LEFTCONTROL,SCAN_TAB,SCAN_ENTER,SCAN_BL_CURSORUP,SCAN_BL_CURSORDOWN,SCAN_BL_CURSORLEFT,SCAN_BL_CURSORRIGHT},
39 {SCAN_LEFTALT,SCAN_LEFTCONTROL,SCAN_TAB,SCAN_ENTER,SCAN_BL_CURSORUP,SCAN_BL_CURSORDOWN,SCAN_BL_CURSORLEFT,SCAN_BL_CURSORRIGHT},
40 {SCAN_LEFTALT,SCAN_LEFTCONTROL,SCAN_TAB,SCAN_ENTER,SCAN_BL_CURSORUP,SCAN_BL_CURSORDOWN,SCAN_BL_CURSORLEFT,SCAN_BL_CURSORRIGHT},
41 {SCAN_LEFTALT,SCAN_LEFTCONTROL,SCAN_TAB,SCAN_ENTER,SCAN_BL_CURSORUP,SCAN_BL_CURSORDOWN,SCAN_BL_CURSORLEFT,SCAN_BL_CURSORRIGHT}
42 };
43int keybEnable=1;
44
45int powerpadside=0;
46int powerpadsc[2][12]={
47 {
48 SCAN_O,SCAN_P,SCAN_BRACKET_LEFT,
49 SCAN_BRACKET_RIGHT,SCAN_K,SCAN_L,SCAN_SEMICOLON,SCAN_APOSTROPHE,
50 SCAN_M,SCAN_COMMA,SCAN_PERIOD,SCAN_SLASH
51 },
52 {
53 SCAN_O,SCAN_P,SCAN_BRACKET_LEFT,
54 SCAN_BRACKET_RIGHT,SCAN_K,SCAN_L,SCAN_SEMICOLON,SCAN_APOSTROPHE,
55 SCAN_M,SCAN_COMMA,SCAN_PERIOD,SCAN_SLASH
56 }
57 };
58
59
60
61
62void KeyboardClose(void)
63{
64 if(lpdid) IDirectInputDevice7_Unacquire(lpdid);
65 lpdid=0;
66}
67
68static char keys[256];
69static void KeyboardUpdateState(void)
70{
71 ddrval=IDirectInputDevice7_GetDeviceState(lpdid,256,keys);
72 switch(ddrval)
73 {
74 case DIERR_INPUTLOST:
75 case DIERR_NOTACQUIRED:
76 IDirectInputDevice7_Acquire(lpdid);
77 break;
78 }
79}
80
81int KeyboardInitialize(void)
82{
83
84 if(lpdid)
85 return(1);
86
87 ddrval=IDirectInput7_CreateDeviceEx(lpDI, &GUID_SysKeyboard,&IID_IDirectInputDevice7, (LPVOID *)&lpdid,0);
88 if(ddrval != DI_OK)
89 {
90 FCEUD_PrintError("DirectInput: Error creating keyboard device.");
91 return 0;
92 }
93
94 ddrval=IDirectInputDevice7_SetCooperativeLevel(lpdid, hAppWnd,DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);
95 if(ddrval != DI_OK)
96 {
97 FCEUD_PrintError("DirectInput: Error setting keyboard cooperative level.");
98 return 0;
99 }
100
101 ddrval=IDirectInputDevice7_SetDataFormat(lpdid,&c_dfDIKeyboard);
102 if(ddrval != DI_OK)
103 {
104 FCEUD_PrintError("DirectInput: Error setting keyboard data format.");
105 return 0;
106 }
107
108 ddrval=IDirectInputDevice7_Acquire(lpdid);
109 if(ddrval != DI_OK)
110 {
111 FCEUD_PrintError("DirectInput: Error acquiring keyboard.");
112 return 0;
113 }
114 return 1;
115}
116
117static int DIPS=0;
118static uint8 keyonce[256];
119#define KEY(__a) keys[SCAN_##__a]
120#define keyonly(__a,__z) {if(KEY(__a)){if(!keyonce[SCAN_##__a]) {keyonce[SCAN_##__a]=1;__z}} else{keyonce[SCAN_##__a]=0;}}
121int cidisabled=0;
122
123void KeyboardUpdate(void)
124{
125 KeyboardUpdateState();
126
127 if(InputTypeFC==SIFC_FKB && cidisabled)
128 return;
129
130 NoWaiting&=~1;
131 if(KEY(GRAVE))
132 NoWaiting|=1;
133
134 if(GI)
135 {
136 if(GI->type==GIT_FDS)
137 {
138 keyonly(S,DriverInterface(DES_FDSSELECT,0);)
139 keyonly(I,DriverInterface(DES_FDSINSERT,0);)
140 keyonly(E,DriverInterface(DES_FDSEJECT,0);)
141 }
142
143 if(GI->type!=GIT_NSF)
144 {
145 keyonly(F5,FCEUI_SaveState();)
146 keyonly(F7,FCEUI_LoadState();)
147 }
148 keyonly(F9,FCEUI_SaveSnapshot();)
149
150 if(GI->type==GIT_VSUNI)
151 {
152 keyonly(C,DriverInterface(DES_VSUNICOIN,0);)
153 keyonly(V,DIPS^=1;DriverInterface(DES_VSUNITOGGLEDIPVIEW,0);)
154 if(!(DIPS&1)) goto DIPSless;
155 keyonly(1,DriverInterface(DES_VSUNIDIPSET,(void *)1);)
156 keyonly(2,DriverInterface(DES_VSUNIDIPSET,(void *)2);)
157 keyonly(3,DriverInterface(DES_VSUNIDIPSET,(void *)3);)
158 keyonly(4,DriverInterface(DES_VSUNIDIPSET,(void *)4);)
159 keyonly(5,DriverInterface(DES_VSUNIDIPSET,(void *)5);)
160 keyonly(6,DriverInterface(DES_VSUNIDIPSET,(void *)6);)
161 keyonly(7,DriverInterface(DES_VSUNIDIPSET,(void *)7);)
162 keyonly(8,DriverInterface(DES_VSUNIDIPSET,(void *)8);)
163 }
164 else
165 {
166 keyonly(H,DriverInterface(DES_NTSCSELHUE,0);)
167 keyonly(T,DriverInterface(DES_NTSCSELTINT,0);)
168 if(KEY(KP_MINUS) || KEY(MINUS)) DriverInterface(DES_NTSCDEC,0);
169 if(KEY(KP_PLUS) || KEY(EQUAL)) DriverInterface(DES_NTSCINC,0);
170
171 DIPSless:
172 keyonly(0,FCEUI_SelectState(0);)
173 keyonly(1,FCEUI_SelectState(1);)
174 keyonly(2,FCEUI_SelectState(2);)
175 keyonly(3,FCEUI_SelectState(3);)
176 keyonly(4,FCEUI_SelectState(4);)
177 keyonly(5,FCEUI_SelectState(5);)
178 keyonly(6,FCEUI_SelectState(6);)
179 keyonly(7,FCEUI_SelectState(7);)
180 keyonly(8,FCEUI_SelectState(8);)
181 keyonly(9,FCEUI_SelectState(9);)
182 }
183 }
184}
185
186uint32 KeyboardDodo(void)
187{
188 uint32 JS=0;
189
190
191 if(GI)
192 if(GI->type!=GIT_NSF)
193 {
194 int x,y,u,b;
195
196 for(u=0;u<4;u++)
197 {
198 if(keybEnable&(1<<u))
199 {
200 int *tmpo=keyBMap[u];
201 x=y=0;
202
203 for(b=3;b>=0;b--)
204 if(keys[tmpo[b]]) JS|=(1<<b)<<(u<<3);
205
206 if(keys[tmpo[4]]) y|= JOY_UP;
207 if(keys[tmpo[5]]) y|= JOY_DOWN;
208 if(keys[tmpo[6]]) x|= JOY_LEFT;
209 if(keys[tmpo[7]]) x|= JOY_RIGHT;
210
211 if(y!=(JOY_DOWN|JOY_UP)) JS|=y<<(u<<3);
212 if(x!=(JOY_LEFT|JOY_RIGHT)) JS|=x<<(u<<3);
213 }
214 }
215 }
216 return JS;
217}
218
219uint32 UpdatePPadData(int w)
220{
221 static const char shifttableA[12]={8,9,0,1,11,7,4,2,10,6,5,3};
222 static const char shifttableB[12]={1,0,9,8,2,4,7,11,3,5,6,10};
223 uint32 r=0;
224 int *ppadtsc=powerpadsc[w];
225 int x;
226
227 if(powerpadside&(1<<w))
228 {
229 for(x=0;x<12;x++)
230 if(keys[ppadtsc[x]]) r|=1<<shifttableA[x];
231 }
232 else
233 {
234 for(x=0;x<12;x++)
235 if(keys[ppadtsc[x]]) r|=1<<shifttableB[x];
236 }
237 return r;
238}
239
240int fkbmap[0x48]=
241{
242 SCAN_F1,SCAN_F2,SCAN_F3,SCAN_F4,SCAN_F5,SCAN_F6,SCAN_F7,SCAN_F8,
243 SCAN_1,SCAN_2,SCAN_3,SCAN_4,SCAN_5,SCAN_6,SCAN_7,SCAN_8,SCAN_9,SCAN_0,
244 SCAN_MINUS,SCAN_EQUAL,SCAN_BACKSLASH,SCAN_BACKSPACE,
245 SCAN_ESCAPE,SCAN_Q,SCAN_W,SCAN_E,SCAN_R,SCAN_T,SCAN_Y,SCAN_U,SCAN_I,SCAN_O,
246 SCAN_P,SCAN_GRAVE,SCAN_BRACKET_LEFT,SCAN_ENTER,
247 SCAN_LEFTCONTROL,SCAN_A,SCAN_S,SCAN_D,SCAN_F,SCAN_G,SCAN_H,SCAN_J,SCAN_K,
248 SCAN_L,SCAN_SEMICOLON,SCAN_APOSTROPHE,SCAN_BRACKET_RIGHT,SCAN_BL_INSERT,
249 SCAN_LEFTSHIFT,SCAN_Z,SCAN_X,SCAN_C,SCAN_V,SCAN_B,SCAN_N,SCAN_M,SCAN_COMMA,
250 SCAN_PERIOD,SCAN_SLASH,SCAN_RIGHTALT,SCAN_RIGHTSHIFT,SCAN_LEFTALT,SCAN_SPACE,
251 SCAN_BL_DELETE,SCAN_BL_END,SCAN_BL_PAGEDOWN,
252 SCAN_BL_CURSORUP,SCAN_BL_CURSORLEFT,SCAN_BL_CURSORRIGHT,SCAN_BL_CURSORDOWN
253};
254
255uint8 fkbkeys[0x48];
256void UpdateFKB(void)
257{
258 int x;
259
260 for(x=0;x<0x48;x++)
261 {
262 fkbkeys[x]=0;
263 if(keys[fkbmap[x]])
264 fkbkeys[x]=1;
265 }
266}
267
268
269
270static int inkeyloop=0;
271
272static BOOL CALLBACK KeyConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
273{
274 int x,y;
275 char tempo[64];
276
277 switch(uMsg) {
278 case WM_USER+666:
279 if(inkeyloop)
280 {
281 SetDlgItemInt(hwndDlg,inkeyloop,lParam,0);
282 inkeyloop=0;
283 }
284 break;
285 case WM_INITDIALOG:
286 sprintf(tempo,"Virtual Gamepad %d",porttemp+1);
287 SetDlgItemText(hwndDlg,302,tempo);
288 sprintf(tempo,"Virtual Gamepad %d",porttemp+3);
289 SetDlgItemText(hwndDlg,311,tempo);
290
291 for(x=0;x<2;x++)
292 {
293 for(y=0;y<8;y++)
294 SetDlgItemInt(hwndDlg,600+y+x*10,keyBMap[porttemp+(x<<1)][y],0);
295 if(keybEnable&(1<<((x<<1)+porttemp)))
296 CheckDlgButton(hwndDlg,320+x,BST_CHECKED);
297 }
298 break;
299 case WM_CLOSE:
300 case WM_QUIT: goto gornk;
301 case WM_COMMAND:
302 if(!(wParam>>16))
303 {
304 wParam&=0xFFFF;
305 if((wParam>=600 && wParam<=607) || (wParam>=610 && wParam<=617))
306 inkeyloop=wParam;
307 else switch(wParam)
308 {
309 case 1:
310 gornk:
311 for(x=0;x<2;x++)
312 {
313 for(y=0;y<8;y++)
314 keyBMap[porttemp+(x<<1)][y]=GetDlgItemInt(hwndDlg,600+y+x*10,0,0);
315
316 if(IsDlgButtonChecked(hwndDlg,320+x)==BST_CHECKED)
317 keybEnable|=(1<<((x<<1)+porttemp));
318 else
319 keybEnable&=~(1<<((x<<1)+porttemp));
320 }
321
322 EndDialog(hwndDlg,0);
323 break;
324 }
325 }
326 }
327 return 0;
328}
329
330static BOOL CALLBACK KeyPPConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
331{
332 int x;
333 char tempo[64];
334
335 switch(uMsg) {
336 case WM_USER+666:
337 if(inkeyloop)
338 {
339 SetDlgItemInt(hwndDlg,inkeyloop,lParam,0);
340 inkeyloop=0;
341 }
342 break;
343 case WM_INITDIALOG:
344 for(x=0;x<12;x++)
345 SetDlgItemInt(hwndDlg,500+x,powerpadsc[porttemp][x],0);
346 CheckDlgButton(hwndDlg,300+((powerpadside>>porttemp)&1),BST_CHECKED);
347 sprintf(tempo,"Virtual Power Pad %d",porttemp+1);
348 SetDlgItemText(hwndDlg,302,tempo);
349 break;
350 case WM_CLOSE:
351 case WM_QUIT: goto gornk;
352 case WM_COMMAND:
353 if(!(wParam>>16))
354 {
355 wParam&=0xFFFF;
356 if(wParam>=500 && wParam<=511)
357 inkeyloop=wParam;
358 else switch(wParam)
359 {
360 case 1:
361 gornk:
362 for(x=0;x<12;x++)
363 powerpadsc[porttemp][x]=GetDlgItemInt(hwndDlg,500+x,0,0);
364 powerpadside&=~(1<<porttemp);
365 if(IsDlgButtonChecked(hwndDlg,301)==BST_CHECKED)
366 powerpadside|=1<<porttemp;
367 EndDialog(hwndDlg,0);
368 break;
369 }
370 }
371 }
372 return 0;
373}
374
375static BOOL CALLBACK FKBConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
376{
377 int x;
378
379 switch(uMsg) {
380 case WM_USER+666:
381 if(inkeyloop)
382 {
383 SetDlgItemInt(hwndDlg,inkeyloop,lParam,0);
384 fkbmap[inkeyloop-300]=lParam;
385 inkeyloop=0;
386 }
387 break;
388 case WM_INITDIALOG:
389 for(x=0;x<72;x++)
390 SetDlgItemInt(hwndDlg,300+x,fkbmap[x],0);
391 break;
392 case WM_CLOSE:
393 case WM_QUIT: goto gornk;
394 case WM_COMMAND:
395 if(!(wParam>>16))
396 {
397 wParam&=0xFFFF;
398 if(wParam>=300 && wParam<=371)
399 inkeyloop=wParam;
400 else switch(wParam)
401 {
402 case 1:
403 gornk:
404 EndDialog(hwndDlg,0);
405 break;
406 }
407 }
408 }
409 return 0;
410}
411
412static HHOOK hHook;
413static LRESULT CALLBACK FilterFunc(int nCode, WORD wParam, DWORD lParam)
414{
415 MSG FAR *ptrMsg;
416 LPARAM tmpo;
417
418 if(nCode>=0)
419 {
420 if(nCode==MSGF_DIALOGBOX)
421 {
422 ptrMsg=(MSG FAR *)lParam;
423 if(ptrMsg->message==WM_KEYDOWN || ptrMsg->message==WM_SYSKEYDOWN)
424 {
425 tmpo=((ptrMsg->lParam>>16)&0x7F)|((ptrMsg->lParam>>17)&0x80);
426 PostMessage(GetParent(ptrMsg->hwnd),WM_USER+666,0,tmpo);
427 if(inkeyloop) return 1;
428 }
429 }
430 }
431 return CallNextHookEx(hHook,nCode,wParam,lParam);
432}
433
434
435void ConfigKeyboardie(HWND hParent, int port)
436{
437 porttemp=port;
438
439 hHook=SetWindowsHookEx(WH_MSGFILTER,(HOOKPROC)FilterFunc,fceu_hInstance,GetCurrentThreadId());
440 DialogBox(fceu_hInstance,"KEYCONFIG",hParent,KeyConCallB);
441 UnhookWindowsHookEx(hHook);
442}
443
444void ConfigKeyboardiePowerpad(HWND hParent, int port)
445{
446 porttemp=port;
447
448 hHook=SetWindowsHookEx(WH_MSGFILTER,(HOOKPROC)FilterFunc,fceu_hInstance,GetCurrentThreadId());
449 DialogBox(fceu_hInstance,"KEYPPCONFIG",hParent,KeyPPConCallB);
450 UnhookWindowsHookEx(hHook);
451}
452
453void ConfigFKB(HWND hParent)
454{
455 hHook=SetWindowsHookEx(WH_MSGFILTER,(HOOKPROC)FilterFunc,fceu_hInstance,GetCurrentThreadId());
456 DialogBox(fceu_hInstance,"FKBCONFIG",hParent,FKBConCallB);
457 UnhookWindowsHookEx(hHook);
458}