1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
18 #include <wx/msgdlg.h>
23 #include "Common.h" // Common
25 #include "pluginspecs_wiimote.h"
26 #include "StringUtil.h" // For ArrayToString
28 #include "wiimote_hid.h"
31 #include "EmuSubroutines.h"
32 #include "EmuDefinitions.h"
33 #include "Config.h" // For g_Config
35 extern SWiimoteInitialize g_WiimoteInitialize
;
41 // Variables: 0 = Wiimote, 1 = Nunchuck
42 int g_RecordingPlaying
[3]; //g_RecordingPlaying[0] = -1; g_RecordingPlaying[1] = -1;
43 int g_RecordingCounter
[3]; //g_RecordingCounter[0] = 0; g_RecordingCounter[1] = 0;
44 int g_RecordingPoint
[3]; //g_RecordingPoint[0] = 0; g_RecordingPoint[1] = 0;
45 double g_RecordingStart
[3]; //g_RecordingStart[0] = 0; g_RecordingStart[1] = 0;
46 double g_RecordingCurrentTime
[3]; //g_RecordingCurrentTime[0] = 0; g_RecordingCurrentTime[1] = 0;
48 /* Convert from -350 to -3.5 g. The Nunchuck gravity size is 51 compared to the 26 to 28 for the Wiimote.
49 So the maximum g values are higher for the Wiimote. */
50 int G2Accelerometer(int _G
, int XYZ
, int Wm
)
52 float G
= (float)_G
/ 100.0;
53 float Neutral
= 0.0, OneG
= 0.0, Accelerometer
;
58 if(Wm
== WM_RECORDING_WIIMOTE
)
60 OneG
= (float)g_wm
.cal_g
.x
;
61 Neutral
= (float)g_wm
.cal_zero
.x
;
65 OneG
= (float)g_nu
.cal_g
.x
;
66 Neutral
= (float)g_nu
.cal_zero
.x
;
70 if(Wm
== WM_RECORDING_WIIMOTE
)
72 OneG
= (float)g_wm
.cal_g
.y
;
73 Neutral
= (float)g_wm
.cal_zero
.y
;
77 OneG
= (float)g_nu
.cal_g
.y
;
78 Neutral
= (float)g_nu
.cal_zero
.y
;
82 if(Wm
== WM_RECORDING_WIIMOTE
)
84 OneG
= (float)g_wm
.cal_g
.z
;
85 Neutral
= (float)g_wm
.cal_zero
.z
;
89 OneG
= (float)g_nu
.cal_g
.z
;
90 Neutral
= (float)g_nu
.cal_zero
.z
;
93 default: PanicAlert("There is a syntax error in a function that is calling G2Accelerometer(%i, %i)", _G
, XYZ
);
96 Accelerometer
= Neutral
+ (OneG
* G
);
97 int Return
= (int)Accelerometer
;
100 //DEBUG_LOG(WIIMOTE, "G2Accelerometer():%f %f %f %f", Neutral, OneG, G, Accelerometer);
103 if (Return
> 255) Return
= 255;
104 if (Return
< 0) Return
= 0;
109 template<class IRReportType
>
110 bool RecordingPlayAccIR(u8
&_x
, u8
&_y
, u8
&_z
, IRReportType
&_IR
, int Wm
)
112 // Check if the recording is on
113 if (g_RecordingPlaying
[Wm
] == -1) return false;
115 // Return if the list is empty
116 if(VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.size() == 0)
118 g_RecordingPlaying
[Wm
] = -1;
119 DEBUG_LOG(WIIMOTE
, "Empty");
123 // Return if the playback speed is unset
124 if(VRecording
.at(g_RecordingPlaying
[Wm
]).PlaybackSpeed
< 0)
126 DEBUG_LOG(WIIMOTE
, "PlaybackSpeed empty: %i", g_RecordingPlaying
[Wm
]);
127 g_RecordingPlaying
[Wm
] = -1;
132 int IRBytes
= VRecording
.at(g_RecordingPlaying
[Wm
]).IRBytes
;
134 // Return if the IR mode is wrong
135 if (Wm
== WM_RECORDING_IR
136 && ( (IRBytes
== 12 && !(g_ReportingMode
[g_ID
] == 0x33))
137 || (IRBytes
== 10 && !(g_ReportingMode
[g_ID
] == 0x36 || g_ReportingMode
[g_ID
] == 0x37))
141 DEBUG_LOG(WIIMOTE
, "Wrong IR mode: %i", g_RecordingPlaying
[Wm
]);
142 g_RecordingPlaying
[Wm
] = -1;
147 if(g_RecordingCounter
[Wm
] == 0)
149 DEBUG_LOG(WIIMOTE
, "Begin: %i", Wm
);
150 g_RecordingStart
[Wm
] = Common::Timer::GetDoubleTime();
154 g_RecordingCurrentTime
[Wm
] = Common::Timer::GetDoubleTime() - g_RecordingStart
[Wm
];
156 // Modify the current time
157 g_RecordingCurrentTime
[Wm
] *= ((25.0 + (double)VRecording
.at(g_RecordingPlaying
[Wm
]).PlaybackSpeed
* 25.0) / 100.0);
160 for (int i
= 0; i
< (int)VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.size(); i
++)
161 if (VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.at(i
).Time
> g_RecordingCurrentTime
[Wm
])
163 g_RecordingPoint
[Wm
] = i
;
167 // Return if we are at the end of the list
168 if(g_RecordingCurrentTime
[Wm
] >=
169 VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.at(
170 VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.size() - 1).Time
)
171 // Or if we are playing back all observations regardless of time
172 //g_RecordingPoint[Wm] = g_RecordingCounter[Wm];
173 //if (g_RecordingPoint[Wm] >= VRecording.at(g_RecordingPlaying[Wm]).Recording.size())
175 g_RecordingCounter
[Wm
] = 0;
176 g_RecordingPlaying
[Wm
] = -1;
177 g_RecordingStart
[Wm
] = 0;
178 g_RecordingCurrentTime
[Wm
] = 0;
179 DEBUG_LOG(WIIMOTE
, "End: %i", Wm
);
183 // Update accelerometer values
184 _x
= G2Accelerometer(VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.at(g_RecordingPoint
[Wm
]).x
, 0, Wm
);
185 _y
= G2Accelerometer(VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.at(g_RecordingPoint
[Wm
]).y
, 1, Wm
);
186 _z
= G2Accelerometer(VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.at(g_RecordingPoint
[Wm
]).z
, 2, Wm
);
188 if(Wm
== WM_RECORDING_IR
) memcpy(&_IR
, VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.at(g_RecordingPoint
[Wm
]).IR
, IRBytes
);
190 if (g_DebugAccelerometer
)
192 //Console::ClearScreen();
193 DEBUG_LOG(WIIMOTE
, "Current time: [%i / %i] %f %f",
194 g_RecordingPoint
[Wm
], VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.size(),
195 VRecording
.at(g_RecordingPlaying
[Wm
]).Recording
.at(g_RecordingPoint
[Wm
]).Time
, g_RecordingCurrentTime
[Wm
]
197 DEBUG_LOG(WIIMOTE
, "Accel x, y, z: %03u %03u %03u", _x
, _y
, _z
);
199 //DEBUG_LOG(WIIMOTE, "Accel x, y, z: %03u %03u %03u", _x, _y, _z);
201 g_RecordingCounter
[Wm
]++;
206 /* Because the playback is neatly controlled by RecordingPlayAccIR() we use these functions to be able to
207 use RecordingPlayAccIR() for both accelerometer and IR recordings */
208 bool RecordingPlay(u8
&_x
, u8
&_y
, u8
&_z
, int Wm
)
211 return RecordingPlayAccIR(_x
, _y
, _z
, IR
, Wm
);
214 template<class IRReportType
>
215 bool RecordingPlayIR(IRReportType
&_IR
)
218 return RecordingPlayAccIR(x
, y
, z
, _IR
, 2);
221 // Return true if this particual numerical key is pressed
222 bool IsNumericalKeyPressed(int _Key
)
225 // Check which key it is
226 std::string TmpKey
= StringFromFormat("%i", _Key
);
227 if(GetAsyncKeyState(TmpKey
[0]))
230 // That numerical key is pressed
238 // Check if a switch is pressed
239 bool IsSwitchPressed(int _Key
)
242 // Check if that switch is pressed
245 case 0: if (GetAsyncKeyState(VK_SHIFT
)) return true;
246 case 1: if (GetAsyncKeyState(VK_CONTROL
)) return true;
247 case 2: if (GetAsyncKeyState(VK_MENU
)) return true;
250 // That switch was not pressed
258 // Check if we should start the playback of a recording. Once it has been started it can currently
259 // not be stopped, it will always run to the end of the recording.
260 int RecordingCheckKeys(int WmNuIr
)
263 //DEBUG_LOG(WIIMOTE, "RecordingCheckKeys: %i", Wiimote);
265 // Check if we have a HotKey match
268 for(int i
= 0; i
< RECORDING_ROWS
; i
++)
270 // Check all ten numerical keys
271 for(int j
= 0; j
< 10; j
++)
273 if ((VRecording
.at(i
).HotKeyWiimote
== j
&& WmNuIr
== 0 && IsNumericalKeyPressed(j
)
274 || VRecording
.at(i
).HotKeyNunchuck
== j
&& WmNuIr
== 1 && IsNumericalKeyPressed(j
)
275 || VRecording
.at(i
).HotKeyIR
== j
&& WmNuIr
== 2 && IsNumericalKeyPressed(j
))
276 && (IsSwitchPressed(VRecording
.at(i
).HotKeySwitch
) || VRecording
.at(i
).HotKeySwitch
== 3))
278 //DEBUG_LOG(WIIMOTE, "Match: %i %i", i, Key);
286 // Return nothing if we don't have a match
287 if (!Match
) return -1;
297 // Multi System Input Status Check
302 if (WiiMapping
[g_ID
].Source
== 1)
304 int MapKey
= WiiMapping
[g_ID
].Button
[Key
];
309 Ret
= GetAsyncKeyState(MapKey
); // Keyboard (Windows)
311 else if (MapKey
< 0x1100)
312 #elif defined(HAVE_X11) && HAVE_X11
313 if (MapKey
< 256 || MapKey
>= 0xf000)
317 XQueryKeymap(WMdisplay
, keys
);
318 keyCode
= XKeysymToKeycode(WMdisplay
, MapKey
);
319 Ret
= (keys
[keyCode
/8] & (1 << (keyCode
%8))); // Keyboard (Linux)
321 else if (MapKey
< 0x1100)
326 Ret
= SDL_JoystickGetButton(WiiMapping
[g_ID
].joy
, MapKey
- 0x1000); // Pad button
331 HatCode
= SDL_JoystickGetHat(WiiMapping
[g_ID
].joy
, (MapKey
- 0x1100) / 0x0010);
332 HatKey
= (MapKey
- 0x1100) % 0x0010;
334 if (HatCode
& HatKey
)
339 if ((Key
== EWM_SHAKE
&& GetAsyncKeyState(VK_MBUTTON
))
340 || (Key
== EWM_A
&& GetAsyncKeyState(VK_LBUTTON
))
341 || (Key
== EWM_B
&& GetAsyncKeyState(VK_RBUTTON
)))
345 Ret
= !(x
< 0 || x
> 1 || y
< 0 || y
> 1);
348 #if defined(HAVE_X11) && HAVE_X11
349 if (Key
== EWM_SHAKE
|| Key
== EWM_A
|| Key
== EWM_B
)
351 Window GLWin
= *(Window
*)g_WiimoteInitialize
.pXWindow
;
352 int root_x
, root_y
, win_x
, win_y
;
353 Window rootDummy
, childWin
;
355 XQueryPointer(WMdisplay
, GLWin
, &rootDummy
, &childWin
, &root_x
, &root_y
, &win_x
, &win_y
, &mask
);
356 if (((Key
== EWM_A
) && (mask
& Button1Mask
))
357 || ((Key
== EWM_B
) && (mask
& Button3Mask
))
358 || ((Key
== EWM_SHAKE
) && (mask
& Button3Mask
)))
362 Ret
= !(x
< 0 || x
> 1 || y
< 0 || y
> 1);
368 return (Ret
) ? true : false;
371 // Wiimote core buttons
372 void FillReportInfo(wm_core
& _core
)
374 // Check that Dolphin is in focus
375 if (!IsFocus()) return;
378 if (WiiMapping
[g_ID
].UDPWM
.instance
)
379 WiiMapping
[g_ID
].UDPWM
.instance
->update();
381 if ((WiiMapping
[g_ID
].UDPWM
.instance
)&&(WiiMapping
[g_ID
].UDPWM
.enableButtons
))
382 mask
=WiiMapping
[g_ID
].UDPWM
.instance
->getButtons();
384 // Allow both mouse buttons and keyboard to press a and b
385 _core
.a
= IsKey(EWM_A
)||(mask
&UDPWM_BA
);
386 _core
.b
= IsKey(EWM_B
)||(mask
&UDPWM_BB
);
387 _core
.one
= IsKey(EWM_ONE
)||(mask
&UDPWM_B1
);
388 _core
.two
= IsKey(EWM_TWO
)||(mask
&UDPWM_B2
);
389 _core
.plus
= IsKey(EWM_P
)||(mask
&UDPWM_BP
);
390 _core
.minus
= IsKey(EWM_M
)||(mask
&UDPWM_BM
);
391 _core
.home
= IsKey(EWM_H
)||(mask
&UDPWM_BH
);
393 /* Sideways controls (for example for Wario Land) if the Wiimote is intended to be held sideways */
394 if(WiiMapping
[g_ID
].bSideways
)
396 _core
.left
= IsKey(EWM_D
)||(mask
&UDPWM_BL
);
397 _core
.up
= IsKey(EWM_L
)||(mask
&UDPWM_BU
);
398 _core
.right
= IsKey(EWM_U
)||(mask
&UDPWM_BR
);
399 _core
.down
= IsKey(EWM_R
)||(mask
&UDPWM_BU
);
403 _core
.left
= IsKey(EWM_L
)||(mask
&UDPWM_BL
);
404 _core
.up
= IsKey(EWM_U
)||(mask
&UDPWM_BU
);
405 _core
.right
= IsKey(EWM_R
)||(mask
&UDPWM_BR
);
406 _core
.down
= IsKey(EWM_D
)||(mask
&UDPWM_BD
);
410 void FillReportAcc(wm_accel
& _acc
)
412 // Recorded movements
413 // Check for a playback command
414 if (g_RecordingPlaying
[0] < 0)
416 g_RecordingPlaying
[0] = RecordingCheckKeys(0);
420 // If the recording reached the end or failed somehow we will not return
421 if (RecordingPlay(_acc
.x
, _acc
.y
, _acc
.z
, 0))
423 //DEBUG_LOG(WIIMOTE, "X, Y, Z: %u %u %u", _acc.x, _acc.y, _acc.z);
427 _acc
.x
= g_wm
.cal_zero
.x
;
428 _acc
.y
= g_wm
.cal_zero
.y
;
429 _acc
.z
= g_wm
.cal_zero
.z
;
431 // Adjust position, also add some noise to prevent disconnection
432 if (!WiiMapping
[g_ID
].bUpright
)
433 _acc
.z
+= g_wm
.cal_g
.z
+ WiiMapping
[g_ID
].Motion
.TiltWM
.FakeNoise
;
434 else // Upright wiimote
435 _acc
.y
-= g_wm
.cal_g
.y
+ WiiMapping
[g_ID
].Motion
.TiltWM
.FakeNoise
;
437 WiiMapping
[g_ID
].Motion
.TiltWM
.FakeNoise
= -WiiMapping
[g_ID
].Motion
.TiltWM
.FakeNoise
;
445 if ((WiiMapping
[g_ID
].UDPWM
.instance
&& WiiMapping
[g_ID
].UDPWM
.enableButtons
446 && (WiiMapping
[g_ID
].UDPWM
.instance
->getButtons() & UDPWM_SK
))
447 || (IsKey(EWM_SHAKE
) && !WiiMapping
[g_ID
].Motion
.TiltWM
.Shake
))
448 WiiMapping
[g_ID
].Motion
.TiltWM
.Shake
= 1;
450 // Step the shake simulation one step
451 ShakeToAccelerometer(acc_x
, acc_y
, acc_z
, WiiMapping
[g_ID
].Motion
.TiltWM
);
453 // Tilt Wiimote, allow the shake function to interrupt it
454 if (!WiiMapping
[g_ID
].Motion
.TiltWM
.Shake
)
455 TiltWiimote(acc_x
, acc_y
, acc_z
);
458 if (acc_x
> 0xFF) acc_x
= 0xFF;
459 else if (acc_x
< 0x00) acc_x
= 0x00;
460 if (acc_y
> 0xFF) acc_y
= 0xFF;
461 else if (acc_y
< 0x00) acc_y
= 0x00;
462 if (acc_z
> 0xFF) acc_z
= 0xFF;
463 else if (acc_z
< 0x00) acc_z
= 0x00;
470 // Debugging for translating Wiimote to Keyboard (or Gamepad)
473 // Toogle console display
474 if(GetAsyncKeyState('U'))
476 if(consoleDisplay < 2)
482 if(GetAsyncKeyState('5'))
484 else if(GetAsyncKeyState('6'))
486 if(GetAsyncKeyState('7'))
488 else if(GetAsyncKeyState('8'))
490 if(GetAsyncKeyState('9'))
492 else if(GetAsyncKeyState('0'))
495 else if(GetAsyncKeyState(VK_NUMPAD3))
497 else if(GetAsyncKeyState(VK_NUMPAD6))
499 else if(GetAsyncKeyState(VK_ADD))
501 else if(GetAsyncKeyState(VK_SUBTRACT))
505 if(GetAsyncKeyState(VK_INSERT))
507 else if(GetAsyncKeyState(VK_DELETE))
509 else if(GetAsyncKeyState(VK_HOME))
511 else if(GetAsyncKeyState(VK_END))
513 else if(GetAsyncKeyState(VK_SHIFT))
515 else if(GetAsyncKeyState(VK_CONTROL))
518 if(GetAsyncKeyState(VK_NUMPAD1))
520 else if(GetAsyncKeyState(VK_NUMPAD2))
522 if(GetAsyncKeyState(VK_NUMPAD4))
524 else if(GetAsyncKeyState(VK_NUMPAD5))
526 if(GetAsyncKeyState(VK_NUMPAD7))
528 else if(GetAsyncKeyState(VK_NUMPAD8))
531 //if(consoleDisplay == 0)
532 DEBUG_LOG(WIIMOTE, "x: %03i | y: %03i | z: %03i | A:%i B:%i C:%i a:%i b:%i c:%i d:%i X:%i Y:%i Z:%i",
533 _acc.x, _acc.y, _acc.z,
538 DEBUG_LOG(WIIMOTE, "x: %03i | y: %03i | z: %03i | X:%i Y:%i Z:%i | AX:%i AY:%i AZ:%i ",
539 _acc.x, _acc.y, _acc.z,
545 // The extended 12 byte (3 byte per object) reporting
546 void FillReportIR(wm_ir_extended
& _ir0
, wm_ir_extended
& _ir1
)
548 // Recorded movements
549 // Check for a playback command
550 if(g_RecordingPlaying
[2] < 0)
552 g_RecordingPlaying
[2] = RecordingCheckKeys(2);
556 //DEBUG_LOG(WIIMOTE, "X, Y, Z: %u %u %u", _acc.x, _acc.y, _acc.z);
557 if (RecordingPlayIR(_ir0
)) return;
560 /* Fill with 0xff if empty. The real Wiimote seems to use 0xff when it
561 doesn't see a certain point, at least from how WiiMoteReal::SendEvent()
563 memset(&_ir0
, 0xff, sizeof(wm_ir_extended
));
564 memset(&_ir1
, 0xff, sizeof(wm_ir_extended
));
566 float MouseX
, MouseY
;
567 if ((WiiMapping
[g_ID
].UDPWM
.instance
)&&(WiiMapping
[g_ID
].UDPWM
.enableIR
))
568 WiiMapping
[g_ID
].UDPWM
.instance
->getIR(MouseX
,MouseY
);
570 GetMousePos(MouseX
, MouseY
);
572 // If we are outside the screen leave the values at 0xff
573 if(MouseX
> 1 || MouseX
< 0 || MouseY
> 1 || MouseY
< 0) return;
575 // Position calculation
576 int y0
= g_Config
.iIRTop
+ g_Config
.iIRHeight
* MouseY
;
579 // The distance between the x positions are two sensor bar radii
580 int x0
= 1023 - g_Config
.iIRLeft
- g_Config
.iIRWidth
* MouseX
- SENSOR_BAR_WIDTH
/ 2;
581 int x1
= x0
+ SENSOR_BAR_WIDTH
;
583 RotateIRDot(x0
, y0
, WiiMapping
[g_ID
].Motion
.TiltWM
);
584 RotateIRDot(x1
, y1
, WiiMapping
[g_ID
].Motion
.TiltWM
);
586 // Converted to IR data
587 _ir0
.x
= x0
& 0xff; _ir0
.xHi
= x0
>> 8;
588 _ir0
.y
= y0
& 0xff; _ir0
.yHi
= y0
>> 8;
590 _ir1
.x
= x1
& 0xff; _ir1
.xHi
= x1
>> 8;
591 _ir1
.y
= y1
& 0xff; _ir1
.yHi
= y1
>> 8;
593 // The size can be between 0 and 15 and is probably not important
597 // Debugging for calibration
599 if(!GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_RIGHT))
601 else if(GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_RIGHT))
603 if(!GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_LEFT))
605 else if(GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_LEFT))
607 if(!GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_UP))
609 else if(GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_UP))
611 if(!GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_DOWN))
613 else if(GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_DOWN))
615 if(!GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_NUMPAD0))
616 SensorBarRadius += 1;
617 else if(GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_NUMPAD0))
618 SensorBarRadius -= 1;
620 //Console::ClearScreen();
621 //if(consoleDisplay == 1)
622 DEBUG_LOG(WIIMOTE, "x0:%03i x1:%03i y0:%03i y1:%03i | T:%i L:%i R:%i B:%i S:%i",
623 x0, x1, y0, y1, Top, Left, Right, Bottom, SensorBarRadius
627 // The 10 byte reporting used when an extension is connected
628 void FillReportIRBasic(wm_ir_basic
& _ir0
, wm_ir_basic
& _ir1
)
630 // Recorded movements
631 // Check for a playback command
632 if(g_RecordingPlaying
[2] < 0)
634 g_RecordingPlaying
[2] = RecordingCheckKeys(2);
636 // We are playing back a recording, we don't accept any manual input this time
639 //DEBUG_LOG(WIIMOTE, "X, Y, Z: %u %u %u", _acc.x, _acc.y, _acc.z);
640 if (RecordingPlayIR(_ir0
)) return;
643 // Fill with 0xff if empty
644 memset(&_ir0
, 0xff, sizeof(wm_ir_basic
));
645 memset(&_ir1
, 0xff, sizeof(wm_ir_basic
));
647 float MouseX
, MouseY
;
648 if ((WiiMapping
[g_ID
].UDPWM
.instance
)&&(WiiMapping
[g_ID
].UDPWM
.enableIR
))
649 WiiMapping
[g_ID
].UDPWM
.instance
->getIR(MouseX
,MouseY
);
651 GetMousePos(MouseX
, MouseY
);
653 // If we are outside the screen leave the values at 0xff
654 if(MouseX
> 1 || MouseX
< 0 || MouseY
> 1 || MouseY
< 0) return;
656 int y1
= g_Config
.iIRTop
+ g_Config
.iIRHeight
* MouseY
;
659 int x1
= 1023 - g_Config
.iIRLeft
- g_Config
.iIRWidth
* MouseX
- SENSOR_BAR_WIDTH
/ 2;
660 int x2
= x1
+ SENSOR_BAR_WIDTH
;
662 RotateIRDot(x1
, y1
, WiiMapping
[g_ID
].Motion
.TiltWM
);
663 RotateIRDot(x2
, y2
, WiiMapping
[g_ID
].Motion
.TiltWM
);
665 /* As with the extented report we settle with emulating two out of four
666 possible objects the only difference is that we don't report any size of
667 the tracked object here */
669 _ir0
.x1
= x1
& 0xff; _ir0
.x1Hi
= (x1
>> 8); // we are dealing with 2 bit values here
670 _ir0
.y1
= y1
& 0xff; _ir0
.y1Hi
= (y1
>> 8);
672 _ir0
.x2
= x2
& 0xff; _ir0
.x2Hi
= (x2
>> 8);
673 _ir0
.y2
= y2
& 0xff; _ir0
.y2Hi
= (y2
>> 8);
675 // Debugging for calibration
677 if(GetAsyncKeyState(VK_NUMPAD1))
679 else if(GetAsyncKeyState(VK_NUMPAD2))
681 if(GetAsyncKeyState(VK_NUMPAD4))
683 else if(GetAsyncKeyState(VK_NUMPAD5))
685 if(GetAsyncKeyState(VK_NUMPAD7))
687 else if(GetAsyncKeyState(VK_NUMPAD8))
689 if(GetAsyncKeyState(VK_NUMPAD6))
691 else if(GetAsyncKeyState(VK_NUMPAD3))
693 if(GetAsyncKeyState(VK_INSERT))
694 SensorBarRadius += 1;
695 else if(GetAsyncKeyState(VK_DELETE))
696 SensorBarRadius -= 1;
699 //if(consoleDisplay == 1)
701 DEBUG_LOG(WIIMOTE, "x1:%03i x2:%03i y1:%03i y2:%03i irx1:%02x y1:%02x x2:%02x y2:%02x | T:%i L:%i R:%i B:%i S:%i",
702 x1, x2, y1, y2, _ir0.x1, _ir0.y1, _ir1.x2, _ir1.y2, Top, Left, Right, Bottom, SensorBarRadius
704 DEBUG_LOG(WIIMOTE, "");
705 DEBUG_LOG(WIIMOTE, "ir0.x1:%02x x1h:%02x x2:%02x x2h:%02x | ir0.y1:%02x y1h:%02x y2:%02x y2h:%02x | ir1.x1:%02x x1h:%02x x2:%02x x2h:%02x | ir1.y1:%02x y1h:%02x y2:%02x y2h:%02x",
706 _ir0.x1, _ir0.x1Hi, _ir0.x2, _ir0.x2Hi,
707 _ir0.y1, _ir0.y1Hi, _ir0.y2, _ir0.y2Hi,
708 _ir1.x1, _ir1.x1Hi, _ir1.x2, _ir1.x2Hi,
709 _ir1.y1, _ir1.y1Hi, _ir1.y2, _ir1.y2Hi
711 // ------------------
715 /* Generate the 6 byte extension report for the Nunchuck, encrypted. The bytes
716 are JX JY AX AY AZ BT. */
717 void FillReportExtension(wm_extension
& _ext
)
719 // Recorded movements
720 // Check for a playback command
721 if(g_RecordingPlaying
[1] < 0)
723 g_RecordingPlaying
[1] = RecordingCheckKeys(1);
727 // We should not play back the accelerometer values
728 if (RecordingPlay(_ext
.ax
, _ext
.ay
, _ext
.az
, 1))
732 // The default joystick and button values unless we use them
733 _ext
.jx
= g_nu
.jx
.center
;
734 _ext
.jy
= g_nu
.jy
.center
;
735 _ext
.bt
= 0x03; // 0x03 means no button pressed, the button is zero active
737 // Use the neutral values
738 _ext
.ax
= g_nu
.cal_zero
.x
;
739 _ext
.ay
= g_nu
.cal_zero
.y
;
740 _ext
.az
= g_nu
.cal_zero
.z
+ g_nu
.cal_g
.z
;
748 if (IsKey(ENC_SHAKE
) && !WiiMapping
[g_ID
].Motion
.TiltNC
.Shake
)
749 WiiMapping
[g_ID
].Motion
.TiltNC
.Shake
= 1;
751 // Step the shake simulation one step
752 ShakeToAccelerometer(acc_x
, acc_y
, acc_z
, WiiMapping
[g_ID
].Motion
.TiltNC
);
754 // Tilt Nunchuck, allow the shake function to interrupt it
755 if (!WiiMapping
[g_ID
].Motion
.TiltNC
.Shake
)
756 TiltNunchuck(acc_x
, acc_y
, acc_z
);
759 if (acc_x
> 0xFF) acc_x
= 0xFF;
760 else if (acc_x
< 0x00) acc_x
= 0x00;
761 if (acc_y
> 0xFF) acc_y
= 0xFF;
762 else if (acc_y
< 0x00) acc_y
= 0x00;
763 if (acc_z
> 0xFF) acc_z
= 0xFF;
764 else if (acc_z
< 0x00) acc_z
= 0x00;
770 if ((WiiMapping
[g_ID
].UDPWM
.instance
)&&(WiiMapping
[g_ID
].UDPWM
.enableNunchuck
))
774 WiiMapping
[g_ID
].UDPWM
.instance
->getNunchuck(x
,y
,b
);
775 //NOTICE_LOG(WIIMOTE,"%f %f %x",x,y,b);
777 int factNeg
= + g_nu
.jx
.center
- g_nu
.jx
.min
;
778 int factPoz
= - g_nu
.jx
.center
+ g_nu
.jx
.max
;
779 if (x
==0) _ext
.jx
=g_nu
.jx
.center
;
780 if (x
>0) _ext
.jx
=(int)(x
*factPoz
+g_nu
.jx
.center
);
781 if (x
<0) _ext
.jx
=(int)(x
*factNeg
+g_nu
.jx
.center
);
783 factNeg
= + g_nu
.jy
.center
- g_nu
.jy
.min
;
784 factPoz
= - g_nu
.jy
.center
+ g_nu
.jy
.max
;
785 if (y
==0) _ext
.jy
=g_nu
.jy
.center
;
786 if (y
>0) _ext
.jy
=(int)(y
*factPoz
+g_nu
.jy
.center
);
787 if (y
<0) _ext
.jy
=(int)(y
*factNeg
+g_nu
.jy
.center
);
789 if(IsKey(ENC_C
)||(b
&UDPWM_NC
)) _ext
.bt
&= ~0x02;
790 if(IsKey(ENC_Z
)||(b
&UDPWM_NZ
)) _ext
.bt
&= ~0x01;
793 // Update the analog stick
794 if (WiiMapping
[g_ID
].Stick
.NC
== FROM_KEYBOARD
)
796 // Set the max values to the current calibration values
797 if(IsKey(ENC_L
)) // x
798 _ext
.jx
= g_nu
.jx
.min
;
800 _ext
.jx
= g_nu
.jx
.max
;
802 if(IsKey(ENC_D
)) // y
803 _ext
.jy
= g_nu
.jy
.min
;
805 _ext
.jy
= g_nu
.jy
.max
;
807 // On a real stick, the initialization value of center is 0x80,
808 // but after a first time touch, the center value automatically changes to 0x7F
809 if(_ext
.jx
!= g_nu
.jx
.center
)
810 g_nu
.jx
.center
= 0x7F;
811 if(_ext
.jy
!= g_nu
.jy
.center
)
812 g_nu
.jy
.center
= 0x7F;
816 // Get adjusted pad state values
817 int _Lx
= WiiMapping
[g_ID
].AxisState
.Lx
;
818 int _Ly
= WiiMapping
[g_ID
].AxisState
.Ly
;
819 int _Rx
= WiiMapping
[g_ID
].AxisState
.Rx
;
820 int _Ry
= WiiMapping
[g_ID
].AxisState
.Ry
;
822 // The Y-axis is inverted
826 /* This is if we are also using a real Nunchuck that we are sharing the
827 calibration with. It's not needed if we are using our default
828 values. We adjust the values to the configured range, we even allow
829 the center to not be 0x80. */
830 if(g_nu
.jx
.max
!= 0xff || g_nu
.jy
.max
!= 0xff
831 || g_nu
.jx
.min
!= 0 || g_nu
.jy
.min
!= 0
832 || g_nu
.jx
.center
!= 0x80 || g_nu
.jy
.center
!= 0x80)
834 float Lx
= (float)_Lx
;
835 float Ly
= (float)_Ly
;
836 float Rx
= (float)_Rx
;
837 float Ry
= (float)_Ry
;
838 //float Tl = (float)_Tl;
839 //float Tr = (float)_Tr;
841 float XRangePos
= (float) (g_nu
.jx
.max
- g_nu
.jx
.center
);
842 float XRangeNeg
= (float) (g_nu
.jx
.center
- g_nu
.jx
.min
);
843 float YRangePos
= (float) (g_nu
.jy
.max
- g_nu
.jy
.center
);
844 float YRangeNeg
= (float) (g_nu
.jy
.center
- g_nu
.jy
.min
);
845 if (Lx
> 0x80) Lx
= Lx
* (XRangePos
/ 128.0);
846 if (Lx
< 0x80) Lx
= Lx
* (XRangeNeg
/ 128.0);
847 if (Lx
== 0x80) Lx
= (float)g_nu
.jx
.center
;
848 if (Ly
> 0x80) Ly
= Ly
* (YRangePos
/ 128.0);
849 if (Ly
< 0x80) Ly
= Ly
* (YRangeNeg
/ 128.0);
850 if (Ly
== 0x80) Lx
= (float)g_nu
.jy
.center
;
856 if (_Lx
> 0xff) _Lx
= 0xff; if (_Lx
< 0) _Lx
= 0;
857 if (_Rx
> 0xff) _Rx
= 0xff; if (_Rx
< 0) _Rx
= 0;
858 if (_Ly
> 0xff) _Ly
= 0xff; if (_Ly
< 0) _Ly
= 0;
859 if (_Ry
> 0xff) _Ry
= 0xff; if (_Ry
< 0) _Ry
= 0;
862 if (WiiMapping
[g_ID
].Stick
.NC
== FROM_ANALOG1
)
874 if(IsKey(ENC_C
)) _ext
.bt
&= ~0x02;
875 if(IsKey(ENC_Z
)) _ext
.bt
&= ~0x01;
879 /* Here we encrypt the report */
881 // Create a temporary storage for the data
882 u8 Tmp
[sizeof(_ext
)];
883 // Clear the array by copying zeroes to it
884 memset(Tmp
, 0, sizeof(_ext
));
885 // Copy the data to it
886 memcpy(Tmp
, &_ext
, sizeof(_ext
));
888 wiimote_encrypt(&g_ExtKey
[g_ID
], Tmp
, 0x00, sizeof(_ext
));
889 // Write it back to the struct
890 memcpy(&_ext
, Tmp
, sizeof(_ext
));
894 /* Generate the 6 byte extension report for the Classic Controller, encrypted.
896 void FillReportClassicExtension(wm_classic_extension
& _ext
)
898 /* These are the default neutral values for the analog triggers and sticks */
899 u8 Rx
= g_ClassicContCalibration
.Rx
.center
, Ry
= g_ClassicContCalibration
.Ry
.center
,
900 Lx
= g_ClassicContCalibration
.Lx
.center
, Ly
= g_ClassicContCalibration
.Ly
.center
,
901 lT
= g_ClassicContCalibration
.Tl
.neutral
, rT
= g_ClassicContCalibration
.Tl
.neutral
;
903 _ext
.b1
.padding
= 0x01; // 0x01 means not pressed
921 // Check that Dolphin is in focus
924 /* Left and right analog sticks and analog triggers
936 We use a 200 range (28 to 228) for the left analog stick and a 176 range
937 (40 to 216) for the right analog stick to match our calibration values
938 in classic_calibration
941 // Update the left analog stick
942 if (WiiMapping
[g_ID
].Stick
.CCL
== FROM_KEYBOARD
)
944 if(IsKey(ECC_Ll
)) // Left analog left
945 Lx
= g_ClassicContCalibration
.Lx
.min
;
946 if(IsKey(ECC_Lr
)) // right
947 Lx
= g_ClassicContCalibration
.Lx
.max
;
948 if(IsKey(ECC_Lu
)) // up
949 Ly
= g_ClassicContCalibration
.Ly
.max
;
950 if(IsKey(ECC_Ld
)) // down
951 Ly
= g_ClassicContCalibration
.Ly
.min
;
953 // On a real stick, the initialization value of center is 0x80,
954 // but after a first time touch, the center value automatically changes to 0x7F
955 if(Lx
!= g_ClassicContCalibration
.Lx
.center
)
956 g_ClassicContCalibration
.Lx
.center
= 0x7F;
957 if(Ly
!= g_ClassicContCalibration
.Ly
.center
)
958 g_ClassicContCalibration
.Ly
.center
= 0x7F;
962 // Get adjusted pad state values
963 int _Lx
= WiiMapping
[g_ID
].AxisState
.Lx
;
964 int _Ly
= WiiMapping
[g_ID
].AxisState
.Ly
;
965 int _Rx
= WiiMapping
[g_ID
].AxisState
.Rx
;
966 int _Ry
= WiiMapping
[g_ID
].AxisState
.Ry
;
968 // The Y-axis is inverted
972 /* This is if we are also using a real Classic Controller that we
973 are sharing the calibration with. It's not needed if we are
974 using our default values. We adjust the values to the configured
977 Status: Not added, we are not currently sharing the calibration
978 with the real Classic Controller
981 if (WiiMapping
[g_ID
].Stick
.CCL
== FROM_ANALOG1
)
993 // Update the right analog stick
994 if (WiiMapping
[g_ID
].Stick
.CCR
== FROM_KEYBOARD
)
996 if(IsKey(ECC_Rl
)) // Right analog left
997 Rx
= g_ClassicContCalibration
.Rx
.min
;
998 if(IsKey(ECC_Rr
)) // right
999 Rx
= g_ClassicContCalibration
.Rx
.max
;
1000 if(IsKey(ECC_Ru
)) // up
1001 Ry
= g_ClassicContCalibration
.Ry
.max
;
1002 if(IsKey(ECC_Rd
)) // down
1003 Ry
= g_ClassicContCalibration
.Ry
.min
;
1005 // On a real stick, the initialization value of center is 0x80,
1006 // but after a first time touch, the center value automatically changes to 0x7F
1007 if(Rx
!= g_ClassicContCalibration
.Rx
.center
)
1008 g_ClassicContCalibration
.Rx
.center
= 0x7F;
1009 if(Ry
!= g_ClassicContCalibration
.Ry
.center
)
1010 g_ClassicContCalibration
.Ry
.center
= 0x7F;
1014 // Get adjusted pad state values
1015 int _Lx
= WiiMapping
[g_ID
].AxisState
.Lx
;
1016 int _Ly
= WiiMapping
[g_ID
].AxisState
.Ly
;
1017 int _Rx
= WiiMapping
[g_ID
].AxisState
.Rx
;
1018 int _Ry
= WiiMapping
[g_ID
].AxisState
.Ry
;
1020 // The Y-axis is inverted
1024 /* This is if we are also using a real Classic Controller that we
1025 are sharing the calibration with. It's not needed if we are
1026 using our default values. We adjust the values to the configured
1029 Status: Not added, we are not currently sharing the calibration
1030 with the real Classic Controller
1033 if (WiiMapping
[g_ID
].Stick
.CCR
== FROM_ANALOG1
)
1045 // Update the left and right analog triggers
1046 if (WiiMapping
[g_ID
].Stick
.CCT
== FROM_KEYBOARD
)
1048 if(IsKey(ECC_Tl
)) // analog left trigger
1049 { _ext
.b1
.bLT
= 0x00; lT
= 0x1f; }
1050 if(IsKey(ECC_Tr
)) // analog right trigger
1051 { _ext
.b1
.bRT
= 0x00; rT
= 0x1f; }
1053 else // g_Config.ClassicController.TRIGGER
1055 // Get adjusted pad state values
1056 int _Tl
= WiiMapping
[g_ID
].AxisState
.Tl
;
1057 int _Tr
= WiiMapping
[g_ID
].AxisState
.Tr
;
1059 /* This is if we are also using a real Classic Controller that we
1060 are sharing the calibration with. It's not needed if we are
1061 using our default values. We adjust the values to the configured
1064 Status: Not added, we are not currently sharing the calibration
1065 with the real Classic Controller
1068 // Check if the trigger is fully pressed, then update the digital
1069 // trigger values to
1070 if (_Tl
== 0xff) _ext
.b1
.bLT
= 0x00;
1071 if (_Tr
== 0xff) _ext
.b1
.bRT
= 0x00;
1073 // These can be copied directly, the bitshift further down fix this
1090 if(IsKey(ECC_Dl
)) _ext
.b2
.bdL
= 0x00; // Digital left
1091 if(IsKey(ECC_Du
)) _ext
.b2
.bdU
= 0x00; // Up
1092 if(IsKey(ECC_Dr
)) _ext
.b1
.bdR
= 0x00; // Right
1093 if(IsKey(ECC_Dd
)) _ext
.b1
.bdD
= 0x00; // Down
1111 if(IsKey(ECC_A
)) _ext
.b2
.bA
= 0x00;
1112 if(IsKey(ECC_B
)) _ext
.b2
.bB
= 0x00;
1113 if(IsKey(ECC_Y
)) _ext
.b2
.bY
= 0x00;
1114 if(IsKey(ECC_X
)) _ext
.b2
.bX
= 0x00;
1115 if(IsKey(ECC_P
)) _ext
.b1
.bP
= 0x00;
1116 if(IsKey(ECC_M
)) _ext
.b1
.bM
= 0x00;
1117 if(IsKey(ECC_H
)) _ext
.b1
.bH
= 0x00;
1118 if(IsKey(ECC_Zl
)) _ext
.b2
.bZL
= 0x00;
1119 if(IsKey(ECC_Zr
)) _ext
.b2
.bZR
= 0x00;
1121 // All buttons pressed
1122 //if(GetAsyncKeyState('C') && GetAsyncKeyState('Z'))
1123 // { _ext.b2.bA = 0x01; _ext.b2.bB = 0x01; }
1126 // Convert data for reporting
1127 _ext
.Lx
= (Lx
>> 2);
1128 _ext
.Ly
= (Ly
>> 2);
1130 _ext
.Rx
= (Rx
>> 3) & 0x01;
1131 // 5 bit to the next 2 bit
1132 _ext
.Rx2
= ((Rx
>> 3) >> 1) & 0x03;
1133 // 5 bit to the next 2 bit
1134 _ext
.Rx3
= ((Rx
>> 3) >> 3) & 0x03;
1135 _ext
.Ry
= (Ry
>> 3);
1137 _ext
.lT
= (lT
>> 3) & 0x07;
1138 // 5 bit to the highest two bits
1139 _ext
.lT2
= (lT
>> 3) >> 3;
1140 _ext
.rT
= (rT
>> 3);
1142 /* Here we encrypt the report */
1143 // Create a temporary storage for the data
1144 u8 Tmp
[sizeof(_ext
)];
1145 // Clear the array by copying zeroes to it
1146 memset(Tmp
, 0, sizeof(_ext
));
1147 // Copy the data to it
1148 memcpy(Tmp
, &_ext
, sizeof(_ext
));
1150 wiimote_encrypt(&g_ExtKey
[g_ID
], Tmp
, 0x00, sizeof(_ext
));
1151 // Write it back to the struct
1152 memcpy(&_ext
, Tmp
, sizeof(_ext
));
1155 /* Generate the 6 byte extension report for the GH3 Controller, encrypted.
1156 The bytes are ... */
1157 void FillReportGuitarHero3Extension(wm_GH3_extension
& _ext
)
1159 // u8 TB : 5; // not used in GH3
1161 u8 SX
= g_GH3Calibration
.Lx
.center
, SY
= g_GH3Calibration
.Ly
.center
;
1183 // Check that Dolphin is in focus
1186 // Update the left analog stick
1187 if (WiiMapping
[g_ID
].Stick
.GH
== FROM_KEYBOARD
)
1189 if(IsKey(EGH_Al
)) // Left analog left
1190 _ext
.SX
= g_GH3Calibration
.Lx
.min
;
1191 if(IsKey(EGH_Ar
)) // right
1192 _ext
.SX
= g_GH3Calibration
.Lx
.max
;
1193 if(IsKey(EGH_Au
)) // up
1194 _ext
.SY
= g_GH3Calibration
.Ly
.max
;
1195 if(IsKey(EGH_Ad
)) // down
1196 _ext
.SY
= g_GH3Calibration
.Ly
.min
;
1200 // Get adjusted pad state values
1201 int _Lx
= WiiMapping
[g_ID
].AxisState
.Lx
;
1202 int _Ly
= WiiMapping
[g_ID
].AxisState
.Ly
;
1203 int _Rx
= WiiMapping
[g_ID
].AxisState
.Rx
;
1204 int _Ry
= WiiMapping
[g_ID
].AxisState
.Ry
;
1206 // The Y-axis is inverted
1210 if (WiiMapping
[g_ID
].Stick
.GH
== FROM_ANALOG1
)
1222 if(IsKey(EGH_Yellow
)) _ext
.Yellow
= 0;
1223 if(IsKey(EGH_Green
)) _ext
.Green
= 0;
1224 if(IsKey(EGH_Blue
)) _ext
.Blue
= 0;
1225 if(IsKey(EGH_Red
)) _ext
.Red
= 0;
1226 if(IsKey(EGH_Orange
)) _ext
.Orange
= 0;
1227 if(IsKey(EGH_Plus
)) _ext
.Plus
= 0;
1228 if(IsKey(EGH_Minus
)) _ext
.Minus
= 0;
1229 if(IsKey(EGH_StrumUp
)) _ext
.StrumUp
= 0; // Strum Up
1230 if(IsKey(EGH_StrumDown
)) _ext
.StrumDown
= 0; // Strum Down
1233 // Convert data for reporting
1234 _ext
.SX
= (SX
>> 2);
1235 _ext
.SY
= (SY
>> 2);
1237 /* Here we encrypt the report */
1238 // Create a temporary storage for the data
1239 u8 Tmp
[sizeof(_ext
)];
1240 // Clear the array by copying zeroes to it
1241 memset(Tmp
, 0, sizeof(_ext
));
1242 // Copy the data to it
1243 memcpy(Tmp
, &_ext
, sizeof(_ext
));
1245 wiimote_encrypt(&g_ExtKey
[g_ID
], Tmp
, 0x00, sizeof(_ext
));
1246 // Write it back to the struct
1247 memcpy(&_ext
, Tmp
, sizeof(_ext
));
1250 } // end of namespace