1 /* FCE Ultra - NES/Famicom Emulator
\r
3 * Copyright notice for this file:
\r
4 * Copyright (C) 2002 Ben Parnell
\r
6 * This program is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 2 of the License, or
\r
9 * (at your option) any later version.
\r
11 * This program is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with this program; if not, write to the Free Software
\r
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
25 #include "joystick.h"
\r
30 static GUID joyGUID[64];
\r
32 static int joycounter;
\r
34 static LPDIRECTINPUTDEVICE7 lpJoy[4]={0,0,0,0};
\r
36 int joyOptions[4]={0,0,0,0};
\r
37 int joyA[4]={1,1,1,1};
\r
38 int joyB[4]={0,0,0,0};
\r
39 int joySelect[4]={2,2,2,2};
\r
40 int joyStart[4]={3,3,3,3};
\r
41 int joyUp[4]={4,4,4,4};
\r
42 int joyDown[4]={5,5,5,5};
\r
43 int joyLeft[4]={6,6,6,6};
\r
44 int joyRight[4]={7,7,7,7};
\r
46 int joy[4]={0,0,0,0};
\r
48 static int JoyXMax[4];
\r
49 static int JoyXMin[4];
\r
51 static int JoyYMax[4];
\r
52 static int JoyYMin[4];
\r
54 static DIJOYSTATE2 JoyStatus;
\r
56 static void ShowDIJErr(int w, char *s)
\r
59 sprintf(tempo,"DirectInput: Joystick %d: %s",w+1,s);
\r
60 FCEUD_PrintError(tempo);
\r
63 static void JoyAutoRestore(HRESULT ddrval,LPDIRECTINPUTDEVICE7 lpJJoy)
\r
67 case DIERR_INPUTLOST:
\r
68 case DIERR_NOTACQUIRED:
\r
69 IDirectInputDevice7_Acquire(lpJJoy);
\r
74 static int GetJoystickButton(int x)
\r
82 if(errc>8) return(-1);
\r
84 ddrval=IDirectInputDevice7_Poll(lpJoy[x]);
\r
85 if(ddrval!=DI_OK && ddrval!=DI_NOEFFECT) {JoyAutoRestore(ddrval,lpJoy[x]);errc++;goto doagaino;}
\r
87 ddrval=IDirectInputDevice7_GetDeviceState(lpJoy[x],sizeof(JoyStatus),&JoyStatus);
\r
88 if(ddrval!=DI_OK) {JoyAutoRestore(ddrval,lpJoy[x]);errc++;goto doagaino;}
\r
91 if(JoyStatus.rgbButtons[z]&0x80)
\r
97 uint32 GetJSOr(void)
\r
108 ddrval=IDirectInputDevice7_Poll(lpJoy[x]);
\r
109 if(ddrval!=DI_OK && ddrval!=DI_NOEFFECT) JoyAutoRestore(ddrval,lpJoy[x]);
\r
111 ddrval=IDirectInputDevice7_GetDeviceState(lpJoy[x],sizeof(JoyStatus),&JoyStatus);
\r
112 if(ddrval!=DI_OK) JoyAutoRestore(ddrval,lpJoy[x]);
\r
114 if(joyOptions[x]&1)
\r
116 if(JoyStatus.rgbButtons[joyUp[x]&127]&0x80) ret|=JOY_UP<<(x<<3);
\r
117 if(JoyStatus.rgbButtons[joyDown[x]&127]&0x80) ret|=JOY_DOWN<<(x<<3);
\r
118 if(JoyStatus.rgbButtons[joyLeft[x]&127]&0x80) ret|=JOY_LEFT<<(x<<3);
\r
119 if(JoyStatus.rgbButtons[joyRight[x]&127]&0x80) ret|=JOY_RIGHT<<(x<<3);
\r
123 if(JoyStatus.lX>=JoyXMax[x])
\r
124 ret|=JOY_RIGHT<<(x<<3);
\r
125 else if(JoyStatus.lX<=JoyXMin[x])
\r
126 ret|=JOY_LEFT<<(x<<3);
\r
128 if(JoyStatus.lY>=JoyYMax[x])
\r
129 ret|=JOY_DOWN<<(x<<3);
\r
130 else if(JoyStatus.lY<=JoyYMin[x])
\r
131 ret|=JOY_UP<<(x<<3);
\r
133 if(JoyStatus.rgbButtons[joyA[x]&127]&0x80) ret|=1<<(x<<3);
\r
134 if(JoyStatus.rgbButtons[joyB[x]&127]&0x80) ret|=2<<(x<<3);
\r
135 if(JoyStatus.rgbButtons[joySelect[x]&127]&0x80) ret|=4<<(x<<3);
\r
136 if(JoyStatus.rgbButtons[joyStart[x]&127]&0x80) ret|=8<<(x<<3);
\r
143 static void KillJoystick(int w)
\r
147 IDirectInputDevice7_Unacquire(lpJoy[w]);
\r
148 IDirectInputDevice7_Release(lpJoy[w]);
\r
153 void KillJoysticks(void)
\r
160 static BOOL CALLBACK JoystickFound(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
\r
164 joyGUID[joycounter]=lpddi->guidInstance;
\r
168 SendDlgItemMessage(pvRef,106,CB_ADDSTRING,0,(LPARAM)(LPSTR)lpddi->tszProductName);
\r
169 SendDlgItemMessage(pvRef,112,CB_ADDSTRING,0,(LPARAM)(LPSTR)lpddi->tszProductName);
\r
171 return DIENUM_CONTINUE;
\r
177 void InitJoystick(int w, HWND wnd)
\r
181 if(joy[w]>joycounter)
\r
183 ShowDIJErr(w,"Not found.");
\r
187 ddrval=IDirectInput7_CreateDeviceEx(lpDI,&joyGUID[joy[w]-1],&IID_IDirectInputDevice7,(LPVOID *)&lpJoy[w],0);
\r
188 if(ddrval != DI_OK)
\r
190 ShowDIJErr(w,"Error creating device.");
\r
194 ddrval=IDirectInputDevice7_SetCooperativeLevel(lpJoy[w],wnd,DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);
\r
195 if (ddrval != DI_OK)
\r
197 ShowDIJErr(w,"Error setting cooperative level.");
\r
202 ddrval=IDirectInputDevice7_SetDataFormat(lpJoy[w],&c_dfDIJoystick2);
\r
203 if (ddrval != DI_OK)
\r
205 ShowDIJErr(w,"Error setting data format.");
\r
215 memset(&diprg,0,sizeof(DIPROPRANGE));
\r
216 diprg.diph.dwSize=sizeof(DIPROPRANGE);
\r
217 diprg.diph.dwHeaderSize=sizeof(DIPROPHEADER);
\r
218 diprg.diph.dwHow=DIPH_BYOFFSET;
\r
219 diprg.diph.dwObj=DIJOFS_X;
\r
220 ddrval=IDirectInputDevice7_GetProperty(lpJoy[w],DIPROP_RANGE,&diprg.diph);
\r
223 ShowDIJErr(w,"Error getting X axis range.");
\r
229 r=diprg.lMax-diprg.lMin;
\r
230 JoyXMax[w]=diprg.lMax-(r>>2);
\r
231 JoyXMin[w]=diprg.lMin+(r>>2);
\r
233 memset(&diprg,0,sizeof(DIPROPRANGE));
\r
234 diprg.diph.dwSize=sizeof(DIPROPRANGE);
\r
235 diprg.diph.dwHeaderSize=sizeof(DIPROPHEADER);
\r
236 diprg.diph.dwHow=DIPH_BYOFFSET;
\r
237 diprg.diph.dwObj=DIJOFS_Y;
\r
238 ddrval=IDirectInputDevice7_GetProperty(lpJoy[w],DIPROP_RANGE,&diprg.diph);
\r
241 ShowDIJErr(w,"Error getting X axis range.");
\r
246 r=diprg.lMax-diprg.lMin;
\r
247 JoyYMax[w]=diprg.lMax-(r>>2);
\r
248 JoyYMin[w]=diprg.lMin+(r>>2);
\r
254 void InitJoysticks(HWND wnd)
\r
259 IDirectInput7_EnumDevices(lpDI, DIDEVTYPE_JOYSTICK,JoystickFound,0,DIEDFL_ATTACHEDONLY);
\r
262 InitJoystick(x,wnd);
\r
266 static int joyconport;
\r
268 static BOOL CALLBACK JoyConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
276 if(bid>=200 && bid<=215)
\r
280 /* GetJoystickButton() makes sure there is a joystick,
\r
281 so we don't need to here.
\r
285 if( (z=GetJoystickButton(joyconport))!=-1)
\r
286 SetDlgItemInt(hwndDlg,bid,z,0);
\r
290 if( (z=GetJoystickButton(2+joyconport))!=-1)
\r
291 SetDlgItemInt(hwndDlg,bid,z,0);
\r
295 case WM_INITDIALOG:
\r
297 SetTimer(hwndDlg,666,20,0); /* Every 20ms(50x a second).*/
\r
299 InitJoysticks(hwndDlg);
\r
301 SendDlgItemMessage(hwndDlg,106,CB_ADDSTRING,0,(LPARAM)(LPSTR)"<none>");
\r
302 SendDlgItemMessage(hwndDlg,112,CB_ADDSTRING,0,(LPARAM)(LPSTR)"<none>");
\r
304 sprintf(tempo,"Virtual Gamepad %d",joyconport+1);
\r
305 SetDlgItemText(hwndDlg,102,tempo);
\r
306 sprintf(tempo,"Virtual Gamepad %d",joyconport+3);
\r
307 SetDlgItemText(hwndDlg,104,tempo);
\r
311 SetDlgItemInt(hwndDlg,200+(x<<2),joySelect[x+joyconport],0);
\r
312 SetDlgItemInt(hwndDlg,201+(x<<2),joyStart[x+joyconport],0);
\r
313 SetDlgItemInt(hwndDlg,202+(x<<2),joyB[x+joyconport],0);
\r
314 SetDlgItemInt(hwndDlg,203+(x<<2),joyA[x+joyconport],0);
\r
316 SetDlgItemInt(hwndDlg,204+(x<<2),joyUp[x+joyconport],0);
\r
317 SetDlgItemInt(hwndDlg,205+(x<<2),joyDown[x+joyconport],0);
\r
318 SetDlgItemInt(hwndDlg,206+(x<<2),joyLeft[x+joyconport],0);
\r
319 SetDlgItemInt(hwndDlg,207+(x<<2),joyRight[x+joyconport],0);
\r
323 IDirectInput7_EnumDevices(lpDI, DIDEVTYPE_JOYSTICK,JoystickFound,hwndDlg,DIEDFL_ATTACHEDONLY);
\r
325 SendDlgItemMessage(hwndDlg,106,CB_SETCURSEL,joy[0+joyconport],(LPARAM)(LPSTR)0);
\r
326 SendDlgItemMessage(hwndDlg,112,CB_SETCURSEL,joy[2+joyconport],(LPARAM)(LPSTR)0);
\r
328 if(joyOptions[joyconport]&1)
\r
329 CheckDlgButton(hwndDlg,300,BST_CHECKED);
\r
330 if(joyOptions[joyconport+2]&1)
\r
331 CheckDlgButton(hwndDlg,301,BST_CHECKED);
\r
334 case WM_QUIT: goto gornk;
\r
336 if(HIWORD(wParam)==EN_SETFOCUS)
\r
338 bid=LOWORD(wParam);
\r
340 else if(HIWORD(wParam)==EN_KILLFOCUS)
\r
344 else if(HIWORD(wParam)==CBN_SELENDOK)
\r
346 switch(LOWORD(wParam))
\r
349 KillJoystick(joyconport);
\r
350 joy[0+(joyconport)]=SendDlgItemMessage(hwndDlg,106,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
\r
351 InitJoystick(joyconport,hwndDlg);
\r
352 SendDlgItemMessage(hwndDlg,106,CB_SETCURSEL,joy[0+joyconport],(LPARAM)(LPSTR)0);
\r
355 KillJoystick(2+joyconport);
\r
356 joy[2+(joyconport)]=SendDlgItemMessage(hwndDlg,112,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
\r
357 InitJoystick(2+joyconport,hwndDlg);
\r
358 SendDlgItemMessage(hwndDlg,112,CB_SETCURSEL,joy[2+joyconport],(LPARAM)(LPSTR)0);
\r
364 switch(wParam&0xFFFF)
\r
369 KillTimer(hwndDlg,666);
\r
374 joySelect[x+(joyconport)]=GetDlgItemInt(hwndDlg,200+(x<<2),0,0);
\r
375 joyStart[x+(joyconport)]=GetDlgItemInt(hwndDlg,201+(x<<2),0,0);
\r
376 joyB[x+(joyconport)]=GetDlgItemInt(hwndDlg,202+(x<<2),0,0);
\r
377 joyA[x+(joyconport)]=GetDlgItemInt(hwndDlg,203+(x<<2),0,0);
\r
379 joyUp[x+(joyconport)]=GetDlgItemInt(hwndDlg,204+(x<<2),0,0);
\r
380 joyDown[x+(joyconport)]=GetDlgItemInt(hwndDlg,205+(x<<2),0,0);
\r
381 joyLeft[x+(joyconport)]=GetDlgItemInt(hwndDlg,206+(x<<2),0,0);
\r
382 joyRight[x+(joyconport)]=GetDlgItemInt(hwndDlg,207+(x<<2),0,0);
\r
384 if(IsDlgButtonChecked(hwndDlg,300)==BST_CHECKED)
\r
385 joyOptions[joyconport]|=1;
\r
387 joyOptions[joyconport]&=~1;
\r
388 if(IsDlgButtonChecked(hwndDlg,301)==BST_CHECKED)
\r
389 joyOptions[joyconport+2]|=1;
\r
391 joyOptions[joyconport+2]&=~1;
\r
392 EndDialog(hwndDlg,0);
\r
399 void ConfigJoystickies(HWND hParent, int port)
\r
404 DialogBox(fceu_hInstance,"JOYCONFIG",hParent,JoyConCallB);
\r
405 InitJoysticks(hAppWnd);
\r