1. Fixed the dual mode. You should now be able to change between the real and emulated Wiimote at any time, even when the Nunchuck is connected. It also supports third party Wireless Nunchucks that never sends any calibration values. The Nunchuck status should be automatically updated. The Nunchuck stick may get stuck, but that should fix itself if you disconnect and reconnect again. The only important problems seems to be that the real Wiimote fails to answer sometimes so that the Core functions disconnect it.

2. Began looking at how to reconnect the Wiimote after an unwanted HCI disconnect command

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2129 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-02-07 03:16:41 +00:00
parent 1d0e8ddf84
commit fcdd2a8e17
26 changed files with 466 additions and 259 deletions

View File

@ -18,11 +18,19 @@
#ifndef _COMMON_H
#define _COMMON_H
//////////////////////////////////////////////////////////////////////////////////////////
// Settings
// -----------------
#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
#define CHECK_HEAP_INTEGRITY()
//////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// -----------------
#ifdef _WIN32
#ifdef _DEBUG
#include <crtdbg.h>
@ -49,30 +57,37 @@
#include <string.h>
#include "Paths.h"
///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Settings
// -----------------
// Darwin ABI requires that stack frames be aligned to 16-byte boundaries.
// This probably wouldn't break anyone either, but hey
#ifdef __APPLE__
#define STACKALIGN __attribute__((__force_align_arg_pointer__))
#define STACKALIGN __attribute__((__force_align_arg_pointer__))
#else
#define STACKALIGN
#define STACKALIGN
#endif
// Function Cross-Compatibility
#ifdef _WIN32
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define unlink _unlink
#define snprintf _snprintf
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define unlink _unlink
#define snprintf _snprintf
#else
#define _stricmp strcasecmp
#define _strnicmp strncasecmp
#define _unlink unlink
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#define _stricmp strcasecmp
#define _strnicmp strncasecmp
#define _unlink unlink
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#ifdef _WIN32
#ifdef _WIN32
// By default, MS' stdio implementation does not support 64-bit offsets.
// This little hack fixes that, keeping the code portable to linux where fseek and fread
// do support 64-bit offsets in modern distributions.
@ -164,9 +179,19 @@ template<class T>
inline T min(const T& a, const T& b) {return a > b ? b : a;}
template<class T>
inline T max(const T& a, const T& b) {return a > b ? a : b;}
///////////////////////////////////
// **************************************************************************************
// Utility functions
// **************************************************************************************
//////////////////////////////////////////////////////////////////////////////////////////
// Byte ordering
// -----------------
namespace Common
{
inline u8 swap8(u8 _data) {return(_data);}
@ -194,12 +219,12 @@ inline u64 swap64(u64 data) {return(((u64)swap32(data) << 32) | swap32(data >> 3
#endif
} // end of namespace Common
///////////////////////////////////
// Utility functions
//////////////////////////////////////////////////////////////////////////////////////////
// Message alerts
// -----------------
enum MSG_TYPE
{
INFORMATION,
@ -223,10 +248,12 @@ extern bool MsgAlert(const char* caption, bool yes_no, int Style, const char* fo
#define PanicYesNo(format, ...) MsgAlert("PANIC", true, WARNING, format, ##__VA_ARGS__)
#define AskYesNo(format, ...) MsgAlert("ASK", true, QUESTION, format, ##__VA_ARGS__)
#endif
///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Logging
// -----------------
// dummy class
class LogTypes
@ -328,9 +355,12 @@ void Host_UpdateLogDisplay();
#define _assert_(a)
#define _assert_msg_(...)
#endif
///////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Compile time asserts
// -----------------
namespace
{
@ -346,8 +376,9 @@ namespace
#endif
#endif
}
///////////////////////////////////////
#endif // #ifndef _COMMON_H
#endif // _COMMON_H

View File

@ -95,16 +95,19 @@ void Close()
// Print to screen and file
int Print(const char *fmt, ...)
{
// Maximum bytes, mind this value to avoid an overrun
static const int MAX_BYTES = 1024*20;
#if defined(_WIN32)
if(__hStdOut)
{
#endif
char s[1024*20]; // Warning, mind this value
char s[MAX_BYTES];
va_list argptr;
int cnt; // To store the vsnprintf return message
va_start(argptr, fmt);
cnt = vsnprintf(s, 500, fmt, argptr);
cnt = vsnprintf(s, MAX_BYTES, fmt, argptr);
va_end(argptr);

View File

@ -151,16 +151,14 @@ std::string StringFromFormat(const char* format, ...)
// ----------------
std::string ArrayToString(const u8 *data, u32 size, u32 offset, int line_len, bool Spaces)
{
std::string Temp;
std::string Tmp, Spc;
if (Spaces) Spc = " "; else Spc = "";
for (u32 i = 0; i < size; i++)
{
char Buffer[128];
if (Spaces) sprintf(Buffer, "%02x ", data[i + offset]);
else sprintf(Buffer, "%02x", data[i + offset]);
if(i > 0 && i % line_len == 0) Temp.append("\n"); // break long lines
Temp.append(Buffer);
Tmp += StringFromFormat("%02x%s", data[i + offset], Spc.c_str());
if(i > 1 && (i + 1) % line_len == 0) Tmp.append("\n"); // break long lines
}
return Temp;
return Tmp;
}
// ================

View File

@ -144,6 +144,12 @@ bool GetRealWiimote()
{
return g_bRealWiimote;
}
// This doesn't work yet, I don't understand how the connection work yet
void ReconnectWiimote()
{
HW::InitWiimote();
Console::Print("ReconnectWiimote()\n");
}
/////////////////////////////////////
@ -293,7 +299,7 @@ THREAD_RETURN EmuThread(void *pArg)
LOG(OSREPORT, "Dualcore = %s", _CoreParameter.bUseDualCore ? "Yes" : "No");
HW::Init();
emuThreadGoing.Set();
// Load the VideoPlugin

View File

@ -60,6 +60,7 @@ namespace Core
bool MakeScreenshot(const std::string& _rFilename);
void* GetWindowHandle();
bool GetRealWiimote();
void ReconnectWiimote();
extern bool bReadTrace;
extern bool bWriteTrace;

View File

@ -108,4 +108,10 @@ namespace HW
AudioInterface::DoState(p);
WII_IPCInterface::DoState(p);
}
// Restart Wiimote
void InitWiimote()
{
WII_IPCInterface::Init();
}
}

View File

@ -26,6 +26,7 @@ namespace HW
void Init();
void Shutdown();
void DoState(PointerWrap &p);
void InitWiimote();
}
#endif

View File

@ -19,12 +19,13 @@
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
#include "WII_IPC_HLE_Device_usb.h"
#include "../PluginManager.h"
#include "ConsoleWindow.h" // Common
#include "../Core.h" // Local core functions
#include "../Debugger/Debugger_SymbolMap.h"
#include "../Host.h"
#include "../PluginManager.h"
#include "WII_IPC_HLE_Device_usb.h"
///////////////////////
@ -1783,6 +1784,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDisconnect(u8* _Input)
"anyway. It is strongly recommed to save and/or restart the\n"
"emulation.");
}
Console::Print("IPC CommandDisconnect\n");
// Send message to plugin
/*
Common::PluginWiimote* mote = CPluginManager::GetInstance().GetWiimote(0);
u8 Message = WIIMOTE_RECONNECT;
mote->Wiimote_ControlChannel(99, &Message, 0);
*/
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkSupervisionTimeout(u8* _Input)

View File

@ -47,6 +47,7 @@ be accessed from Core::GetWindowHandle().
#include "Common.h" // Common
#include "FileUtil.h"
#include "Timer.h"
#include "ConsoleWindow.h"
#include "ConfigManager.h" // Core
#include "Core.h"
@ -170,16 +171,26 @@ int abc = 0;
switch(wParam)
{
// Stop
case 5:
case OPENGL_WM_USER_STOP:
main_frame->DoStop();
return 0; // Don't bother letting wxWidgets process this at all
case 15:
case OPENGL_WM_USER_CREATE:
// We don't have a local setting for bRenderToMain but we can detect it this way instead
//PanicAlert("main call %i %i %i %i", lParam, (HWND)Core::GetWindowHandle(), MSWGetParent_((HWND)Core::GetWindowHandle()), (HWND)this->GetHWND());
if (lParam == NULL) main_frame->bRenderToMain = false;
else main_frame->bRenderToMain = true;
return 0;
case NJOY_RELOAD:
// DirectInput in nJoy has failed
return 0;
case WIIMOTE_RECONNECT:
// The Wiimote plugin has been shut down, now reconnect the Wiimote
Console::Print("WIIMOTE_RECONNECT\n");
Core::ReconnectWiimote();
return 0;
}
break;

View File

@ -56,6 +56,7 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DolphinWX", "Core\DolphinWX\DolphinWX.vcproj", "{A72606EF-C5C1-4954-90AD-F0F93A8D97D9}"
ProjectSection(ProjectDependencies) = postProject
{48AD7E0A-25B1-4974-A1E3-03F8C438D34F} = {48AD7E0A-25B1-4974-A1E3-03F8C438D34F}
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160} = {CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}
{0318BA30-EF48-441A-9E10-DC85EFAE39F0} = {0318BA30-EF48-441A-9E10-DC85EFAE39F0}
{8D612734-FAA5-4B8A-804F-4DEA2367D495} = {8D612734-FAA5-4B8A-804F-4DEA2367D495}
{71B16F46-0B00-4EDA-B253-D6D9D03A215C} = {71B16F46-0B00-4EDA-B253-D6D9D03A215C}
@ -228,6 +229,7 @@ Global
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.DebugFast|x64.ActiveCfg = DebugFast|x64
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|Win32.ActiveCfg = Release|Win32
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|Win32.Build.0 = Release|Win32
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|x64.ActiveCfg = Release|x64
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|x64.Build.0 = Release|x64
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9}.Debug|Win32.ActiveCfg = Debug|Win32

View File

@ -17,6 +17,21 @@
///////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
/* Plugin communication. I place this here rather in Common.h since these messages are only received
at one place, by the CPanel in Frame.cpp. That way I don't have to rebuild if any of this is changed */
// -----------------
enum PLUGIN_COMM
{
// Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on
OPENGL_WM_USER_STOP = 10,
OPENGL_WM_USER_CREATE,
NJOY_RELOAD, // Reload nJoy if DirectInput has failed
WIIMOTE_RECONNECT // Reconnect the Wiimote if it has disconnected
};
///////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// System specific declarations and definitions
// ------------

View File

@ -138,7 +138,7 @@ namespace EmuWindow
switch( iMsg )
{
case WM_CREATE:
PostMessage(m_hMain, WM_USER, 15, (int)m_hParent); // 15 = WM_USER_CREATE, make enum table if it's confusing
PostMessage(m_hMain, WM_USER, OPENGL_WM_USER_CREATE, (int)m_hParent);
break;
case WM_PAINT:
@ -154,13 +154,15 @@ namespace EmuWindow
//PostQuitMessage(0);
/* The fullscreen option for Windows users is not very user friendly. With this the user
can only get out of the fullscreen mode by pressing Esc or Alt + F4. But that also
closes*/
can only get out of the fullscreen mode by pressing Esc or Alt + F4. Esc also stops
the emulation. Todo: But currently it hangs, so I have disabled the shutdown. */
//if(m_hParent == NULL) ExitProcess(0);
if(m_hParent == NULL)
{
{
if (g_Config.bFullscreen)
PostMessage(m_hMain, WM_USER, 5, 0); // Stop
{
//PostMessage(m_hMain, WM_USER, OPENGL_WM_USER_STOP, 0); // Stop
}
else
// Toggle maximize and restore
if (IsZoomed(hWnd)) ShowWindow(hWnd, SW_RESTORE); else ShowWindow(hWnd, SW_MAXIMIZE);

View File

@ -765,7 +765,7 @@ void ConfigDialog::CreateGUIControls()
// ===================================================
/* Do use real wiimote */
/* Do connect real wiimote */
// ----------------
void ConfigDialog::DoConnectReal()
{
@ -777,15 +777,53 @@ void ConfigDialog::DoConnectReal()
}
else
{
if (g_RealWiiMoteInitialized) WiiMoteReal::Shutdown();
Console::Print("Post Message: %i\n", g_RealWiiMoteInitialized);
if (g_RealWiiMoteInitialized)
{
WiiMoteReal::Shutdown();
/*
if (g_WiimoteUnexpectedDisconnect)
{
#ifdef _WIN32
PostMessage(g_ParentHWND, WM_USER, WIIMOTE_RECONNECT, 0);
g_WiimoteUnexpectedDisconnect = false;
#endif
}
*/
}
}
}
// ===================================================
/* Do use real wiimote. We let the game set up the real Wiimote reporting mode and init the Extension when we change
want to use it again. */
// ----------------
void ConfigDialog::DoUseReal()
{
// Clear any eventual events in the Wiimote queue
WiiMoteReal::ClearEvents();
// Are we using an extension now? The report that it's removed, then reconnected.
bool UsingExtension = false;
if (g_Config.bNunchuckConnected || g_Config.bClassicControllerConnected)
UsingExtension = true;
Console::Print("\nDoUseReal() Connect extension: %i\n", !UsingExtension);
DoExtensionConnectedDisconnected(UsingExtension ? 0 : 1);
// Sleep this thread
sleep(100);
UsingExtension = !UsingExtension;
Console::Print("\nDoUseReal() Connect extension: %i\n", !UsingExtension);
DoExtensionConnectedDisconnected(UsingExtension ? 1 : 0);
// Sleep again, to allow the approximate time it takes for the Wiimote to come online
sleep(200);
}
// ===================================================
/* Generate connect/disconnect status event */
// ----------------
void ConfigDialog::DoExtensionConnectedDisconnected()
void ConfigDialog::DoExtensionConnectedDisconnected(int Extension)
{
// There is no need for this if no game is running
if(!g_EmulatorRunning) return;
@ -795,7 +833,7 @@ void ConfigDialog::DoExtensionConnectedDisconnected()
// Check if a game is running, in that case change the status
if(WiiMoteEmu::g_ReportingChannel > 0)
WiiMoteEmu::WmRequestStatus(WiiMoteEmu::g_ReportingChannel, rs);
WiiMoteEmu::WmRequestStatus(WiiMoteEmu::g_ReportingChannel, rs, Extension);
}
// ===================================================
@ -809,9 +847,9 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
DoConnectReal();
break;
case ID_USE_REAL:
// Enable the Wiimote thread
g_Config.bUseRealWiimote = m_UseRealWiimote[Page]->IsChecked();
//if(g_Config.bUseRealWiimote) WiiMoteReal::SetDataReportingMode();
if(g_Config.bUseRealWiimote) WiiMoteReal::ClearEvents();
if(g_Config.bUseRealWiimote) DoUseReal();
break;
case ID_SIDEWAYSDPAD:
@ -842,8 +880,8 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
g_Config.bNunchuckConnected = m_NunchuckConnected[Page]->IsChecked();
// Copy the calibration data
memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::nunchuck_calibration,
sizeof(WiiMoteEmu::nunchuck_calibration));
memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::nunchuck_calibration, sizeof(WiiMoteEmu::nunchuck_calibration));
memcpy(WiiMoteEmu::g_RegExt + 0x30, WiiMoteEmu::nunchuck_calibration, sizeof(WiiMoteEmu::nunchuck_calibration));
memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::nunchuck_id, sizeof(WiiMoteEmu::nunchuck_id));
// Generate connect/disconnect status event
@ -862,8 +900,8 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
g_Config.bClassicControllerConnected = m_ClassicControllerConnected[Page]->IsChecked();
// Copy the calibration data
memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::classic_calibration,
sizeof(WiiMoteEmu::classic_calibration));
memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::classic_calibration, sizeof(WiiMoteEmu::classic_calibration));
memcpy(WiiMoteEmu::g_RegExt + 0x30, WiiMoteEmu::classic_calibration, sizeof(WiiMoteEmu::classic_calibration));
memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::classic_id, sizeof(WiiMoteEmu::classic_id));
// Generate connect/disconnect status event
DoExtensionConnectedDisconnected();
@ -925,14 +963,13 @@ void ConfigDialog::UpdateGUI()
{
Console::Print("UpdateGUI: \n");
/* We can't allow different values for this one if we are using the real and emulated wiimote
side by side so that we can switch between between during gameplay. We update the checked
or unchecked values from the g_Config settings, and we make sure they are up to date with
unplugged and reinserted extensions. */
/* We only allow a change of extension if we are not currently using the real Wiimote, if it's in use the status will be updated
from the data scanning functions in main.cpp */
bool AllowExtensionChange = !(g_RealWiiMotePresent && g_Config.bConnectRealWiimote && g_Config.bUseRealWiimote && g_EmulatorRunning);
m_NunchuckConnected[Page]->SetValue(g_Config.bNunchuckConnected);
m_ClassicControllerConnected[Page]->SetValue(g_Config.bClassicControllerConnected);
m_NunchuckConnected[Page]->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote && g_EmulatorRunning));
m_ClassicControllerConnected[Page]->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote && g_EmulatorRunning));
m_NunchuckConnected[Page]->Enable(AllowExtensionChange);
m_ClassicControllerConnected[Page]->Enable(AllowExtensionChange);
/* I have disabled this option during a running game because it's enough to be able to switch
between using and not using then. To also use the connect option during a running game would

View File

@ -156,8 +156,9 @@ class ConfigDialog : public wxDialog
void AboutClick(wxCommandEvent& event);
void DoConnectReal(); // Real
void DoUseReal();
void DoExtensionConnectedDisconnected(); // Emulated
void DoExtensionConnectedDisconnected(int Extension = -1); // Emulated
void GeneralSettingsChanged(wxCommandEvent& event);
};

View File

@ -50,7 +50,6 @@ u8 g_Eeprom[WIIMOTE_EEPROM_SIZE];
u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE];
u8 g_RegExt[WIIMOTE_REG_EXT_SIZE];
u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE];
u8 g_RegExtTmpReport[WIIMOTE_REG_EXT_SIZE];
u8 g_RegIr[WIIMOTE_REG_IR_SIZE];
u8 g_ReportingMode; // The reporting mode and channel id
@ -59,6 +58,7 @@ u16 g_ReportingChannel;
std::vector<wm_ackdelay> AckDelay; // Ackk delay
wiimote_key g_ExtKey; // The extension encryption key
bool g_Encryption; // Encryption on or off
} // namespace

View File

@ -78,7 +78,6 @@ extern u8 g_Eeprom[WIIMOTE_EEPROM_SIZE];
extern u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE];
extern u8 g_RegExt[WIIMOTE_REG_EXT_SIZE];
extern u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE];
extern u8 g_RegExtTmpReport[WIIMOTE_REG_EXT_SIZE];
extern u8 g_RegIr[WIIMOTE_REG_IR_SIZE];
extern u8 g_ReportingMode;
@ -95,6 +94,7 @@ struct wm_ackdelay
extern std::vector<wm_ackdelay> AckDelay;
extern wiimote_key g_ExtKey; // extension encryption key
extern bool g_Encryption;
/* An example of a factory default first bytes of the Eeprom memory. There are differences between
different Wiimotes, my Wiimote had different neutral values for the accelerometer. */
@ -120,11 +120,15 @@ static const u8 nunchuck_calibration[] =
0x80,0x80,0x80,0x00, // accelerometer x, y, z neutral
0xb3,0xb3,0xb3,0x00, // x, y, z g-force values
0xe0, 0x20, 0x80, 0xe0, // 0x80 = analog stick x and y axis center
0x20, 0x80, 0xee, 0x43,
0x80,0x80,0x80,0x00, 0xb3,0xb3,0xb3,0x00, // repeat
0xe0,0x20,0x80,0xe0, 0x20,0x80,0xee,0x43
0xff, 0x00, 0x80, 0xff, // 0x80 = analog stick x and y axis center
0x00, 0x80, 0xee, 0x43 // checksum on the last two bytes
};
static const u8 wireless_nunchuck_calibration[] =
{
128, 128, 128, 0x00,
181, 181, 181, 0x00,
255, 0, 125, 255,
0, 126, 0xed, 0x43
};
/* Classic Controller calibration. 0x80 is the neutral for the analog triggers and
@ -133,9 +137,6 @@ static const u8 nunchuck_calibration[] =
static const u8 classic_calibration[] =
{
0xe4,0x1c,0x80,0xe4, 0x1c,0x80,0xd8,0x28,
0x80,0xd8,0x28,0x80, 0x20,0x20,0x95,0xea,
0xe4,0x1c,0x80,0xe4, 0x1c,0x80,0xd8,0x28, // repeat
0x80,0xd8,0x28,0x80, 0x20,0x20,0x95,0xea
};

View File

@ -232,10 +232,33 @@ void UpdateEeprom()
g_accel.cal_g.y = g_Eeprom[27] - g_Eeprom[24];
g_accel.cal_g.z = g_Eeprom[28] - g_Eeprom[24];
g_nu.cal_zero.x = g_RegExt[0x20];
g_nu.cal_zero.y = g_RegExt[0x21];
g_nu.cal_zero.z = g_RegExt[0x22];
g_nu.jx.max = g_RegExt[0x28];
g_nu.jx.min = g_RegExt[0x29];
g_nu.jx.center = g_RegExt[0x2a];
g_nu.jy.max = g_RegExt[0x2b];
g_nu.jy.min = g_RegExt[0x2c];
g_nu.jy.center = g_RegExt[0x2d];
Console::Print("UpdateEeprom: %i %i %i\n",
WiiMoteEmu::g_Eeprom[22], WiiMoteEmu::g_Eeprom[23], WiiMoteEmu::g_Eeprom[27]);
}
// Calculate checksum for the nunchuck calibration. The last two bytes.
void ExtensionChecksum(u8 * Calibration)
{
u8 sum = 0; u8 Byte15, Byte16;
for (int i = 0; i < sizeof(Calibration) - 2; i++)
{
sum += Calibration[i];
printf("Plus 0x%02x\n", Calibration[i]);
}
Byte15 = sum + 0x55; // Byte 15
Byte16 = sum + 0xaa; // Byte 16
}
// Set initial values
void ResetVariables()
{
@ -246,6 +269,7 @@ void ResetVariables()
g_ReportingMode = 0;
g_ReportingChannel = 0;
g_Encryption = false;
g_EmulatedWiiMoteInitialized = false;
}
@ -277,11 +301,13 @@ void Initialize()
if(g_Config.bNunchuckConnected)
{
memcpy(g_RegExt + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration));
memcpy(g_RegExt + 0x30, nunchuck_calibration, sizeof(nunchuck_calibration));
memcpy(g_RegExt + 0xfa, nunchuck_id, sizeof(nunchuck_id));
}
else if(g_Config.bClassicControllerConnected)
{
memcpy(g_RegExt + 0x20, classic_calibration, sizeof(classic_calibration));
memcpy(g_RegExt + 0x30, classic_calibration, sizeof(classic_calibration));
memcpy(g_RegExt + 0xfa, classic_id, sizeof(classic_id));
}

View File

@ -370,6 +370,7 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size)
// Add header values
pReply->buttons = 0;
pReply->error = 0;
// 0x1 means two bytes, 0xf means 16 bytes
pReply->size = (copySize - 1) & 0xf;
pReply->address = Common::swap16(_Address + dataOffset);
@ -534,7 +535,7 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
request rs and all its eventual instructions it may include (for example turn off
rumble or something else) and just send the status report. */
// ----------------
void WmRequestStatus(u16 _channelID, wm_request_status* rs)
void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension)
{
//PanicAlert("WmRequestStatus");
LOGV(WII_IPC_WIIMOTE, 0, "================================================");
@ -562,11 +563,22 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs)
0x55 - 0xff: level 4 */
pStatus->battery = 0x5f; // fully charged
// Read config value for this one
if(g_Config.bNunchuckConnected || g_Config.bClassicControllerConnected)
pStatus->extension = 1;
// Check if we have a specific order about the extension status
if (Extension == -1)
{
// Read config value for this one
if(g_Config.bNunchuckConnected || g_Config.bClassicControllerConnected)
pStatus->extension = 1;
else
pStatus->extension = 0;
}
else
pStatus->extension = 0;
{
if(Extension)
pStatus->extension = 1;
else
pStatus->extension = 0;
}
LOGV(WII_IPC_WIIMOTE, 0, " Extension: %x", pStatus->extension);
LOGV(WII_IPC_WIIMOTE, 0, " SendStatusReport()");

View File

@ -53,7 +53,7 @@ void HidOutputReport(u16 _channelID, wm_report* sr);
void WmLeds(u16 _channelID, wm_leds* leds);
void WmReadData(u16 _channelID, wm_read_data* rd);
void WmWriteData(u16 _channelID, wm_write_data* wd);
void WmRequestStatus(u16 _channelID, wm_request_status* rs);
void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension = -1);
void WmRequestStatus_(u16 _channelID, int a);
void WmDataReporting(u16 _channelID, wm_data_reporting* dr);

View File

@ -777,57 +777,45 @@ void FillReportExtension(wm_extension& _ext)
// ------------------------------------
// The default joystick and button values unless we use them
// --------------
_ext.jx = 0x80;
_ext.jy = 0x80;
_ext.jx = g_nu.jx.center;
_ext.jy = g_nu.jy.center;
_ext.bt = 0x03; // 0x03 means no button pressed, the button is zero active
// ---------------------
#ifdef _WIN32
/* We use a 192 range (32 to 224) that match our calibration values in nunchuck_calibration[] */
if(GetAsyncKeyState(VK_NUMPAD4)) // left
_ext.jx = 0x20;
// Set the max values to the current calibration values
if(GetAsyncKeyState(VK_NUMPAD4)) // x
_ext.jx = g_nu.jx.min;
if(GetAsyncKeyState(VK_NUMPAD6))
_ext.jx = g_nu.jx.max;
if(GetAsyncKeyState(VK_NUMPAD5)) // y
_ext.jy = g_nu.jy.min;
if(GetAsyncKeyState(VK_NUMPAD8))
_ext.jy = 0xe0;
if(GetAsyncKeyState(VK_NUMPAD6)) // right
_ext.jx = 0xe0;
if(GetAsyncKeyState(VK_NUMPAD5))
_ext.jy = 0x20;
_ext.jy = g_nu.jy.max;
if(GetAsyncKeyState('C'))
_ext.bt = 0x01;
if(GetAsyncKeyState('Z'))
_ext.bt = 0x02;
_ext.bt = 0x02;
if(GetAsyncKeyState('C') && GetAsyncKeyState('Z'))
_ext.bt = 0x00;
#else
// TODO linux port
#endif
/* Here we use g_RegExtTmpReport as a temporary storage for the enryption function because
the type if array may have some importance for wiimote_encrypt(). We avoid using
g_RegExtTmp that is used in EmuMain.cpp because if this runs on a different thread
there is a small chance that they may interfer with each other. */
// Clear g_RegExtTmpReport by copying zeroes to it, this may not be needed
memset(g_RegExtTmpReport, 0, sizeof(g_RegExtTmp));
/* Write the nunchuck inputs to it. We begin writing at 0x08, but it could also be
0x00, the important thing is that we begin at an address evenly divisible
by 0x08 */
memcpy(g_RegExtTmpReport + 0x08, &_ext, sizeof(_ext));
/* Here we encrypt the report */
// Create a temporary storage for the data
u8 Tmp[sizeof(_ext)];
// Clear the array by copying zeroes to it
memset(Tmp, 0, sizeof(_ext));
// Copy the data to it
memcpy(Tmp, &_ext, sizeof(_ext));
// Encrypt it
wiimote_encrypt(&g_ExtKey, &g_RegExtTmpReport[0x08], 0x08, sizeof(_ext));
// Write it back to the extension
memcpy(&_ext, &g_RegExtTmpReport[0x08], sizeof(_ext));
wiimote_encrypt(&g_ExtKey, Tmp, 0x00, sizeof(_ext));
// Write it back to the struct
memcpy(&_ext, Tmp, sizeof(_ext));
}
// =======================
@ -1002,17 +990,18 @@ void FillReportClassicExtension(wm_classic_extension& _ext)
// TODO linux port
#endif
// Clear g_RegExtTmp by copying zeroes to it
memset(g_RegExtTmpReport, 0, sizeof(g_RegExtTmp));
/* Write the nunchuck inputs to it. We begin writing at 0x08, see comment above. */
memcpy(g_RegExtTmpReport + 0x08, &_ext, sizeof(_ext));
/* Here we encrypt the report */
// Create a temporary storage for the data
u8 Tmp[sizeof(_ext)];
// Clear the array by copying zeroes to it
memset(Tmp, 0, sizeof(_ext));
// Copy the data to it
memcpy(Tmp, &_ext, sizeof(_ext));
// Encrypt it
wiimote_encrypt(&g_ExtKey, &g_RegExtTmpReport[0x08], 0x08, 0x06);
// Write it back
memcpy(&_ext, &g_RegExtTmpReport[0x08], sizeof(_ext));
wiimote_encrypt(&g_ExtKey, Tmp, 0x00, sizeof(_ext));
// Write it back to the struct
memcpy(&_ext, Tmp, sizeof(_ext));
}
// =======================

View File

@ -39,6 +39,11 @@
namespace WiiMoteReal
{
int GetReportSize(struct wiimote_t* wm)
{
// The report size is 0x33 = 18, 0x37 = 22 withouth the leading (a1) byte
if(WIIUSE_USING_EXP(wm)) return 22; else return 18;
}
void handle_ctrl_status(struct wiimote_t* wm)
{
@ -51,12 +56,11 @@ void handle_ctrl_status(struct wiimote_t* wm)
Console::Print("battery: %f %%\n", wm->battery_level);
}
bool IRDataOK(struct wiimote_t* wm)
{
//Console::Print("IRDataOK: ");
// The report size is 0x33 = 18, 0x37 = 22 withouth the leading (a1) byte
int ReportSize; if(WIIUSE_USING_EXP(wm)) ReportSize = 22; else ReportSize = 18;
int ReportSize = GetReportSize(wm);
for(int i = 0; i < ReportSize; i++)
{
//Console::Print("%02x ", wm->event_buf[i]);
@ -246,6 +250,8 @@ void ReadWiimote()
be needed. But I still use it becase it seemed like state_changed() or the threshold values or
something else might fail so that only huge status changed were reported. */
handle_event(g_WiiMotesFromWiiUse[0]);
// Declaration
std::string Temp;
/* Timeout for data reading. This is used in Initialize() to read the Eeprom, if we have not gotten
@ -282,7 +288,7 @@ void ReadWiimote()
case WIIUSE_STATUS:
/* a status event occured */
handle_ctrl_status(g_WiiMotesFromWiiUse[i]);
//handle_ctrl_status(g_WiiMotesFromWiiUse[i]);
break;
case WIIUSE_DISCONNECT:

View File

@ -16,6 +16,22 @@
// http://code.google.com/p/dolphin-emu/
//////////////////////////////////////////////////////////////////////////////////////////
// Current issues
/* ¯¯¯¯¯¯¯¯¯¯¯¯¯
The real Wiimote fails to answer the core correctly sometmes. Leading to an unwanted disconnection. And
there is currenty no functions to reconnect with the game. There are two ways to solve this:
1. Make a reconnect function in the IOS emulation
2. Detect failed answers in this plugin and solve it by replacing them with emulated answers.
The first solution seems easier, if I knew a little better how the /dev/usb/oh1 and Wiimote functions
worked.
/////////////////////////////////////////////*/
//////////////////////////////////////////////////////////////////////////////////////////
// Includes
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
@ -52,14 +68,17 @@ bool g_FrameOpen = false;
bool g_RealWiiMotePresent = false;
bool g_RealWiiMoteInitialized = false;
bool g_EmulatedWiiMoteInitialized = false;
bool g_WiimoteUnexpectedDisconnect = false;
// Settings
accel_cal g_accel;
nu_cal g_nu;
// Debugging
bool g_DebugAccelerometer = false;
bool g_DebugData = false;
bool g_DebugComm = true;
bool g_DebugCustom = false;
// Update speed
int g_UpdateCounter = 0;
@ -74,6 +93,10 @@ std::vector<SRecordingAll> VRecording(RECORDING_ROWS);
// DLL instance
HINSTANCE g_hInstance;
#ifdef _WIN32
HWND g_ParentHWND = NULL;
#endif
#if defined(HAVE_WX) && HAVE_WX
wxWindow win;
ConfigDialog *frame = NULL;
@ -178,6 +201,10 @@ extern "C" void Initialize(void *init)
SWiimoteInitialize _WiimoteInitialize = *(SWiimoteInitialize *)init;
g_WiimoteInitialize = _WiimoteInitialize;
#ifdef _WIN32
g_ParentHWND = GetParent(g_WiimoteInitialize.hWnd);
#endif
g_EmulatorRunning = true;
#if defined(HAVE_WX) && HAVE_WX
@ -265,6 +292,16 @@ extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _
LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
const u8* data = (const u8*)_pData;
// Check for custom communication
if(_channelID == 99 && data[0] == WIIMOTE_RECONNECT)
{
Console::Print("\n\nWiimote Disconnected\n\n");
g_EmulatorRunning = false;
g_WiimoteUnexpectedDisconnect = true;
if (frame) frame->UpdateGUI();
return;
}
// Debugging
{
LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_ControlChannel");
@ -315,14 +352,17 @@ extern "C" void Wiimote_Update()
// Debugging
#ifdef _WIN32
if( GetAsyncKeyState(VK_HOME) && g_DebugComm ) g_DebugComm = false;
if( GetAsyncKeyState(VK_HOME) && g_DebugComm ) g_DebugComm = false; // Page Down
else if (GetAsyncKeyState(VK_HOME) && !g_DebugComm ) g_DebugComm = true;
if( GetAsyncKeyState(VK_PRIOR) && g_DebugData ) g_DebugData = false;
if( GetAsyncKeyState(VK_PRIOR) && g_DebugData ) g_DebugData = false; // Page Up
else if (GetAsyncKeyState(VK_PRIOR) && !g_DebugData ) g_DebugData = true;
if( GetAsyncKeyState(VK_NEXT) && g_DebugAccelerometer ) g_DebugAccelerometer = false;
if( GetAsyncKeyState(VK_NEXT) && g_DebugAccelerometer ) g_DebugAccelerometer = false; // Home
else if (GetAsyncKeyState(VK_NEXT) && !g_DebugAccelerometer ) g_DebugAccelerometer = true;
if( GetAsyncKeyState(VK_END) && g_DebugCustom ) { g_DebugCustom = false; Console::Print("Custom Debug: Off\n");} // End
else if (GetAsyncKeyState(VK_END) && !g_DebugCustom ) {g_DebugCustom = true; Console::Print("Custom Debug: Off\n");}
#endif
}
@ -353,6 +393,17 @@ bool IsFocus()
#endif
}
// Turn off all extensions
void DisableExtensions()
{
//g_Config.bMotionPlus = false;
g_Config.bNunchuckConnected = false;
g_Config.bClassicControllerConnected = false;
//g_Config.bBalanceBoard = false;
//g_Config.bGuitar = false;
//g_Config.bDrums = false;
}
void ReadDebugging(bool Emu, const void* _pData, int Size)
{
//
@ -361,32 +412,38 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
int size;
bool DataReport = false;
std::string Name;
std::string Name, TmpData;
switch(data[1])
{
case WM_STATUS_REPORT: // 0x20
size = sizeof(wm_status_report);
Name = "WM_STATUS_REPORT";
{
/*wm_status_report* pStatus = (wm_status_report*)(data + 2);
Console::Print(""
wm_status_report* pStatus = (wm_status_report*)(data + 2);
Console::Print("\n"
"Extension Controller: %i\n"
"Speaker enabled: %i\n"
"IR camera enabled: %i\n"
"LED 1: %i\n"
"LED 2: %i\n"
"LED 3: %i\n"
"LED 4: %i\n"
//"Speaker enabled: %i\n"
//"IR camera enabled: %i\n"
//"LED 1: %i\n"
//"LED 2: %i\n"
//"LED 3: %i\n"
//"LED 4: %i\n"
"Battery low: %i\n\n",
pStatus->extension,
pStatus->speaker,
pStatus->ir,
(pStatus->leds >> 0),
(pStatus->leds >> 1),
(pStatus->leds >> 2),
(pStatus->leds >> 3),
//pStatus->speaker,
//pStatus->ir,
//(pStatus->leds >> 0),
//(pStatus->leds >> 1),
//(pStatus->leds >> 2),
//(pStatus->leds >> 3),
pStatus->battery_low
);*/
);
// Update the global extension settings
if(!Emu && !pStatus->extension)
{
DisableExtensions();
if (frame) frame->UpdateGUI();
}
}
break;
case WM_READ_DATA_REPLY: // 0x21
@ -395,17 +452,56 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
// data[4]: Size and error
// data[5, 6]: The registry offset
// Show the accelerometer neutral values
if (data[5] == 0x00 && data[6] == 0x10)
// Show the extension ID
if ((data[4] == 0x10 || data[4] == 0x20 || data[4] == 0x50) && data[5] == 0x00 && (data[6] == 0xfa || data[6] == 0xfe))
{
Console::Print("\nGame got the Wiimote accelerometer neutral values: %i %i %i\n\n",
data[13], data[14], data[19]);
if(data[4] == 0x10)
Console::Print("\n\nGame got the encrypted extension ID: %02x%02x\n", data[7], data[8]);
else if(data[4] == 0x50)
Console::Print("\n\nGame got the encrypted extension ID: %02x%02x%02x%02x%02x%02x\n", data[7], data[8], data[9], data[10], data[11], data[12]);
// We have already sent the data report so we can safely decrypt it now
if(WiiMoteEmu::g_Encryption)
{
if(data[4] == 0x10)
wiimote_decrypt(&WiiMoteEmu::g_ExtKey, &data[0x07], 0x06, (data[4] >> 0x04) + 1);
if(data[4] == 0x50)
wiimote_decrypt(&WiiMoteEmu::g_ExtKey, &data[0x07], 0x02, (data[4] >> 0x04) + 1);
}
// Update the global extension settings
if(data[4] == 0x10)
{
if (!Emu) DisableExtensions();
if (!Emu && data[7] == 0x00 && data[8] == 0x00) g_Config.bNunchuckConnected = true;
if (!Emu && data[7] == 0x01 && data[8] == 0x01) g_Config.bClassicControllerConnected = true;
g_Config.Save();
WiiMoteEmu::UpdateEeprom();
if (frame) frame->UpdateGUI();
Console::Print("Game got the decrypted extension ID: %02x%02x\n\n", data[7], data[8]);
}
else if(data[4] == 0x50)
{
if (!Emu) DisableExtensions();
if (!Emu && data[11] == 0x00 && data[12] == 0x00) g_Config.bNunchuckConnected = true;
if (!Emu && data[11] == 0x01 && data[12] == 0x01) g_Config.bClassicControllerConnected = true;
g_Config.Save();
WiiMoteEmu::UpdateEeprom();
if (frame) frame->UpdateGUI();
Console::Print("Game got the decrypted extension ID: %02x%02x%02x%02x%02x%02x\n\n", data[7], data[8], data[9], data[10], data[11], data[12]);
}
}
// Show the nunchuck neutral values
// We have already sent the data report so we can safely decrypt it now
wiimote_decrypt(&WiiMoteEmu::g_ExtKey, &data[7], 0x00, Size - 7);
if(data[4] == 0xf0 && data[5] == 0x00 && data[6] == 0x20)
if(data[4] == 0xf0 && data[5] == 0x00 && (data[6] == 0x20 || data[6] == 0x30))
{
// Save the encrypted data
TmpData = StringFromFormat("Read[%s] (enc): %s\n", (Emu ? "Emu" : "Real"), ArrayToString(data, size + 2, 0, 30).c_str());
// We have already sent the data report so we can safely decrypt it now
if(WiiMoteEmu::g_Encryption)
wiimote_decrypt(&WiiMoteEmu::g_ExtKey, &data[0x07], 0x00, (data[4] >> 0x04) + 1);
Console::Print("\nGame got the Nunchuck calibration:\n");
Console::Print("Cal_zero.x: %i\n", data[7 + 0]);
Console::Print("Cal_zero.y: %i\n", data[7 + 1]);
@ -419,6 +515,22 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
Console::Print("Js.Max.y: %i\n", data[7 + 11]);
Console::Print("Js.Min.y: %i\n", data[7 + 12]);
Console::Print("JS.Center.y: %i\n\n", data[7 + 13]);
// Save the values
if (!Emu && data[7 + 0] != 0xff)
{
memcpy(WiiMoteEmu::g_RegExt + 0x20, &data[7], 0x10);
memcpy(WiiMoteEmu::g_RegExt + 0x30, &data[7], 0x10);
}
// We got a third party nunchuck
else if(data[7 + 0] == 0xff)
{
memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::wireless_nunchuck_calibration, sizeof(WiiMoteEmu::wireless_nunchuck_calibration));
memcpy(WiiMoteEmu::g_RegExt + 0x30, WiiMoteEmu::wireless_nunchuck_calibration, sizeof(WiiMoteEmu::wireless_nunchuck_calibration));
}
// Show the encrypted data
Console::Print("%s", TmpData.c_str());
}
break;
@ -459,7 +571,8 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
DataReport = true;
break;
default:
PanicAlert("%s ReadDebugging: Unknown channel 0x%02x", (Emu ? "Emu" : "Real"), data[1]);
//PanicAlert("%s ReadDebugging: Unknown channel 0x%02x", (Emu ? "Emu" : "Real"), data[1]);
Console::Print("%s ReadDebugging: Unknown channel 0x%02x", (Emu ? "Emu" : "Real"), data[1]);
return;
}
@ -513,29 +626,31 @@ void InterruptDebugging(bool Emu, const void* _pData)
//
const u8* data = (const u8*)_pData;
if (g_DebugComm) Console::Print("Write[%s] ", (Emu ? "Emu" : "Real"));
std::string Name;
int size;
if (g_DebugComm) Name += StringFromFormat("Write[%s] ", (Emu ? "Emu" : "Real"));
switch(data[1])
{
case 0x10:
size = 4; // I don't know the size
if (g_DebugComm) Console::Print("0x10");
if (g_DebugComm) Name.append("0x10");
break;
case WM_LEDS: // 0x11
size = sizeof(wm_leds);
if (g_DebugComm) Console::Print("WM_LEDS");
if (g_DebugComm) Name.append("WM_LEDS");
break;
case WM_DATA_REPORTING: // 0x12
size = sizeof(wm_data_reporting);
if (g_DebugComm) Console::Print("WM_DATA_REPORTING");
if (g_DebugComm) Name.append("WM_DATA_REPORTING");
break;
case WM_REQUEST_STATUS: // 0x15
size = sizeof(wm_request_status);
if (g_DebugComm) Console::Print("WM_REQUEST_STATUS");
if (g_DebugComm) Name.append("WM_REQUEST_STATUS");
break;
case WM_WRITE_DATA: // 0x16
if (g_DebugComm) Console::Print("WM_WRITE_DATA");
if (g_DebugComm) Name.append("WM_WRITE_DATA");
size = sizeof(wm_write_data);
// data[2]: The address space 0, 1 or 2
// data[3]: The registry type
@ -544,17 +659,27 @@ void InterruptDebugging(bool Emu, const void* _pData)
switch(data[2] >> 0x01)
{
case WM_SPACE_EEPROM:
if (g_DebugComm) Console::Print(" REG_EEPROM"); break;
if (g_DebugComm) Name.append(" REG_EEPROM"); break;
case WM_SPACE_REGS1:
case WM_SPACE_REGS2:
switch(data[3])
{
case 0xa2:
if (g_DebugComm) Console::Print(" REG_SPEAKER"); break;
if (g_DebugComm) Name.append(" REG_SPEAKER"); break;
case 0xa4:
if (g_DebugComm) Console::Print(" REG_EXT"); break;
if (g_DebugComm) Name.append(" REG_EXT");
// Update the encryption mode
if (data[3] == 0xa4 && data[5] == 0xf0)
{
if (data[7] == 0xaa)
WiiMoteEmu::g_Encryption = true;
else if (data[7] == 0x55)
WiiMoteEmu::g_Encryption = false;
Console::Print("\nExtension enryption turned %s\n\n", WiiMoteEmu::g_Encryption ? "On" : "Off");
}
break;
case 0xb0:
if (g_DebugComm) Console::Print(" REG_IR"); break;
if (g_DebugComm) Name.append(" REG_IR"); break;
}
break;
}
@ -565,33 +690,33 @@ void InterruptDebugging(bool Emu, const void* _pData)
// data[3]: The registry type
// data[5]: The registry offset
// data[7]: The number of bytes, 6 and 7 together
if (g_DebugComm) Console::Print("WM_READ_DATA");
if (g_DebugComm) Name.append("WM_READ_DATA");
switch(data[2] >> 0x01)
{
case WM_SPACE_EEPROM:
if (g_DebugComm) Console::Print(" REG_EEPROM"); break;
if (g_DebugComm) Name.append(" REG_EEPROM"); break;
case WM_SPACE_REGS1:
case WM_SPACE_REGS2:
switch(data[3])
{
case 0xa2:
if (g_DebugComm) Console::Print(" REG_SPEAKER"); break;
if (g_DebugComm) Name.append(" REG_SPEAKER"); break;
case 0xa4:
if (g_DebugComm) Console::Print(" REG_EXT"); break;
if (g_DebugComm) Name.append(" REG_EXT"); break;
case 0xb0:
if (g_DebugComm) Console::Print(" REG_IR"); break;
if (g_DebugComm) Name.append(" REG_IR"); break;
}
break;
}
break;
case WM_IR_PIXEL_CLOCK: // 0x13
case WM_IR_LOGIC: // 0x1a
if (g_DebugComm) Console::Print("WM_IR");
if (g_DebugComm) Name.append("WM_IR");
size = 1;
break;
case WM_SPEAKER_ENABLE: // 0x14
case WM_SPEAKER_MUTE:
if (g_DebugComm) Console::Print("WM_SPEAKER");
if (g_DebugComm) Name.append("WM_SPEAKER");
size = 1;
break;
default:
@ -603,7 +728,7 @@ void InterruptDebugging(bool Emu, const void* _pData)
{
std::string Temp = ArrayToString(data, size + 2, 0, 30);
//LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str());
Console::Print(": %s\n", Temp.c_str()); // No timestamp
Console::Print("%s: %s\n", Name.c_str(), Temp.c_str()); // No timestamp
//Console::Print(" (%s): %s\n", Tm(true).c_str(), Temp.c_str()); // Timestamp
}
}

View File

@ -71,14 +71,20 @@ struct SRecordingAll
extern bool g_RealWiiMotePresent;
extern bool g_RealWiiMoteInitialized;
extern bool g_EmulatedWiiMoteInitialized;
extern bool g_WiimoteUnexpectedDisconnect;
#ifdef _WIN32
extern HWND g_ParentHWND;
#endif
// Settings
extern accel_cal g_accel;
extern nu_cal g_nu;
// Debugging
extern bool g_DebugAccelerometer;
extern bool g_DebugData;
extern bool g_DebugComm;
extern bool g_DebugCustom;
// Update speed
extern int g_UpdateCounter;

View File

@ -300,6 +300,15 @@ struct accel_cal
wm_accel cal_g; /**< 1g difference around 0cal */
};
struct nu_js {
u8 max, min, center;
};
struct nu_cal
{
wm_accel cal_zero; // zero calibratio
nu_js jx; //
nu_js jy; //
};
#pragma pack(pop)

View File

@ -177,12 +177,6 @@ void ReadData()
// Copy Buffer to LastReport
memcpy(m_LastReport.m_PayLoad, pBuffer, MAX_PAYLOAD);
m_LastReportValid = true;
/* Check if the data reporting mode is okay. This should not cause any harm outside the dual mode
(being able to switch between the real and emulated wiimote) because WiiMoteEmu::g_ReportingMode
should always have the right reporting mode. */
if (g_EmulatorRunning && pBuffer[0] != WiiMoteEmu::g_ReportingMode)
SetDataReportingMode();
}
else
{
@ -327,89 +321,6 @@ void ClearEvents()
g_WiiMotes[i]->ClearEvents();
}
// Update the data reporting mode if we are switching between the emulated and the real Wiimote
void SetDataReportingMode(u8 ReportingMode)
{
// Don't allow this to run to often
if (Common::Timer::GetTimeSinceJan1970() == g_UpdateTime) return;
// Save the time
g_UpdateTime = Common::Timer::GetTimeSinceJan1970();
// Decide if we should we use custom values
if (ReportingMode == 0) ReportingMode = WiiMoteEmu::g_ReportingMode;
// Just in case this should happen
if (ReportingMode == 0) ReportingMode = 0x30;
// Shortcut
wiimote_t* wm = WiiMoteReal::g_WiiMotesFromWiiUse[0];
switch(ReportingMode) // See Wiimote_Update()
{
case WM_REPORT_CORE:
wiiuse_motion_sensing(wm, 0);
wiiuse_set_ir(wm, 0);
break;
case WM_REPORT_CORE_ACCEL:
wiiuse_motion_sensing(wm, 1);
wiiuse_set_ir(wm, 0);
break;
case WM_REPORT_CORE_ACCEL_IR12:
wiiuse_motion_sensing(wm, 1);
wiiuse_set_ir(wm, 1);
break;
case WM_REPORT_CORE_ACCEL_EXT16:
wiiuse_motion_sensing(wm, 1);
wiiuse_set_ir(wm, 0);
break;
case WM_REPORT_CORE_ACCEL_IR10_EXT6:
wiiuse_motion_sensing(wm, 1);
wiiuse_set_ir(wm, 1);
break;
}
/* On occasion something in this function caused an instant reboot of Windows XP SP3
with Bluesoleil 6. So I'm trying to use the API functions to reach the same goal. */
/*byte DataReporting[MAX_PAYLOAD];
byte IR0[MAX_PAYLOAD];
byte IR1[MAX_PAYLOAD];
DataReporting[0] = 0x12; // Report 0x12
DataReporting[1] = 0x06; // Continuous reporting
DataReporting[2] = ReportingMode; // Reporting mode
IR0[0] = 0x13; // Report 0x13
if (IR) IR0[1] = 0x06; else IR0[1] = 0x02;
IR1[0] = 0x1a; // Report 0x1a
if (IR) IR1[1] = 0x06; else IR1[1] = 0x02;
// Calibrate IR
static const u8 IR_0[] = { 0x16, 0x04, 0xb0, 0x00, 0x30, 0x01,
0x01 };
static const u8 IR_1[] = { 0x16, 0x04, 0xb0, 0x00, 0x00, 0x09,
0x02, 0x00, 0x00, 0x71, 0x01, 0x00, 0xaa, 0x00, 0x64 };
static const u8 IR_2[] = { 0x16, 0x04, 0xb0, 0x00, 0x1a, 0x02,
0x63, 0x03 };
static const u8 IR_3[] = { 0x16, 0x04, 0xb0, 0x00, 0x33, 0x01,
0x03 };
static const u8 IR_4[] = { 0x16, 0x04, 0xb0, 0x00, 0x30, 0x01,
0x08 };
wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)DataReporting, MAX_PAYLOAD);
wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR0, MAX_PAYLOAD);
wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR1, MAX_PAYLOAD);
if (IR)
{
wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_0, MAX_PAYLOAD);
wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_1, MAX_PAYLOAD);
wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_2, MAX_PAYLOAD);
wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_3, MAX_PAYLOAD);
wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_4, MAX_PAYLOAD);
}*/
}
// Flash lights, and if connecting, also rumble
void FlashLights(bool Connect)
{
@ -458,7 +369,7 @@ int Initialize()
for (int i = 0; i < g_NumberOfWiiMotes; i++)
g_WiiMotes[i] = new CWiiMote(i + 1, g_WiiMotesFromWiiUse[i]);
// Create a nee thread and start listening for Wiimote data
// Create a new thread and start listening for Wiimote data
if (g_NumberOfWiiMotes > 0)
g_pReadThread = new Common::Thread(ReadWiimote_ThreadFunc, NULL);
@ -472,12 +383,11 @@ int Initialize()
byte *data = (byte*)malloc(sizeof(byte) * sizeof(WiiMoteEmu::EepromData_0));
wiiuse_read_data(g_WiiMotesFromWiiUse[0], data, 0, sizeof(WiiMoteEmu::EepromData_0));
// Update the global extension settings
g_Config.bNunchuckConnected = (g_WiiMotesFromWiiUse[0]->exp.type == EXP_NUNCHUK);
g_Config.bClassicControllerConnected = (g_WiiMotesFromWiiUse[0]->exp.type == EXP_CLASSIC);
// Don't run the Wiimote thread if no wiimotes were found
if (g_NumberOfWiiMotes > 0) g_Shutdown = false;
// Initialized
if (g_NumberOfWiiMotes > 0) { g_RealWiiMoteInitialized = true; g_Shutdown = false; }
// Initialized, even if we didn't find a Wiimote
g_RealWiiMoteInitialized = true;
return g_NumberOfWiiMotes;
}
@ -510,9 +420,6 @@ void Shutdown(void)
// Clean up wiiuse
wiiuse_cleanup(g_WiiMotesFromWiiUse, g_NumberOfWiiMotes);
// Uninitialized
g_RealWiiMoteInitialized = false;
// Uninitialized
g_RealWiiMoteInitialized = false;
g_RealWiiMotePresent = false;

View File

@ -42,7 +42,10 @@ void Update();
void SendAcc(u8 _ReportID);
void SetDataReportingMode(u8 ReportingMode = 0);
void ClearEvents();
// The alternative Wiimote loop
void ReadWiimote();
bool IRDataOK(struct wiimote_t* wm);
#ifndef EXCLUDE_H
extern wiimote_t** g_WiiMotesFromWiiUse;