/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/plugins/SSSPSXPAD/PadSSSPSX.cpp
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta/plugins/SSSPSXPAD/PadSSSPSX.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 9 months ago) by william
Original Path: trunk/plugins/SSSPSXPAD/PadSSSPSX.cpp
File size: 28919 byte(s)
committing r3113 initial commit again...
1 #define WINVER 0x0500
2 #define _WIN32_WINNT WINVER
3 #define DIRECTINPUT_VERSION 0x0800
4
5 #include <windows.h>
6 #include <windowsx.h>
7 #include <commctrl.h>
8 #include <dinput.h>
9 #include <string>
10
11 #include "PadSSSPSX.h"
12
13 #ifdef _MSC_VER
14 # include "svnrev.h"
15 #endif
16
17 static const unsigned char version = 0x0002;
18 static const unsigned char revision = 1;
19 static const unsigned char build = 7;
20 static const unsigned char buildfix = 1;
21
22 HMODULE hInstance;
23 HWND hTargetWnd;
24
25 static std::string s_strIniPath( "inis/" );
26
27 static CRITICAL_SECTION update_lock;
28 static CRITICAL_SECTION init_lock;
29
30 struct EnterScopedSection
31 {
32 CRITICAL_SECTION& m_cs;
33
34 EnterScopedSection( CRITICAL_SECTION& cs ) : m_cs( cs ) {
35 EnterCriticalSection( &m_cs );
36 }
37
38 ~EnterScopedSection() {
39 LeaveCriticalSection( &m_cs );
40 }
41 };
42
43
44 static struct
45 {
46 keyEvent ev;
47 u8 state[2][256];
48 } save;
49
50 static struct
51 {
52 Config config;
53 int devcnt;
54 LPDIRECTINPUT8 pDInput;
55 LPDIRECTINPUTDEVICE8 pDKeyboard;
56 LPDIRECTINPUTDEVICE8 pDDevice[4];
57 LPDIRECTINPUTEFFECT pDEffect[4][2]; /* for Small & Big Motor */
58 DIJOYSTATE JoyState[4];
59 u16 padStat[2];
60 int padID[2];
61 int padMode1[2];
62 int padMode2[2];
63 int padModeE[2];
64 int padModeC[2];
65 int padModeF[2];
66 int padVib0[2];
67 int padVib1[2];
68 int padVibF[2][4];
69 int padVibC[2];
70 DWORD padPress[2][16];
71 int curPad;
72 int curByte;
73 int curCmd;
74 int cmdLen;
75 } global;
76
77 static BOOL CALLBACK EnumAxesCallback (LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef)
78 {
79 LPDIRECTINPUTDEVICE8 pDDevice = (LPDIRECTINPUTDEVICE8)pvRef;
80 DIPROPRANGE diprg;
81 diprg.diph.dwSize = sizeof (diprg);
82 diprg.diph.dwHeaderSize = sizeof (diprg.diph);
83 diprg.diph.dwObj = lpddoi->dwType;
84 diprg.diph.dwHow = DIPH_BYID;
85 diprg.lMin = -128;
86 diprg.lMax = 127;
87 pDDevice->SetProperty (DIPROP_RANGE, &diprg.diph);
88 return DIENUM_CONTINUE;
89 }
90
91 static BOOL CALLBACK EnumJoysticksCallback (const DIDEVICEINSTANCE* instance, VOID* pContext)
92 {
93 const int devno = global.devcnt;
94 if (devno >= 4)
95 return DIENUM_STOP;
96 HRESULT result = global.pDInput->CreateDevice (instance->guidInstance, &global.pDDevice[devno], NULL);
97 if (FAILED (result))
98 return DIENUM_CONTINUE;
99 global.devcnt++;
100 return DIENUM_CONTINUE;
101 }
102
103 static bool ReleaseDirectInput (void)
104 {
105 int index = 4;
106 while (index--)
107 {
108 int index2 = 2;
109 while (index2--)
110 {
111 if (global.pDEffect[index][index2])
112 {
113 global.pDEffect[index][index2]->Unload();
114 global.pDEffect[index][index2]->Release();
115 global.pDEffect[index][index2] = NULL;
116 }
117 }
118 if (global.pDDevice[index])
119 {
120 global.pDDevice[index]->Unacquire();
121 global.pDDevice[index]->Release();
122 global.pDDevice[index] = NULL;
123 }
124 }
125 if (global.pDKeyboard)
126 {
127 global.pDKeyboard->Unacquire();
128 global.pDKeyboard->Release();
129 global.pDKeyboard = NULL;
130 }
131 if (global.pDInput)
132 {
133 global.pDInput->Release();
134 global.pDInput = NULL;
135 }
136 global.devcnt = 0;
137 return FALSE;
138 }
139
140 static bool InitDirectInput (void)
141 {
142 EnterScopedSection initlock( init_lock );
143
144 if (global.pDInput)
145 return TRUE;
146 HRESULT result = DirectInput8Create (hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&global.pDInput, NULL);
147 if (FAILED (result))
148 return ReleaseDirectInput();
149 result = global.pDInput->CreateDevice (GUID_SysKeyboard, &global.pDKeyboard, NULL);
150 if (FAILED (result))
151 return ReleaseDirectInput();
152 result = global.pDInput->EnumDevices (DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY);
153 if (FAILED (result))
154 return ReleaseDirectInput();
155 result = global.pDKeyboard->SetDataFormat (&c_dfDIKeyboard);
156 if (FAILED (result))
157 return ReleaseDirectInput();
158 if (hTargetWnd)
159 {
160 global.pDKeyboard->Unacquire();
161 result = global.pDKeyboard->SetCooperativeLevel (hTargetWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
162 if (FAILED (result))
163 return ReleaseDirectInput();
164 }
165 int index = global.devcnt;
166 while (index--)
167 {
168 const LPDIRECTINPUTDEVICE8 pDDevice = global.pDDevice[index];
169 result = pDDevice->SetDataFormat (&c_dfDIJoystick);
170 if (FAILED (result))
171 return ReleaseDirectInput();
172 if (hTargetWnd)
173 {
174 pDDevice->Unacquire();
175 result = pDDevice->SetCooperativeLevel (hTargetWnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE);
176 if (FAILED (result))
177 return ReleaseDirectInput();
178 }
179 struct
180 {
181 DIPROPDWORD dipdw;
182 DWORD rgdwAxes[2];
183 LONG rglDirection[2];
184 DIPERIODIC per;
185 DICONSTANTFORCE cf;
186 DIEFFECT eff;
187 } local;
188 memset (&local, 0, sizeof (local));
189 local.dipdw.diph.dwSize = sizeof (DIPROPDWORD);
190 local.dipdw.diph.dwHeaderSize = sizeof (DIPROPHEADER);
191 local.dipdw.diph.dwHow = DIPH_DEVICE;
192 local.dipdw.dwData = DIPROPAUTOCENTER_OFF;
193 pDDevice->SetProperty (DIPROP_AUTOCENTER, &local.dipdw.diph);
194 result = pDDevice->EnumObjects (EnumAxesCallback, pDDevice, DIDFT_AXIS);
195 if (FAILED (result))
196 return ReleaseDirectInput();
197
198 local.rgdwAxes[0] = DIJOFS_X;
199 local.rgdwAxes[1] = DIJOFS_Y;
200 local.eff.dwSize = sizeof (DIEFFECT);
201 local.eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
202 local.eff.dwDuration = INFINITE;
203 local.eff.dwGain = DI_FFNOMINALMAX;
204 local.eff.dwTriggerButton = DIEB_NOTRIGGER;
205 local.eff.cAxes = 2;
206 local.eff.rgdwAxes = local.rgdwAxes;
207 local.eff.rglDirection = local.rglDirection;
208
209 /* Small Motor */
210 local.eff.cbTypeSpecificParams = sizeof (DIPERIODIC);
211 local.eff.lpvTypeSpecificParams = &local.per;
212 result = pDDevice->CreateEffect (GUID_Square , &local.eff, &global.pDEffect[index][0], NULL);
213 if (FAILED (result))
214 global.pDEffect[index][0] = NULL;
215
216 /* Big Motor */
217 local.eff.cbTypeSpecificParams = sizeof (DICONSTANTFORCE);
218 local.eff.lpvTypeSpecificParams = &local.cf;
219 result = pDDevice->CreateEffect (GUID_ConstantForce , &local.eff, &global.pDEffect[index][1], NULL);
220 if (FAILED (result))
221 global.pDEffect[index][1] = NULL;
222 }
223 return TRUE;
224 }
225
226 static bool AcquireDevice (LPDIRECTINPUTDEVICE8 lpDirectInputDevice)
227 {
228 if (FAILED (lpDirectInputDevice->Acquire()))
229 {
230 HRESULT result = lpDirectInputDevice->Acquire();
231 if (result == DIERR_OTHERAPPHASPRIO)
232 return FALSE;
233 if (FAILED (result))
234 return ReleaseDirectInput();
235 }
236 return TRUE;
237 }
238
239 /* Small Motor */
240 static bool SetDeviceForceS (int pad, DWORD force)
241 {
242 InitDirectInput();
243 if (global.pDEffect[pad][0])
244 {
245 LONG rglDirection[2] = { 0, 0 };
246 DIPERIODIC per;
247 rglDirection[0] = 0;
248 rglDirection[1] = 1;
249 per.dwMagnitude = force;
250 per.dwPeriod = (DWORD) (0.01 * DI_SECONDS);
251 per.lOffset = 0;
252 per.dwPhase = 0;
253 DIEFFECT eff;
254 eff.dwSize = sizeof (DIEFFECT);
255 eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
256 eff.cAxes = 2;
257 eff.rglDirection = rglDirection;
258 eff.lpEnvelope = 0;
259 eff.cbTypeSpecificParams = sizeof (DIPERIODIC);
260 eff.lpvTypeSpecificParams = &per;
261 if (FAILED (global.pDEffect[pad][0]->SetParameters (&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START)))
262 return ReleaseDirectInput();
263 if (FAILED (global.pDEffect[pad][0]->Stop()))
264 {
265 AcquireDevice (global.pDDevice[pad]);
266 if (FAILED (global.pDEffect[pad][0]->Stop()))
267 return ReleaseDirectInput();
268 }
269 if (force == 0)
270 return TRUE;
271 if (FAILED (global.pDEffect[pad][0]->Start (1, 0)))
272 {
273 AcquireDevice (global.pDDevice[pad]);
274 if (FAILED (global.pDEffect[pad][0]->Start (1, 0)))
275 return ReleaseDirectInput();
276 }
277 }
278 return TRUE;
279 }
280
281 /* Big Motor */
282 static bool SetDeviceForceB (int pad, DWORD force)
283 {
284 InitDirectInput();
285 if (global.pDEffect[pad][1])
286 {
287 LONG rglDirection[2] = { 0, 0 };
288 DICONSTANTFORCE cf;
289 rglDirection[0] = 1;
290 rglDirection[1] = 0;
291 cf.lMagnitude = force;
292 DIEFFECT eff;
293 eff.dwSize = sizeof (DIEFFECT);
294 eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
295 eff.cAxes = 2;
296 eff.rglDirection = rglDirection;
297 eff.lpEnvelope = 0;
298 eff.cbTypeSpecificParams = sizeof (DICONSTANTFORCE);
299 eff.lpvTypeSpecificParams = &cf;
300 if (FAILED (global.pDEffect[pad][1]->SetParameters (&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START)))
301 return ReleaseDirectInput();
302 if (FAILED (global.pDEffect[pad][1]->Stop()))
303 {
304 AcquireDevice (global.pDDevice[pad]);
305 if (FAILED (global.pDEffect[pad][1]->Stop()))
306 return ReleaseDirectInput();
307 }
308 if (force == 0)
309 return TRUE;
310 if (FAILED (global.pDEffect[pad][1]->Start (1, 0)))
311 {
312 AcquireDevice (global.pDDevice[pad]);
313 if (FAILED (global.pDEffect[pad][1]->Start (1, 0)))
314 return ReleaseDirectInput();
315 }
316 }
317 return TRUE;
318 }
319
320 static bool GetJoyState (const int devno)
321 {
322 InitDirectInput();
323 if (global.pDDevice[devno] == NULL)
324 return FALSE;
325 global.pDDevice[devno]->Poll();
326 if (FAILED (global.pDDevice[devno]->GetDeviceState (sizeof (DIJOYSTATE), &global.JoyState[devno])))
327 {
328 AcquireDevice (global.pDDevice[devno]);
329 return FALSE;
330 }
331 return TRUE;
332 }
333
334 static bool GetKeyState (u8* keyboard)
335 {
336 InitDirectInput();
337 if (global.pDKeyboard == NULL)
338 return FALSE;
339 global.pDKeyboard->Poll();
340 if (FAILED (global.pDKeyboard->GetDeviceState (256, keyboard)))
341 {
342 AcquireDevice (global.pDKeyboard);
343 return FALSE;
344 }
345 return TRUE;
346 }
347
348 static std::string MakeConfigFileName()
349 {
350 //GetModuleFileName (hInstance, fname, 256);
351 //strcpy (fname + strlen (fname) - 3, "cfg");
352
353 return s_strIniPath + "PadSSSPSX.cfg";
354 }
355
356 static void SaveConfig (void)
357 {
358 const std::string fname( MakeConfigFileName() );
359 CreateDirectory( s_strIniPath.c_str(), NULL );
360
361 HANDLE hFile = CreateFile (fname.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
362 if (hFile != INVALID_HANDLE_VALUE)
363 {
364 DWORD number_of_bytes;
365 WriteFile (hFile, &global.config, sizeof (global.config), &number_of_bytes, NULL);
366 CloseHandle (hFile);
367 }
368 }
369
370 static void LoadConfig (void)
371 {
372 const std::string fname( MakeConfigFileName() );
373 HANDLE hFile = CreateFile (fname.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
374 if (hFile != INVALID_HANDLE_VALUE)
375 {
376 DWORD number_of_bytes;
377 ReadFile (hFile, &global.config, sizeof (global.config), &number_of_bytes, NULL);
378 CloseHandle (hFile);
379 }
380 global.padVibC[0] = global.padVibC[1] = -1;
381 for (int cnt = 21; cnt--; )
382 {
383 const int key0 = global.config.keys[0][cnt];
384 if (key0 >= 0x1000)
385 global.padVibC[0] = (key0 & 0xfff) / 0x100;
386 const int key1 = global.config.keys[1][cnt];
387 if (key1 >= 0x1000)
388 global.padVibC[1] = (key1 & 0xfff) / 0x100;
389 }
390 }
391
392 static void PADsetMode (const int pad, const int mode)
393 {
394 static const u8 padID[] = { 0x41, 0x73, 0x41, 0x79 };
395 global.padMode1[pad] = mode;
396 global.padVib0[pad] = 0;
397 global.padVib1[pad] = 0;
398 global.padVibF[pad][0] = 0;
399 global.padVibF[pad][1] = 0;
400 global.padID[pad] = padID[global.padMode2[pad] * 2 + mode];
401 }
402
403 static void KeyPress (const int pad, const int index, const bool press)
404 {
405 if (index < 16)
406 {
407 if (press)
408 {
409 global.padStat[pad] &= ~(1 << index);
410 if (global.padPress[pad][index] == 0)
411 global.padPress[pad][index] = GetTickCount();
412 }
413 else
414 {
415 global.padStat[pad] |= 1 << index;
416 global.padPress[pad][index] = 0;
417 }
418 }
419 else
420 {
421 static bool prev[2] = { FALSE, FALSE };
422 if ((prev[pad] != press) && (global.padModeF[pad] == 0))
423 {
424 prev[pad] = press;
425 if (press) PADsetMode (pad, !global.padMode1[pad]);
426 }
427 }
428 }
429
430 static void UpdateState (const int pad)
431 {
432 static int flag_keyboard;
433 static int flag_joypad[4];
434 if (pad == 0)
435 {
436 flag_keyboard = 0;
437 flag_joypad[0] = 0;
438 flag_joypad[1] = 0;
439 flag_joypad[2] = 0;
440 flag_joypad[3] = 0;
441 }
442 static u8 keystate[256];
443 for (int index = 17; index--; )
444 {
445 const int key = global.config.keys[pad][index];
446 if (key == 0)
447 continue;
448 else if (key < 0x100)
449 {
450 if (flag_keyboard == FALSE)
451 {
452 flag_keyboard = TRUE;
453 if (GetKeyState (keystate) == FALSE)
454 return;
455 }
456 KeyPress (pad, index, !!(keystate[key] & 0x80));
457 }
458 else
459 {
460 const int joypad = ((key & 0xfff) / 0x100);
461 if (flag_joypad[joypad] == FALSE)
462 {
463 flag_joypad[joypad] = TRUE;
464 if (GetJoyState (joypad) == FALSE)
465 return;
466 }
467 if (key < 0x2000)
468 {
469 KeyPress (pad, index, !!(global.JoyState[joypad].rgbButtons[key & 0xff]));
470 }
471 else if (key < 0x3000)
472 {
473 const int state = ((int*)&global.JoyState[joypad].lX)[(key & 0xff) /2];
474 switch (key & 1)
475 {
476 case 0: KeyPress (pad, index, state < -64); break;
477 case 1: KeyPress (pad, index, state >= 64); break;
478 }
479 }
480 else
481 {
482 const u32 state = global.JoyState[joypad].rgdwPOV[(key & 0xff) /4];
483 switch (key & 3)
484 {
485 case 0: KeyPress (pad, index, (state >= 0 && state <= 4500) || (state >= 31500 && state <= 36000)); break;
486 case 1: KeyPress (pad, index, state >= 4500 && state <= 13500); break;
487 case 2: KeyPress (pad, index, state >= 13500 && state <= 22500); break;
488 case 3: KeyPress (pad, index, state >= 22500 && state <= 31500); break;
489 }
490 }
491 }
492 }
493
494 /* Small Motor */
495 const int vib0 = global.padVibF[pad][0] ? 2000 : 0;
496 if ((global.padVibF[pad][2] != vib0) && (global.padVibC[pad] >= 0))
497 {
498 global.padVibF[pad][2] = vib0;
499 SetDeviceForceS (global.padVibC[pad], vib0);
500 }
501 /* Big Motor */
502 const int vib1 = global.padVibF[pad][1] ? 500 + 37*global.padVibF[pad][1] : 0;
503 if ((global.padVibF[pad][3] != vib1) && (global.padVibC[pad] >= 0))
504 {
505 global.padVibF[pad][3] = vib1;
506 SetDeviceForceB (global.padVibC[pad], vib1);
507 }
508 }
509
510 static void set_label (const HWND hWnd, const int pad, const int index)
511 {
512 const int key = global.config.keys[pad][index];
513 char buff[64];
514 if (key < 0x100)
515 {
516 if (key == 0)
517 strcpy (buff, "NONE");
518 else if (GetKeyNameText (key << 16, buff, sizeof (buff)) == 0)
519 wsprintf (buff, "Keyboard 0x%02X", key);
520 }
521 else if (key >= 0x1000 && key < 0x2000)
522 {
523 wsprintf (buff, "J%d_%d", (key & 0xfff) / 0x100, (key & 0xff) + 1);
524 }
525 else if (key >= 0x2000 && key < 0x3000)
526 {
527 static const char name[][4] = { "MIN", "MAX" };
528 const int axis = (key & 0xff);
529 wsprintf (buff, "J%d_AXIS%d_%s", (key & 0xfff) / 0x100, axis / 2, name[axis % 2]);
530 if (index >= 17 && index <= 20)
531 buff[strlen (buff) -4] = '\0';
532 }
533 else if (key >= 0x3000 && key < 0x4000)
534 {
535 static const char name[][7] = { "FOWARD", "RIGHT", "BACK", "LEFT" };
536 const int pov = (key & 0xff);
537 wsprintf (buff, "J%d_POV%d_%s", (key & 0xfff) / 0x100, pov /4, name[pov % 4]);
538 }
539 Button_SetText (GetDlgItem (hWnd, IDC_ESELECT + index), buff);
540 }
541
542 static BOOL CALLBACK ConfigureDlgProc (const HWND hWnd, const UINT msg, const WPARAM wParam, const LPARAM lParam)
543 {
544 static BYTE keymaps[2][256];
545 static DWORD countdown;
546 static int disabled;
547 static HWND hTabWnd;
548 static int pad;
549 int cnt1;
550 int cnt2;
551 int key;
552 switch (msg)
553 {
554 case WM_INITDIALOG:
555 hTargetWnd = hWnd;
556 pad = disabled = 0;
557 LoadConfig();
558 for (cnt1 = 21; cnt1--; )
559 set_label (hWnd, pad, cnt1);
560 hTabWnd = GetDlgItem (hWnd, IDC_TABC);
561 TCITEM tcI;
562 tcI.mask = TCIF_TEXT;
563 tcI.pszText = "PAD1";
564 TabCtrl_InsertItem (hTabWnd, 0, &tcI);
565 tcI.mask = TCIF_TEXT;
566 tcI.pszText = "PAD2";
567 TabCtrl_InsertItem (hTabWnd, 1, &tcI);
568 SetTimer (hWnd, 0x80, 50, NULL);
569 return TRUE;
570 case WM_DESTROY:
571 break;
572 case WM_NOTIFY:
573 if (wParam == IDC_TABC)
574 {
575 if (disabled)
576 EnableWindow (GetDlgItem (hWnd, disabled), TRUE);
577 disabled = 0;
578 pad = TabCtrl_GetCurSel (hTabWnd);
579 for (cnt1 = 21; cnt1--; )
580 set_label (hWnd, pad, cnt1);
581 }
582 break;
583 case WM_COMMAND:
584 for (cnt1 = 21; cnt1--; )
585 {
586 if (LOWORD (wParam) == IDC_BSELECT + cnt1)
587 {
588 if (disabled)
589 EnableWindow (GetDlgItem (hWnd, disabled), TRUE);
590 EnableWindow (GetDlgItem (hWnd, disabled = wParam), FALSE);
591 countdown = GetTickCount();
592 GetKeyState (keymaps[0]);
593 return TRUE;
594 }
595 }
596 if (LOWORD (wParam) == IDOK)
597 EndDialog (hWnd, IDOK);
598 else if (LOWORD (wParam) == IDCANCEL)
599 EndDialog (hWnd, IDCANCEL);
600 break;
601 case WM_TIMER:
602 if (disabled)
603 {
604 const int index = disabled - IDC_BSELECT;
605 int analog = FALSE;
606 if ((GetTickCount() - countdown) / 1000 != 10)
607 {
608 char buff[64];
609 wsprintf (buff, "Timeout: %d", 10 - (GetTickCount() - countdown) / 1000);
610 SetWindowText (GetDlgItem (hWnd, IDC_ESELECT + index), buff);
611 }
612 else
613 {
614 global.config.keys[pad][index] = 0;
615 set_label (hWnd, pad, index);
616 EnableWindow (GetDlgItem (hWnd, disabled), TRUE);
617 disabled = 0;
618 break;
619 }
620 if (GetKeyState (keymaps[1]) == FALSE)
621 break;
622 for (key = 0x100; key--; )
623 {
624 if (~keymaps[0][key] & keymaps[1][key] & 0x80)
625 break;
626 }
627 for (cnt1 = global.devcnt; cnt1--;)
628 {
629 if (GetJoyState (cnt1) == FALSE)
630 break;
631
632 for (cnt2 = 32; cnt2--; )
633 {
634 if (global.JoyState[cnt1].rgbButtons[cnt2])
635 key = 0x1000 + 0x100 * cnt1 + cnt2;
636 }
637 for (cnt2 = 8; cnt2--; )
638 {
639 const int now = ((u32*)&global.JoyState[cnt1].lX)[cnt2];
640 if (now < -64)
641 {
642 key = 0x2000 + 0x100 * cnt1 + cnt2 * 2 +0;
643 analog = TRUE;
644 }
645 else if (now >= 64)
646 {
647 key = 0x2000 + 0x100 * cnt1 + cnt2 * 2 +1;
648 analog = TRUE;
649 }
650 }
651 for (cnt2 = 4; cnt2--; )
652 {
653 const u32 now = global.JoyState[cnt1].rgdwPOV[cnt2];
654 if ((now >= 0 && now < 4500) || (now >= 31500 && now < 36000))
655 key = 0x3000 + 0x100 * cnt1 + cnt2 * 4 +0;
656 if (now >= 4500 && now < 13500)
657 key = 0x3000 + 0x100 * cnt1 + cnt2 * 4 +1;
658 if (now >= 13500 && now < 22500)
659 key = 0x3000 + 0x100 * cnt1 + cnt2 * 4 +2;
660 if (now >= 22500 && now < 31500)
661 key = 0x3000 + 0x100 * cnt1 + cnt2 * 4 +3;
662 }
663 }
664 if (index >= 17 && index <= 20 && analog == 0)
665 key = 0;
666 else if (key > 0)
667 {
668 if (key != 1)
669 global.config.keys[pad][index] = key;
670 set_label (hWnd, pad, index);
671 EnableWindow (GetDlgItem (hWnd, disabled), TRUE);
672 disabled = 0;
673 }
674 }
675 }
676 return FALSE;
677 }
678
679 static char LibraryName[256];
680 #define SSSPSX_NAME "SSSPSX PAD Pressure Mod"
681
682 static void InitLibraryName()
683 {
684 #ifndef PCSX2_DEVBUILD
685
686 // Public Release!
687 // Output a simplified string that's just our name:
688
689 strcpy_s( LibraryName, SSSPSX_NAME );
690
691 #else
692 #ifdef SVN_REV_UNKNOWN
693
694 // Unknown revision.
695 // Output a name that includes devbuild status but not
696 // subversion revision tags:
697
698 strcpy_s( LibraryName, SSSPSX_NAME
699 #ifdef PCSX2_DEBUG
700 "-Debug"
701 #elif defined( PCSX2_DEVBUILD )
702 "-Dev"
703 #else
704 ""
705 #endif
706 );
707
708 #else
709
710 // Use TortoiseSVN's SubWCRev utility's output
711 // to label the specific revision:
712
713 sprintf_s( LibraryName, SSSPSX_NAME " r%d%s"
714 #ifdef PCSX2_DEBUG
715 "-Debug"
716 #elif defined( PCSX2_DEVBUILD )
717 "-Dev"
718 #else
719 ""
720 #endif
721 ,SVN_REV,
722 SVN_MODS ? "m" : ""
723 );
724 #endif
725 #endif
726
727 }
728
729
730 u32 CALLBACK PS2EgetLibType (void)
731 {
732 return 0x02;
733 }
734
735 const char* CALLBACK PS2EgetLibName (void)
736 {
737 InitLibraryName();
738 return LibraryName;
739 }
740
741 u32 CALLBACK PS2EgetLibVersion2 (u32 type)
742 {
743 return (version << 16) | (revision << 8) | build | (buildfix<<24);
744 }
745
746 u32 CALLBACK PSEgetLibType (void)
747 {
748 return 8;
749 }
750
751 const char* CALLBACK PSEgetLibName (void)
752 {
753 InitLibraryName();
754 return LibraryName;
755 }
756
757 u32 CALLBACK PSEgetLibVersion (void)
758 {
759 return (version << 16) | (revision << 8) | build;
760 }
761
762 s32 CALLBACK PADinit (u32 flags)
763 {
764 return 0;
765 }
766
767 void CALLBACK PADshutdown (void)
768 {
769 }
770
771 static int n_open = 0;
772 s32 CALLBACK PADopen (HWND hWnd)
773 {
774 if (!IsWindow (hWnd) && !IsBadReadPtr ((u32*)hWnd, 4))
775 hWnd = *(HWND*)hWnd;
776 if (!IsWindow (hWnd))
777 hWnd = NULL;
778 else
779 {
780 while (GetWindowLong (hWnd, GWL_STYLE) & WS_CHILD)
781 hWnd = GetParent (hWnd);
782 }
783 hTargetWnd = hWnd;
784 if (n_open++ == FALSE)
785 {
786 memset (&global, 0, sizeof (global));
787 global.padStat[0] = 0xffff;
788 global.padStat[1] = 0xffff;
789 LoadConfig();
790 PADsetMode (0, 0);
791 PADsetMode (1, 0);
792 }
793 return 0;
794 }
795
796 void CALLBACK PADclose (void)
797 {
798 if (--n_open == 0)
799 ReleaseDirectInput();
800 }
801
802 u32 CALLBACK PADquery (void)
803 {
804 return 3;
805 }
806
807 u8 CALLBACK PADstartPoll (int pad)
808 {
809 global.curPad = pad -1;
810 global.curByte = 0;
811 return 0xff;
812 }
813
814 static const u8 cmd40[8] =
815 {
816 0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5a
817 };
818 static const u8 cmd41[8] =
819 {
820 0xff, 0x5a, 0xff, 0xff, 0x03, 0x00, 0x00, 0x5a,
821 };
822 static const u8 cmd44[8] =
823 {
824 0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 };
826 static const u8 cmd45[8] =
827 {
828 0xff, 0x5a, 0x03, 0x02, 0x01, 0x02, 0x01, 0x00,
829 };
830 static const u8 cmd46[8] =
831 {
832 0xff, 0x5a, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0a,
833 };
834 static const u8 cmd47[8] =
835 {
836 0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
837 };
838 static const u8 cmd4c[8] =
839 {
840 0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
841 };
842 static const u8 cmd4d[8] =
843 {
844 0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
845 };
846 static const u8 cmd4f[8] =
847 {
848 0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a,
849 };
850
851 static u8 get_analog (const int key)
852 {
853 const int pad = ((key & 0xf00) / 0x100);
854 const int pos = ((key & 0x0ff) /2);
855 int value = (((int*)&global.JoyState[pad].lX)[pos] + 0x7F);
856 if (value >= 0xC0) value++;
857 if (value < 0) value = 0;
858 // Don't think this happens, but just in case...
859 if (value > 0xFF) value = 0xFF;
860 return (u8)value;
861 }
862
863 static u8 get_pressure (const DWORD now, const DWORD press)
864 {
865 if (press == 0)
866 return 0;
867 return (u8)((now - press > 2550) ? 255 : (now - press) / 10);
868 }
869
870 void CALLBACK PADupdate (int pad)
871 {
872 // PADupdate should be called by the emulator from the thread that owns our hwnd, but
873 // older versions of PCSX2 don't always follow that rule. I suspect this call was
874 // added to the PAD api because supposedly DInput is happiest called from the thread
875 // that owns the hwnd (although it doesn't seem to care in practice).
876
877 // [TODO] SSSPSX really should do all it's DInput pooling/updating here, instead of
878 // in PADpoll, just for the sake of obeying thread affinity suggested guidelines.
879 // I'm not quite sure how to do that and still have it work though. --air
880 }
881
882 // Called from the context of the EE thread.
883 u8 CALLBACK PADpoll (const u8 value)
884 {
885 const int pad = global.curPad;
886 const int cur = global.curByte;
887 static u8 buf[20];
888 if (cur == 0)
889 {
890 global.curByte++;
891 global.curCmd = value;
892 switch (value)
893 {
894 case 0x40:
895 global.cmdLen = sizeof (cmd40);
896 memcpy (buf, cmd40, sizeof (cmd40));
897 return 0xf3;
898 case 0x41:
899 global.cmdLen = sizeof (cmd41);
900 memcpy (buf, cmd41, sizeof (cmd41));
901 return 0xf3;
902 case 0x42:
903 case 0x43:
904 {
905 //EnterScopedSection scoped_lock( update_lock );
906 if (value == 0x42) UpdateState (pad);
907 global.cmdLen = 2 + 2 * (global.padID[pad] & 0x0f);
908 buf[1] = global.padModeC[pad] ? 0x00 : 0x5a;
909 (u16&)buf[2] = global.padStat[pad];
910 if (value == 0x43 && global.padModeE[pad])
911 {
912 buf[4] = 0;
913 buf[5] = 0;
914 buf[6] = 0;
915 buf[7] = 0;
916 return 0xf3;
917 }
918 else
919 {
920 buf[ 4] = get_analog (global.config.keys[pad][19]);
921 buf[ 5] = get_analog (global.config.keys[pad][20]);
922 buf[ 6] = get_analog (global.config.keys[pad][17]);
923 buf[ 7] = get_analog (global.config.keys[pad][18]);
924 if (global.padID[pad] == 0x79)
925 {
926 const DWORD now = GetTickCount();
927 buf[ 8] = get_pressure (now, global.padPress[pad][2]);
928 buf[ 9] = get_pressure (now, global.padPress[pad][0]);
929 buf[10] = get_pressure (now, global.padPress[pad][3]);
930 buf[11] = get_pressure (now, global.padPress[pad][1]);
931 buf[12] = get_pressure (now, global.padPress[pad][11]);
932 buf[13] = get_pressure (now, global.padPress[pad][10]);
933 buf[14] = get_pressure (now, global.padPress[pad][9]);
934 buf[15] = get_pressure (now, global.padPress[pad][8]);
935 buf[16] = get_pressure (now, global.padPress[pad][13]);
936 buf[17] = get_pressure (now, global.padPress[pad][12]);
937 buf[18] = get_pressure (now, global.padPress[pad][15]);
938 buf[19] = get_pressure (now, global.padPress[pad][14]);
939 }
940 return (u8)global.padID[pad];
941 }
942 break;
943 }
944 case 0x44:
945 global.cmdLen = sizeof (cmd44);
946 memcpy (buf, cmd44, sizeof (cmd44));
947 return 0xf3;
948 case 0x45:
949 global.cmdLen = sizeof (cmd45);
950 memcpy (buf, cmd45, sizeof (cmd45));
951 buf[4] = (u8)global.padMode1[pad];
952 return 0xf3;
953 case 0x46:
954 global.cmdLen = sizeof (cmd46);
955 memcpy (buf, cmd46, sizeof (cmd46));
956 return 0xf3;
957 case 0x47:
958 global.cmdLen = sizeof (cmd47);
959 memcpy (buf, cmd47, sizeof (cmd47));
960 return 0xf3;
961 case 0x4c:
962 global.cmdLen = sizeof (cmd4c);
963 memcpy (buf, cmd4c, sizeof (cmd4c));
964 return 0xf3;
965 case 0x4d:
966 global.cmdLen = sizeof (cmd4d);
967 memcpy (buf, cmd4d, sizeof (cmd4d));
968 return 0xf3;
969 case 0x4f:
970 {
971 //EnterScopedSection scoped_lock( update_lock );
972 global.padID[pad] = 0x79;
973 global.padMode2[pad] = 1;
974 global.cmdLen = sizeof (cmd4f);
975 memcpy (buf, cmd4f, sizeof (cmd4f));
976 return 0xf3;
977 }
978 }
979 }
980
981 //EnterScopedSection scoped_lock( update_lock );
982
983 switch (global.curCmd)
984 {
985 case 0x42:
986 if (cur == global.padVib0[pad])
987 global.padVibF[pad][0] = value;
988 if (cur == global.padVib1[pad])
989 global.padVibF[pad][1] = value;
990 break;
991 case 0x43:
992 if (cur == 2)
993 {
994 global.padModeE[pad] = value;
995 global.padModeC[pad] = 0;
996 }
997 break;
998 case 0x44:
999 if (cur == 2)
1000 PADsetMode (pad, value);
1001 if (cur == 3)
1002 global.padModeF[pad] = (value == 3);
1003 break;
1004 case 0x46:
1005 if (cur == 2)
1006 {
1007 switch(value)
1008 {
1009 case 0:
1010 buf[5] = 0x02;
1011 buf[6] = 0x00;
1012 buf[7] = 0x0A;
1013 break;
1014 case 1:
1015 buf[5] = 0x01;
1016 buf[6] = 0x01;
1017 buf[7] = 0x14;
1018 break;
1019 }
1020 }
1021 break;
1022 case 0x4c:
1023 if (cur == 2)
1024 {
1025 static const u8 buf5[] = { 0x04, 0x07, 0x02, 0x05 };
1026 buf[5] = buf5[value & 3];
1027 }
1028 break;
1029 case 0x4d:
1030 if (cur >= 2)
1031 {
1032 if (cur == global.padVib0[pad])
1033 buf[cur] = 0x00;
1034 if (cur == global.padVib1[pad])
1035 buf[cur] = 0x01;
1036 if (value == 0x00)
1037 {
1038 global.padVib0[pad] = cur;
1039 if ((global.padID[pad] & 0x0f) < (cur - 1) / 2)
1040 global.padID[pad] = (global.padID[pad] & 0xf0) + (cur - 1) / 2;
1041 }
1042 else if (value == 0x01)
1043 {
1044 global.padVib1[pad] = cur;
1045 if ((global.padID[pad] & 0x0f) < (cur - 1) / 2)
1046 global.padID[pad] = (global.padID[pad] & 0xf0) + (cur - 1) / 2;
1047 }
1048 }
1049 break;
1050 }
1051 if (cur >= global.cmdLen)
1052 return 0;
1053 return buf[global.curByte++];
1054 }
1055
1056 typedef struct
1057 {
1058 unsigned char controllerType;
1059 unsigned short buttonStatus;
1060 unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY;
1061 unsigned char moveX, moveY;
1062 unsigned char reserved[91];
1063 } PadDataS;
1064
1065 long CALLBACK PADreadPort1 (PadDataS* pads)
1066 {
1067 memset (pads, 0, sizeof (PadDataS));
1068 if ((global.padID[0] & 0xf0) == 0x40)
1069 pads->controllerType = 4;
1070 else
1071 pads->controllerType = 7;
1072 pads->buttonStatus = global.padStat[0];
1073 pads->leftJoyX = get_analog (global.config.keys[0][17]);
1074 pads->leftJoyY = get_analog (global.config.keys[0][18]);
1075 pads->rightJoyX = get_analog (global.config.keys[0][19]);
1076 pads->rightJoyY = get_analog (global.config.keys[0][20]);
1077 pads->moveX = 0;
1078 pads->moveY = 0;
1079 return 0;
1080 }
1081
1082 long CALLBACK PADreadPort2 (PadDataS* pads)
1083 {
1084 memset (pads, 0, sizeof (PadDataS));
1085 if ((global.padID[1] & 0xf0) == 0x40)
1086 pads->controllerType = 4;
1087 else
1088 pads->controllerType = 7;
1089 pads->buttonStatus = global.padStat[1];
1090 pads->leftJoyX = get_analog (global.config.keys[1][17]);
1091 pads->leftJoyY = get_analog (global.config.keys[1][18]);
1092 pads->rightJoyX = get_analog (global.config.keys[1][19]);
1093 pads->rightJoyY = get_analog (global.config.keys[1][20]);
1094 pads->moveX = 0;
1095 pads->moveY = 0;
1096 return 0;
1097 }
1098
1099 keyEvent* CALLBACK PADkeyEvent (void)
1100 {
1101 if (n_open)
1102 {
1103 memcpy (save.state[0], save.state[1], sizeof (save.state[0]));
1104 GetKeyState (save.state[1]);
1105 for (int cnt = 0; cnt < 256; cnt++)
1106 {
1107 if ((~save.state[0][cnt] & save.state[1][cnt] & 0x80) ||
1108 (save.state[0][cnt] & ~save.state[1][cnt] & 0x80))
1109 {
1110 save.ev.evt = (save.state[1][cnt] & 0x80) ? 1 : 2;
1111 save.ev.key = MapVirtualKey (cnt, 1);
1112 return &save.ev;
1113 }
1114 }
1115 }
1116 return NULL;
1117 }
1118
1119 void CALLBACK PADconfigure (void)
1120 {
1121 if (n_open == 0)
1122 {
1123 memset (&global, 0, sizeof (global));
1124 if (DialogBox (hInstance, MAKEINTRESOURCE (IDD_DIALOG1), GetActiveWindow(), (DLGPROC)ConfigureDlgProc) == IDOK)
1125 SaveConfig();
1126 ReleaseDirectInput();
1127 }
1128 }
1129
1130 void CALLBACK PADabout (void)
1131 {
1132 MessageBox (GetActiveWindow(), "Copyright (C) 2004-2006 Nagisa\nVersion 1.7.1\n\nModified by Jake Stine for PCSX2 0.9.7 compatibility.",
1133 "SSSPSX PAD plugin", MB_OK | MB_SETFOREGROUND);
1134 }
1135
1136 s32 CALLBACK PADtest (void)
1137 {
1138 return 0;
1139 }
1140
1141 void CALLBACK PADsetSettingsDir(const char* dir)
1142 {
1143 s_strIniPath = (dir==NULL) ? "inis/" : dir;
1144 }
1145
1146 // Returns 0 on success, -1 on error.
1147 s32 CALLBACK PADfreeze (int mode, freezeData *data)
1148 {
1149 switch (mode)
1150 {
1151 case FREEZE_SIZE:
1152 data->size = 0;
1153 break;
1154
1155 case FREEZE_LOAD:
1156 break;
1157
1158 case FREEZE_SAVE:
1159 break;
1160 }
1161
1162 return 0;
1163 }
1164
1165 BOOL APIENTRY DllMain(HMODULE hInst, DWORD dwReason, LPVOID lpReserved)
1166 {
1167
1168 if( dwReason == DLL_PROCESS_ATTACH )
1169 {
1170 hInstance = hInst;
1171 InitializeCriticalSection( &update_lock );
1172 InitializeCriticalSection( &init_lock );
1173 }
1174 else if( dwReason == DLL_PROCESS_DETACH )
1175 {
1176 DeleteCriticalSection( &update_lock );
1177 DeleteCriticalSection( &init_lock );
1178 }
1179
1180 return TRUE;
1181 }
1182
1183 BOOL APIENTRY EntryPoint (HMODULE hInst, DWORD dwReason, LPVOID lpReserved)
1184 {
1185 return DllMain( hInst, dwReason, lpReserved );
1186 }

  ViewVC Help
Powered by ViewVC 1.1.22