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/
19 #include "Common.h" // Common
20 #include "LogManager.h"
21 #include "StringUtil.h"
24 #define EXCLUDEMAIN_H // Avoid certain declarations in main.h
25 #include "EmuDefinitions.h" // Local
26 #include "wiimote_hid.h"
28 #if defined(HAVE_WX) && HAVE_WX
29 #include "ConfigPadDlg.h"
30 #include "ConfigBasicDlg.h"
32 WiimotePadConfigDialog
*m_PadConfigFrame
= NULL
;
33 WiimoteBasicConfigDialog
*m_BasicConfigFrame
= NULL
;
36 #include "pluginspecs_wiimote.h"
39 #include "wiimote_real.h"
42 #if defined(HAVE_X11) && HAVE_X11
43 Display
* WMdisplay
= NULL
;
45 SWiimoteInitialize g_WiimoteInitialize
;
46 PLUGIN_GLOBALS
* globals
= NULL
;
49 bool g_EmulatorRunning
= false;
51 bool g_SearchDeviceDone
= false;
52 bool g_RealWiiMotePresent
= false;
55 bool g_DebugAccelerometer
= false;
56 bool g_DebugData
= false;
57 bool g_DebugComm
= false;
58 bool g_DebugSoundData
= false;
59 bool g_DebugCustom
= false;
62 int g_UpdateCounter
= 0;
63 double g_UpdateTime
= 0;
65 int g_UpdateWriteScreen
= 0;
66 std::vector
<int> g_UpdateTimeList (5, 0);
69 std::vector
<SRecordingAll
> VRecording(RECORDING_ROWS
);
71 PLUGIN_EMUSTATE g_EmulatorState
= PLUGIN_EMUSTATE_STOP
;
73 // Standard crap to make wxWidgets happy
75 HINSTANCE g_hInstance
;
77 #if defined(HAVE_WX) && HAVE_WX
78 class wxDLLApp
: public wxApp
85 IMPLEMENT_APP_NO_MAIN(wxDLLApp
)
86 WXDLLIMPEXP_BASE
void wxSetInstance(HINSTANCE hInst
);
89 BOOL APIENTRY
DllMain(HINSTANCE hinstDLL
, // DLL module handle
90 DWORD dwReason
, // reason called
91 LPVOID lpvReserved
) // reserved
95 case DLL_PROCESS_ATTACH
:
97 #if defined(HAVE_WX) && HAVE_WX
98 wxSetInstance((HINSTANCE
)hinstDLL
);
104 case DLL_PROCESS_DETACH
:
106 #if defined(HAVE_WX) && HAVE_WX
113 g_hInstance
= hinstDLL
;
118 #if defined(HAVE_WX) && HAVE_WX
119 wxWindow
* GetParentedWxWindow(HWND Parent
)
122 wxSetInstance((HINSTANCE
)g_hInstance
);
124 wxWindow
*win
= new wxWindow();
126 win
->SetHWND((WXHWND
)Parent
);
127 win
->AdoptAttributesFromHWND();
134 void GetDllInfo(PLUGIN_INFO
* _PluginInfo
)
136 _PluginInfo
->Version
= 0x0100;
137 _PluginInfo
->Type
= PLUGIN_TYPE_WIIMOTE
;
139 sprintf(_PluginInfo
->Name
, "Dolphin Wiimote Plugin (DebugFast)");
142 sprintf(_PluginInfo
->Name
, "Dolphin Wiimote Plugin");
144 sprintf(_PluginInfo
->Name
, "Dolphin Wiimote Plugin (Debug)");
149 void SetDllGlobals(PLUGIN_GLOBALS
* _pPluginGlobals
)
151 globals
= _pPluginGlobals
;
152 LogManager::SetInstance((LogManager
*)globals
->logManager
);
155 void *DllDebugger(void *_hParent
, bool Show
)
160 void DllConfig(HWND _hParent
)
163 if (WiiMoteReal::g_AutoPairUpInvisibleWindow
== NULL
)
165 WiiMoteReal::g_AutoPairUpInvisibleWindow
= new Common::Thread(WiiMoteReal::RunInvisibleMessageWindow_ThreadFunc
, NULL
);
166 WiiMoteReal::g_AutoPairUpMonitoring
= new Common::Thread(WiiMoteReal::PairUp_ThreadFunc
, NULL
);
169 if (!g_SearchDeviceDone
)
173 // We do a pad search before creating the dialog
174 WiiMoteEmu::Search_Devices(WiiMoteEmu::joyinfo
, WiiMoteEmu::NumPads
, WiiMoteEmu::NumGoodPads
);
175 g_SearchDeviceDone
= true;
179 #if defined(HAVE_WX) && HAVE_WX
180 wxWindow
*frame
= GetParentedWxWindow(_hParent
);
181 m_BasicConfigFrame
= new WiimoteBasicConfigDialog(frame
);
184 m_BasicConfigFrame
->ShowModal();
187 m_BasicConfigFrame
->ShowModal();
192 frame
->SetHWND(NULL
);
195 m_BasicConfigFrame
->Destroy();
196 m_BasicConfigFrame
= NULL
;
202 void Initialize(void *init
)
204 g_EmulatorRunning
= true;
205 g_WiimoteInitialize
= *(SWiimoteInitialize
*)init
;
207 #if defined(HAVE_WX) && HAVE_WX
209 g_ISOId
= g_WiimoteInitialize
.ISOId
;
213 #if defined(HAVE_X11) && HAVE_X11
214 WMdisplay
= XOpenDisplay(NULL
);
217 g_ISOId
= g_WiimoteInitialize
.ISOId
;
218 DEBUG_LOG(WIIMOTE
, "ISOId: %08x %s", g_WiimoteInitialize
.ISOId
, Hex2Ascii(g_WiimoteInitialize
.ISOId
).c_str());
220 // Load IR settings, as this is a per-game setting and the user might have loaded a different game
223 // Run this first so that WiiMoteReal::Initialize() overwrites g_Eeprom
224 WiiMoteEmu::Initialize();
226 /* We will run WiiMoteReal::Initialize() even if we are not using a real
227 wiimote, to check if there is a real wiimote connected. We will initiate
228 wiiuse.dll, but we will return before creating a new thread for it if we
229 find no real Wiimotes. Then g_RealWiiMotePresent will also be
230 false. This function call will be done instantly whether there is a real
231 Wiimote connected or not. It takes no time for Wiiuse to check for
232 connected Wiimotes. */
235 WiiMoteReal::Initialize();
236 WiiMoteReal::Allocate();
238 if (WiiMoteReal::g_AutoPairUpInvisibleWindow
== NULL
)
240 WiiMoteReal::g_AutoPairUpInvisibleWindow
= new Common::Thread(WiiMoteReal::RunInvisibleMessageWindow_ThreadFunc
, NULL
);
241 WiiMoteReal::g_AutoPairUpMonitoring
= new Common::Thread(WiiMoteReal::PairUp_ThreadFunc
, NULL
);
247 // If a game is not running this is called by the Configuration window when it's closed
251 g_EmulatorRunning
= false;
253 // Reset the game ID in all cases
257 WiiMoteReal::Shutdown();
259 WiiMoteEmu::Shutdown();
261 #if defined(HAVE_X11) && HAVE_X11
263 XCloseDisplay(WMdisplay
);
268 void DoState(unsigned char **ptr
, int mode
)
270 PointerWrap
p(ptr
, mode
);
272 // TODO: Shorten the list
274 //p.Do(g_EmulatorRunning);
276 //p.Do(g_RealWiiMotePresent);
277 //p.Do(g_RealWiiMoteInitialized);
278 //p.Do(g_EmulatedWiiMoteInitialized);
279 //p.Do(g_UpdateCounter);
280 //p.Do(g_UpdateTime);
281 //p.Do(g_UpdateRate);
282 //p.Do(g_UpdateWriteScreen);
283 //p.Do(g_UpdateTimeList);
286 WiiMoteReal::DoState(p
);
288 WiiMoteEmu::DoState(p
);
292 void EmuStateChange(PLUGIN_EMUSTATE newState
)
294 g_EmulatorState
= newState
;
297 #if defined(HAVE_WX) && HAVE_WX
298 // Hack to use wx key events
299 volatile bool wxkeystate
[WXK_SPECIAL20
];
302 // Set buttons status from keyboard input. Currently this is done from
303 // wxWidgets in the main application.
305 void Wiimote_Input(u16 _Key
, u8 _UpDown
)
307 #if defined(__APPLE__) && defined(USE_WX) && USE_WX
308 if (_Key
< WXK_SPECIAL20
)
310 wxkeystate
[_Key
] = _UpDown
;
315 /* This function produce Wiimote Input (reports from the Wiimote) in response
316 to Output from the Wii. It's called from WII_IPC_HLE_WiiMote.cpp.
318 Switch between real and emulated wiimote: We send all this Input to WiiMoteEmu::InterruptChannel()
319 so that it knows the channel ID and the data reporting mode at all times.
321 void Wiimote_InterruptChannel(int _number
, u16 _channelID
, const void* _pData
, u32 _Size
)
323 // Decide where to send the message
324 if (WiiMoteEmu::WiiMapping
[_number
].Source
<= 1)
325 WiiMoteEmu::InterruptChannel(_number
, _channelID
, _pData
, _Size
);
327 else if (g_RealWiiMotePresent
)
328 WiiMoteReal::InterruptChannel(_number
, _channelID
, _pData
, _Size
);
333 // Function: Used for the initial Bluetooth HID handshake.
334 void Wiimote_ControlChannel(int _number
, u16 _channelID
, const void* _pData
, u32 _Size
)
337 #if defined(_DEBUG) || defined(DEBUGFAST)
338 DEBUG_LOG(WIIMOTE
, "Wiimote_ControlChannel");
339 DEBUG_LOG(WIIMOTE
, " Channel ID: %04x", _channelID
);
340 std::string Temp
= ArrayToString((const u8
*)_pData
, _Size
);
341 DEBUG_LOG(WIIMOTE
, " Data: %s", Temp
.c_str());
344 // Check for custom communication
345 if(_channelID
== 99 && *(const u8
*)_pData
== WIIMOTE_DISCONNECT
)
347 WiiMoteEmu::g_ReportingAuto
[_number
] = false;
348 WARN_LOG(WIIMOTE
, "Wiimote: #%i Disconnected", _number
);
350 PostMessage(g_WiimoteInitialize
.hWnd
, WM_USER
, WIIMOTE_DISCONNECT
, _number
);
355 if (WiiMoteEmu::WiiMapping
[_number
].Source
<= 1)
356 WiiMoteEmu::ControlChannel(_number
, _channelID
, _pData
, _Size
);
358 else if (g_RealWiiMotePresent
)
359 WiiMoteReal::ControlChannel(_number
, _channelID
, _pData
, _Size
);
364 // This sends a Data Report from the Wiimote. See SystemTimers.cpp for the documentation of this update.
365 void Wiimote_Update(int _number
)
367 // This functions will send:
368 // Emulated Wiimote: Only data reports 0x30-0x37
369 // Real Wiimote: Both data reports 0x30-0x37 and all other read reports
370 if (WiiMoteEmu::WiiMapping
[_number
].Source
<= 1)
371 WiiMoteEmu::Update(_number
);
373 else if (g_RealWiiMotePresent
)
374 WiiMoteReal::Update(_number
);
380 if( GetAsyncKeyState(VK_HOME) && g_DebugComm ) g_DebugComm = false; // Page Down
381 else if (GetAsyncKeyState(VK_HOME) && !g_DebugComm ) g_DebugComm = true;
383 if( GetAsyncKeyState(VK_PRIOR) && g_DebugData ) g_DebugData = false; // Page Up
384 else if (GetAsyncKeyState(VK_PRIOR) && !g_DebugData ) g_DebugData = true;
386 if( GetAsyncKeyState(VK_NEXT) && g_DebugAccelerometer ) g_DebugAccelerometer = false; // Home
387 else if (GetAsyncKeyState(VK_NEXT) && !g_DebugAccelerometer ) g_DebugAccelerometer = true;
389 if( GetAsyncKeyState(VK_END) && g_DebugCustom ) { g_DebugCustom = false; DEBUG_LOG(WIIMOTE, "Custom Debug: Off");} // End
390 else if (GetAsyncKeyState(VK_END) && !g_DebugCustom ) {g_DebugCustom = true; DEBUG_LOG(WIIMOTE, "Custom Debug: Off");}
396 unsigned int Wiimote_GetAttachedControllers()
398 unsigned int attached
= 0;
399 for (unsigned int i
=0; i
<4; ++i
)
400 if (WiiMoteEmu::WiiMapping
[i
].Source
)
401 attached
|= (1 << i
);
406 // Unpair Wiimotes, TODO: Add linux/osx un-pair function
407 unsigned int Wiimote_UnPairWiimotes()
410 if (g_Config
.bUnpairRealWiimote
)
411 return WiiMoteReal::WiimotePairUp(true);
416 // Supporting functions
418 // Check if the render window is in focus
422 return g_WiimoteInitialize
.pRendererHasFocus();
425 /* Returns a timestamp with three decimals for precise time comparisons. The return format is
426 of the form seconds.milleseconds for example 1234.123. The leding seconds have no particular meaning
427 but are just there to enable use to tell if we have entered a new second or now. */