Wiimote:
1) I fixed the emulated Nunchuck in Zelda - TP, however I chose the minimum workable delay time that worked in my PC, in fact it's so short that the Nunchuck still fails sometimes. If you have a very fast PC or something like that so that the Nunchuck still don't work please let me know. 2) I also made the Wiimote work after Stop and Start 3) I changed /Dev/USB to initialize the emulated Wiimote directly after ScanEnable, not wait for any countdown git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1814 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
6125efabb1
commit
fa27a97fbb
|
@ -123,7 +123,7 @@ int wprintf(char *fmt, ...)
|
||||||
if(__fStdOut)
|
if(__fStdOut)
|
||||||
{
|
{
|
||||||
fprintf(__fStdOut, s);
|
fprintf(__fStdOut, s);
|
||||||
//fflush(__fStdOut); // Write file now, don't wait
|
fflush(__fStdOut); // Write file now, don't wait
|
||||||
}
|
}
|
||||||
|
|
||||||
return(cnt);
|
return(cnt);
|
||||||
|
|
|
@ -16,11 +16,14 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MM_COMMON_H
|
||||||
|
#define MM_COMMON_H
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Declarations and definitions
|
// Declarations and definitions
|
||||||
// ¯¯¯¯¯¯¯¯¯¯
|
// ¯¯¯¯¯¯¯¯¯¯
|
||||||
void StartConsoleWin(int width, int height, char* fname);
|
void StartConsoleWin(int width = 100, int height = 2000, char* fname = "Console");
|
||||||
int wprintf(char *fmt, ...);
|
int wprintf(char *fmt, ...);
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
|
|
||||||
|
#endif // MM_COMMON_H
|
|
@ -442,7 +442,11 @@ void CFrame::MM_OnLog(wxCommandEvent& event)
|
||||||
MusicMod::bShowConsole = !MusicMod::bShowConsole;
|
MusicMod::bShowConsole = !MusicMod::bShowConsole;
|
||||||
|
|
||||||
if(MusicMod::bShowConsole)
|
if(MusicMod::bShowConsole)
|
||||||
{ MusicMod::ShowConsole(); Player_Console(true); }
|
/* What we do here is run StartConsoleWin() in Common directly after each
|
||||||
|
other first in the exe then in the DLL, sometimes this would give me a rampant memory
|
||||||
|
usage increase until the exe crashed at 700 MB memory usage or something like that.
|
||||||
|
For that reason I'm trying to sleep for a moment between them here. */
|
||||||
|
{ MusicMod::ShowConsole(); Sleep(100); Player_Console(true); }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined (_WIN32)
|
#if defined (_WIN32)
|
||||||
|
|
|
@ -70,6 +70,23 @@ extern int GlobalVolume;
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
// =======================================================================================
|
||||||
|
// Supported music files
|
||||||
|
// ---------------------------------------------------------------------------------------
|
||||||
|
bool CheckFileEnding(std::string FileName)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(FileName.find(".adp") != std::string::npos) // 1080 Avalanche, Crash Bandicoot etc
|
||||||
|
|| (FileName.find(".afc") != std::string::npos) // Zelda WW
|
||||||
|
|| (FileName.find(".ast") != std::string::npos) // Zelda TP, Mario Kart
|
||||||
|
|| (FileName.find(".dsp") != std::string::npos) // Metroid Prime
|
||||||
|
|| (FileName.find(".hps") != std::string::npos) // SSB Melee
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// =======================================================================================
|
||||||
|
|
||||||
|
|
||||||
// =======================================================================================
|
// =======================================================================================
|
||||||
// A function to sort the filelist table after offset
|
// A function to sort the filelist table after offset
|
||||||
|
@ -187,25 +204,6 @@ void Main(std::string FileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// =======================================================================================
|
|
||||||
// Supported music files
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
bool CheckFileEnding(std::string FileName)
|
|
||||||
{
|
|
||||||
if (
|
|
||||||
(FileName.find(".adp") != std::string::npos) // 1080 Avalanche, Crash Bandicoot etc
|
|
||||||
|| (FileName.find(".afc") != std::string::npos) // Zelda WW
|
|
||||||
|| (FileName.find(".ast") != std::string::npos) // Zelda TP, Mario Kart
|
|
||||||
|| (FileName.find(".dsp") != std::string::npos) // Metroid Prime
|
|
||||||
|| (FileName.find(".hps") != std::string::npos) // SSB Melee
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// =======================================================================================
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =======================================================================================
|
// =======================================================================================
|
||||||
// Check if we should play this file
|
// Check if we should play this file
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -15,6 +15,19 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// File description
|
||||||
|
/* ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
|
|
||||||
|
All plugins from Core > Plugins are loaded and unloaded with this class when Dolpin is started
|
||||||
|
and stopped.
|
||||||
|
//////////////////////////////////////*/
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Includes
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -27,6 +40,9 @@
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
#include "DynamicLibrary.h"
|
#include "DynamicLibrary.h"
|
||||||
|
#include "../../../../Branches/MusicMod/Common/Src/Console.h"
|
||||||
|
///////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
DynamicLibrary::DynamicLibrary()
|
DynamicLibrary::DynamicLibrary()
|
||||||
{
|
{
|
||||||
|
@ -138,9 +154,10 @@ void* DynamicLibrary::Get(const char* funcname) const
|
||||||
retval = dlsym(library, funcname);
|
retval = dlsym(library, funcname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!retval) {
|
if (!retval)
|
||||||
|
{
|
||||||
LOG(MASTER_LOG, "Symbol %s missing in %s (error: %s)\n", funcname, library_file.c_str(), GetLastErrorAsString().c_str());
|
LOG(MASTER_LOG, "Symbol %s missing in %s (error: %s)\n", funcname, library_file.c_str(), GetLastErrorAsString().c_str());
|
||||||
PanicAlert("Symbol %s missing in %s (error: %s)\n", funcname, library_file.c_str(), GetLastErrorAsString().c_str());
|
//PanicAlert("Symbol %s missing in %s (error: %s)\n", funcname, library_file.c_str(), GetLastErrorAsString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -121,6 +121,10 @@ bool CBoot::LoadMapFromFilename(const std::string &_rFilename, const char *_game
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Load a GC or Wii BIOS file
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
bool CBoot::Load_BIOS(const std::string& _rBiosFilename)
|
bool CBoot::Load_BIOS(const std::string& _rBiosFilename)
|
||||||
{
|
{
|
||||||
bool bResult = false;
|
bool bResult = false;
|
||||||
|
@ -129,6 +133,7 @@ bool CBoot::Load_BIOS(const std::string& _rBiosFilename)
|
||||||
{
|
{
|
||||||
if (pFile->GetSize() >= 1024*1024*2)
|
if (pFile->GetSize() >= 1024*1024*2)
|
||||||
{
|
{
|
||||||
|
// Write it to memory
|
||||||
u32 CopySize = (u32)pFile->GetSize() - 0x820;
|
u32 CopySize = (u32)pFile->GetSize() - 0x820;
|
||||||
u8* pData = pFile->Lock(0x820, CopySize);
|
u8* pData = pFile->Lock(0x820, CopySize);
|
||||||
Memory::WriteBigEData(pData, 0x81300000, CopySize);
|
Memory::WriteBigEData(pData, 0x81300000, CopySize);
|
||||||
|
@ -143,7 +148,12 @@ bool CBoot::Load_BIOS(const std::string& _rBiosFilename)
|
||||||
delete pFile;
|
delete pFile;
|
||||||
return bResult;
|
return bResult;
|
||||||
}
|
}
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Third boot step after BootManager and Core. See Call schedule in BootManager.cpp
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
bool CBoot::BootUp(const SCoreStartupParameter& _StartupPara)
|
bool CBoot::BootUp(const SCoreStartupParameter& _StartupPara)
|
||||||
{
|
{
|
||||||
const bool bDebugIsoBootup = false;
|
const bool bDebugIsoBootup = false;
|
||||||
|
@ -188,6 +198,7 @@ bool CBoot::BootUp(const SCoreStartupParameter& _StartupPara)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// If we can't load the BIOS file we use the HLE BIOS instead
|
||||||
if (!Load_BIOS(_StartupPara.m_strBios))
|
if (!Load_BIOS(_StartupPara.m_strBios))
|
||||||
{
|
{
|
||||||
// fails to load a BIOS so HLE it
|
// fails to load a BIOS so HLE it
|
||||||
|
|
|
@ -41,7 +41,9 @@ void CBoot::RunFunction(u32 _iAddr)
|
||||||
PowerPC::SingleStep();
|
PowerPC::SingleStep();
|
||||||
}
|
}
|
||||||
|
|
||||||
// BIOS HLE:
|
// __________________________________________________________________________________________________
|
||||||
|
//
|
||||||
|
// GameCube BIOS HLE:
|
||||||
// copy the apploader to 0x81200000
|
// copy the apploader to 0x81200000
|
||||||
// execute the apploader, function by function, using the above utility.
|
// execute the apploader, function by function, using the above utility.
|
||||||
void CBoot::EmulatedBIOS(bool _bDebug)
|
void CBoot::EmulatedBIOS(bool _bDebug)
|
||||||
|
@ -159,7 +161,7 @@ void CBoot::EmulatedBIOS(bool _bDebug)
|
||||||
|
|
||||||
// __________________________________________________________________________________________________
|
// __________________________________________________________________________________________________
|
||||||
//
|
//
|
||||||
// BIOS HLE:
|
// Wii BIOS HLE:
|
||||||
// copy the apploader to 0x81200000
|
// copy the apploader to 0x81200000
|
||||||
// execute the apploader
|
// execute the apploader
|
||||||
//
|
//
|
||||||
|
@ -167,6 +169,7 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
|
||||||
{
|
{
|
||||||
LOG(BOOT, "Faking Wii BIOS...");
|
LOG(BOOT, "Faking Wii BIOS...");
|
||||||
|
|
||||||
|
// See if we have a memory dump to boot
|
||||||
FILE* pDump = fopen(FULL_WII_SYS_DIR "dump_0x0000_0x4000.bin", "rb");
|
FILE* pDump = fopen(FULL_WII_SYS_DIR "dump_0x0000_0x4000.bin", "rb");
|
||||||
if (pDump != NULL)
|
if (pDump != NULL)
|
||||||
{
|
{
|
||||||
|
@ -301,10 +304,11 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
|
||||||
after this check during booting. */
|
after this check during booting. */
|
||||||
VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
|
VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
|
||||||
Memory::Write_U8(0x80, 0x00003184);
|
Memory::Write_U8(0x80, 0x00003184);
|
||||||
|
// ================
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// apploader
|
// Execute the apploader
|
||||||
if (VolumeHandler::IsValid() && VolumeHandler::IsWii())
|
if (VolumeHandler::IsValid() && VolumeHandler::IsWii())
|
||||||
{
|
{
|
||||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||||
|
@ -345,12 +349,16 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
|
||||||
u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+8);
|
u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+8);
|
||||||
|
|
||||||
// iAppLoaderInit
|
// iAppLoaderInit
|
||||||
LOG(BOOT, "Call iAppLoaderInit");
|
LOG(BOOT, "Run iAppLoaderInit");
|
||||||
PowerPC::ppcState.gpr[3] = 0x81300000;
|
PowerPC::ppcState.gpr[3] = 0x81300000;
|
||||||
RunFunction(iAppLoaderInit);
|
RunFunction(iAppLoaderInit);
|
||||||
|
|
||||||
// iAppLoaderMain
|
/* Let the apploader load the exe to memory. At this point I get an unknwon IPC command
|
||||||
LOG(BOOT, "Call iAppLoaderMain");
|
(command zero) when I load Wii Sports or other games a second time. I don't notice
|
||||||
|
any side effects however. It's a little disconcerning however that Start after Stop
|
||||||
|
behaves differently than the first Start after starting Dolphin. It means something
|
||||||
|
was not reset correctly. */
|
||||||
|
LOG(BOOT, "Run iAppLoaderMain");
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
PowerPC::ppcState.gpr[3] = 0x81300004;
|
PowerPC::ppcState.gpr[3] = 0x81300004;
|
||||||
|
@ -368,7 +376,7 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
|
||||||
} while(PowerPC::ppcState.gpr[3] != 0x00);
|
} while(PowerPC::ppcState.gpr[3] != 0x00);
|
||||||
|
|
||||||
// iAppLoaderClose
|
// iAppLoaderClose
|
||||||
LOG(BOOT, "call iAppLoaderClose");
|
LOG(BOOT, "Run iAppLoaderClose");
|
||||||
RunFunction(iAppLoaderClose);
|
RunFunction(iAppLoaderClose);
|
||||||
|
|
||||||
// Load patches and run startup patches
|
// Load patches and run startup patches
|
||||||
|
|
|
@ -94,7 +94,6 @@ void Callback_WiimoteInput(u16 _channelID, const void* _pData, u32 _Size);
|
||||||
|
|
||||||
// For keyboard shortcuts.
|
// For keyboard shortcuts.
|
||||||
void Callback_KeyPress(int key, bool shift, bool control);
|
void Callback_KeyPress(int key, bool shift, bool control);
|
||||||
|
|
||||||
TPeekMessages Callback_PeekMessages = NULL;
|
TPeekMessages Callback_PeekMessages = NULL;
|
||||||
TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL;
|
TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL;
|
||||||
|
|
||||||
|
@ -106,6 +105,7 @@ TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL;
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
bool g_bHwInit = false;
|
bool g_bHwInit = false;
|
||||||
|
bool g_bRealWiimote = false;
|
||||||
HWND g_pWindowHandle = NULL;
|
HWND g_pWindowHandle = NULL;
|
||||||
Common::Thread* g_pThread = NULL;
|
Common::Thread* g_pThread = NULL;
|
||||||
|
|
||||||
|
@ -115,13 +115,50 @@ Common::Event emuThreadGoing;
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Display messages and return values
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯
|
||||||
bool PanicAlertToVideo(const char* text, bool yes_no)
|
bool PanicAlertToVideo(const char* text, bool yes_no)
|
||||||
{
|
{
|
||||||
DisplayMessage(text, 3000);
|
DisplayMessage(text, 3000);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from GUI thread
|
void DisplayMessage(const std::string &message, int time_in_ms)
|
||||||
|
{
|
||||||
|
PluginVideo::Video_AddMessage(message.c_str(), time_in_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayMessage(const char *message, int time_in_ms)
|
||||||
|
{
|
||||||
|
PluginVideo::Video_AddMessage(message, time_in_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Callback_DebuggerBreak()
|
||||||
|
{
|
||||||
|
CCPU::EnableStepping(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SCoreStartupParameter& GetStartupParameter()
|
||||||
|
{
|
||||||
|
return g_CoreStartupParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GetWindowHandle()
|
||||||
|
{
|
||||||
|
return g_pWindowHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetRealWiimote()
|
||||||
|
{
|
||||||
|
return g_bRealWiimote;
|
||||||
|
}
|
||||||
|
/////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This is called from the GUI thread. See the booting call schedule in BootManager.cpp
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯
|
||||||
bool Init(const SCoreStartupParameter _CoreParameter)
|
bool Init(const SCoreStartupParameter _CoreParameter)
|
||||||
{
|
{
|
||||||
if (g_pThread != NULL) {
|
if (g_pThread != NULL) {
|
||||||
|
@ -153,6 +190,7 @@ bool Init(const SCoreStartupParameter _CoreParameter)
|
||||||
|
|
||||||
emuThreadGoing.Init();
|
emuThreadGoing.Init();
|
||||||
|
|
||||||
|
// This will execute EmuThread() further down in this file
|
||||||
g_pThread = new Common::Thread(EmuThread, (void*)&g_CoreStartupParameter);
|
g_pThread = new Common::Thread(EmuThread, (void*)&g_CoreStartupParameter);
|
||||||
|
|
||||||
emuThreadGoing.Wait();
|
emuThreadGoing.Wait();
|
||||||
|
@ -168,16 +206,6 @@ bool Init(const SCoreStartupParameter _CoreParameter)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayMessage(const std::string &message, int time_in_ms)
|
|
||||||
{
|
|
||||||
PluginVideo::Video_AddMessage(message.c_str(), time_in_ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayMessage(const char *message, int time_in_ms)
|
|
||||||
{
|
|
||||||
PluginVideo::Video_AddMessage(message, time_in_ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Called from GUI thread or VI thread
|
// Called from GUI thread or VI thread
|
||||||
void Stop() // - Hammertime!
|
void Stop() // - Hammertime!
|
||||||
|
@ -213,21 +241,6 @@ void Stop() // - Hammertime!
|
||||||
Host_SetWaitCursor(false);
|
Host_SetWaitCursor(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Callback_DebuggerBreak()
|
|
||||||
{
|
|
||||||
CCPU::EnableStepping(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const SCoreStartupParameter& GetStartupParameter()
|
|
||||||
{
|
|
||||||
return g_CoreStartupParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* GetWindowHandle()
|
|
||||||
{
|
|
||||||
return g_pWindowHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Create the CPU thread
|
// Create the CPU thread
|
||||||
|
@ -280,7 +293,7 @@ THREAD_RETURN CpuThread(void *pArg)
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Initalize plugins and create emulation thread
|
// Initalize plugins and create emulation thread
|
||||||
// ¯¯¯¯¯¯¯¯¯¯
|
// ¯¯¯¯¯¯¯¯¯¯
|
||||||
/* Call browser: Init():g_pThread(). See the BootManager.cpp file description for a completel
|
/* Call browser: Init():g_pThread(). See the BootManager.cpp file description for a complete
|
||||||
call schedule. */
|
call schedule. */
|
||||||
THREAD_RETURN EmuThread(void *pArg)
|
THREAD_RETURN EmuThread(void *pArg)
|
||||||
{
|
{
|
||||||
|
@ -348,7 +361,8 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||||
WiimoteInitialize.hWnd = g_pWindowHandle;
|
WiimoteInitialize.hWnd = g_pWindowHandle;
|
||||||
WiimoteInitialize.pLog = Callback_WiimoteLog;
|
WiimoteInitialize.pLog = Callback_WiimoteLog;
|
||||||
WiimoteInitialize.pWiimoteInput = Callback_WiimoteInput;
|
WiimoteInitialize.pWiimoteInput = Callback_WiimoteInput;
|
||||||
PluginWiimote::Wiimote_Initialize(WiimoteInitialize);
|
// Wait for Wiiuse to find the number of connected Wiimotes
|
||||||
|
g_bRealWiimote = PluginWiimote::Wiimote_Initialize(WiimoteInitialize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The hardware is initialized.
|
// The hardware is initialized.
|
||||||
|
|
|
@ -51,13 +51,14 @@ namespace Core
|
||||||
void SaveState();
|
void SaveState();
|
||||||
void LoadState();
|
void LoadState();
|
||||||
|
|
||||||
// get core parameters
|
// Get core parameters
|
||||||
extern SCoreStartupParameter g_CoreStartupParameter; //uck
|
extern SCoreStartupParameter g_CoreStartupParameter; //uck
|
||||||
const SCoreStartupParameter& GetStartupParameter();
|
const SCoreStartupParameter& GetStartupParameter();
|
||||||
|
|
||||||
// make a screen shot
|
// Make a screen shot
|
||||||
bool MakeScreenshot(const std::string& _rFilename);
|
bool MakeScreenshot(const std::string& _rFilename);
|
||||||
void* GetWindowHandle();
|
void* GetWindowHandle();
|
||||||
|
bool GetRealWiimote();
|
||||||
|
|
||||||
extern bool bReadTrace;
|
extern bool bReadTrace;
|
||||||
extern bool bWriteTrace;
|
extern bool bWriteTrace;
|
||||||
|
|
|
@ -15,6 +15,51 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// File description: This file control all system timers
|
||||||
|
/* -------------
|
||||||
|
"Time" is measured in frames, not time: These update frequencies are determined by the passage
|
||||||
|
of frames. So if a game runs slow, on a slow computer for example, these updates will occur
|
||||||
|
less frequently. This makes sense because almost all console games are controlled by frames
|
||||||
|
rather than time, so if a game can't keep up with the normal framerate all animations and
|
||||||
|
actions slows down and the game runs to slow. This is different from PC games that are are
|
||||||
|
often controlled by time instead and may not have maximum framerates.
|
||||||
|
|
||||||
|
However, I'm not sure if the Bluetooth communication for the Wiimote is entirely frame
|
||||||
|
dependent, the timing problems with the ack command in Zelda - TP may be related to
|
||||||
|
time rather than frames? For now the IPC_HLE_PERIOD is frame dependet, but bcause of
|
||||||
|
different conditions on the way to PluginWiimote::Wiimote_Update() the updates may actually
|
||||||
|
be time related after all, or not?
|
||||||
|
|
||||||
|
I'm not sure about this but the text below seems to assume that 60 fps means that the game
|
||||||
|
runs in the normal intended speed. In that case an update time of [GetTicksPerSecond() / 60]
|
||||||
|
would mean one update per frame and [GetTicksPerSecond() / 60] would mean four updates per
|
||||||
|
frame.
|
||||||
|
|
||||||
|
|
||||||
|
IPC_HLE_PERIOD: For the Wiimote this is the call scedule:
|
||||||
|
IPC_HLE_UpdateCallback() // In this file
|
||||||
|
|
||||||
|
// This function seems to call all devices' Update() function four times per frame
|
||||||
|
WII_IPC_HLE_Interface::Update()
|
||||||
|
|
||||||
|
// If the AclFrameQue is empty this will call Wiimote_Update() and make it send
|
||||||
|
the current input status to the game. I'm not sure if this occurs approximately
|
||||||
|
once every frame or if the frequency is not exactly tied to rendered frames
|
||||||
|
CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||||
|
PluginWiimote::Wiimote_Update()
|
||||||
|
|
||||||
|
// This is also a device updated by WII_IPC_HLE_Interface::Update() but it doesn't
|
||||||
|
seem to ultimately call PluginWiimote::Wiimote_Update(). However it can be called
|
||||||
|
by the /dev/usb/oh1 device if the AclFrameQue is empty.
|
||||||
|
CWII_IPC_HLE_WiiMote::Update()
|
||||||
|
//////////////////////////*/
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Inlude
|
||||||
|
// -------------
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "../PatchEngine.h"
|
#include "../PatchEngine.h"
|
||||||
#include "SystemTimers.h"
|
#include "SystemTimers.h"
|
||||||
|
@ -32,10 +77,15 @@
|
||||||
#include "../IPC_HLE/WII_IPC_HLE.h"
|
#include "../IPC_HLE/WII_IPC_HLE.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
|
/////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
namespace SystemTimers
|
namespace SystemTimers
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Declarations and definitions
|
||||||
|
// -------------
|
||||||
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||||
|
|
||||||
s64 fakeDec;
|
s64 fakeDec;
|
||||||
|
@ -85,6 +135,8 @@ int
|
||||||
// Once every 2 frame-period should be enough.
|
// Once every 2 frame-period should be enough.
|
||||||
// Assuming game's frame-finish-watchdog wait more than 2 emulated frame-period before starting its mess.
|
// Assuming game's frame-finish-watchdog wait more than 2 emulated frame-period before starting its mess.
|
||||||
FAKE_GP_WATCHDOG_PERIOD = GetTicksPerSecond() / 30;
|
FAKE_GP_WATCHDOG_PERIOD = GetTicksPerSecond() / 30;
|
||||||
|
///////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
u32 GetTicksPerSecond()
|
u32 GetTicksPerSecond()
|
||||||
{
|
{
|
||||||
|
|
|
@ -399,8 +399,11 @@ void ExecuteCommand(u32 _Address)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown Command %i (0x%08x)", Command, _Address);
|
_dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, _Address);
|
||||||
|
// Break on the same terms as the _dbg_assert_msg_, if LOGGING was defined
|
||||||
|
#ifdef LOGGING
|
||||||
CCPU::Break();
|
CCPU::Break();
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,16 +15,28 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Include
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
#include "WII_IPC_HLE_Device_usb.h"
|
#include "WII_IPC_HLE_Device_usb.h"
|
||||||
#include "../Plugins/Plugin_Wiimote.h"
|
#include "../Plugins/Plugin_Wiimote.h"
|
||||||
|
|
||||||
|
#include "../Core.h" // Local core functions
|
||||||
#include "../Debugger/Debugger_SymbolMap.h"
|
#include "../Debugger/Debugger_SymbolMap.h"
|
||||||
#include "../Host.h"
|
#include "../Host.h"
|
||||||
|
#include "../../../../Branches/MusicMod/Common/Src/Console.h"
|
||||||
|
///////////////////////
|
||||||
|
|
||||||
// ugly hacks for "SendEventNumberOfCompletedPackets"
|
|
||||||
|
// Ugly hacks for "SendEventNumberOfCompletedPackets"
|
||||||
int g_HCICount = 0;
|
int g_HCICount = 0;
|
||||||
int g_GlobalHandle = 0;
|
int g_GlobalHandle = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The device class
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _DeviceID, const std::string& _rDeviceName)
|
CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _DeviceID, const std::string& _rDeviceName)
|
||||||
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
|
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
|
||||||
, m_PINType(0)
|
, m_PINType(0)
|
||||||
|
@ -58,6 +70,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_usb_oh1_57e_305::~CWII_IPC_HLE_Device_usb_oh1_57e_305()
|
CWII_IPC_HLE_Device_usb_oh1_57e_305::~CWII_IPC_HLE_Device_usb_oh1_57e_305()
|
||||||
{}
|
{}
|
||||||
|
///////////////////////////
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
|
@ -290,7 +303,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLFrame(u16 _ConnectionHandle, u8
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
/* This is called from WII_IPC_HLE_Interface::Update() */
|
/* See IPC_HLE_PERIOD in SystemTimers.cpp for a documentation of this update. */
|
||||||
// ----------------
|
// ----------------
|
||||||
u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||||
{
|
{
|
||||||
|
@ -387,19 +400,27 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||||
before we initiate the connection. To avoid doing this for GC games we also
|
before we initiate the connection. To avoid doing this for GC games we also
|
||||||
want m_LocalName from CommandWriteLocalName() to be "Wii".
|
want m_LocalName from CommandWriteLocalName() to be "Wii".
|
||||||
|
|
||||||
FiRES: TODO find a good solution to do this */
|
FiRES: TODO find a good solution to do this
|
||||||
|
JP: Solution to what? When to run SendEventRequestConnection()?
|
||||||
|
*/
|
||||||
// -------------------------
|
// -------------------------
|
||||||
static bool test = true;
|
|
||||||
|
|
||||||
// Why do we need this? 0 worked with the emulated wiimote in all games I tried
|
/* I disabled this and disable m_ScanEnable instead to avoid running SendEventRequestConnection()
|
||||||
static int counter = 1000;
|
again. */
|
||||||
|
//static bool test = true;
|
||||||
|
|
||||||
if (test && !strcasecmp(m_LocalName, "Wii") && (m_ScanEnable & 0x2))
|
/* Why do we need this? 0 worked with the emulated wiimote in all games I tried. Do we have to
|
||||||
|
wait for wiiuse_init() and wiiuse_find() for a real Wiimote here? I'm testing
|
||||||
|
this new method of not waiting at all if there are no real Wiimotes. Please let me know
|
||||||
|
if it doesn't work. */
|
||||||
|
static int counter = (Core::GetRealWiimote() ? 1000 : 0);
|
||||||
|
|
||||||
|
if (!strcasecmp(m_LocalName, "Wii") && (m_ScanEnable & 0x2))
|
||||||
{
|
{
|
||||||
counter--;
|
counter--;
|
||||||
if (counter < 0)
|
if (counter < 0)
|
||||||
{
|
{
|
||||||
test = false;
|
//test = false;
|
||||||
for (size_t i=0; i < m_WiiMotes.size(); i++)
|
for (size_t i=0; i < m_WiiMotes.size(); i++)
|
||||||
{
|
{
|
||||||
if (m_WiiMotes[i].EventPagingChanged(2))
|
if (m_WiiMotes[i].EventPagingChanged(2))
|
||||||
|
@ -564,8 +585,15 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRemoteNameReq(bdaddr_t _bd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////
|
||||||
|
/* This is called from Update() after ScanEnable has been enabled. */
|
||||||
|
// ¯¯¯¯¯¯¯¯¯
|
||||||
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestConnection(CWII_IPC_HLE_WiiMote& _rWiiMote)
|
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestConnection(CWII_IPC_HLE_WiiMote& _rWiiMote)
|
||||||
{
|
{
|
||||||
|
// We have to disable scan now to avoid running this function over and over again
|
||||||
|
m_ScanEnable = 0;
|
||||||
|
|
||||||
SQueuedEvent Event(sizeof(SHCIEventRequestConnection), 0);
|
SQueuedEvent Event(sizeof(SHCIEventRequestConnection), 0);
|
||||||
|
|
||||||
SHCIEventRequestConnection* pEventRequestConnection = (SHCIEventRequestConnection*)Event.m_buffer;
|
SHCIEventRequestConnection* pEventRequestConnection = (SHCIEventRequestConnection*)Event.m_buffer;
|
||||||
|
@ -601,6 +629,8 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestConnection(CWII_IPC_HL
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestLinkKey(bdaddr_t _bd)
|
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestLinkKey(bdaddr_t _bd)
|
||||||
{
|
{
|
||||||
|
@ -1377,7 +1407,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWritePageTimeOut(u8* _Input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////
|
||||||
|
/* This will enable ScanEnable so that Update() can start the Wiimote. */
|
||||||
|
// ¯¯¯¯¯¯¯¯¯
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteScanEnable(u8* _Input)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteScanEnable(u8* _Input)
|
||||||
{
|
{
|
||||||
// Command parameters
|
// Command parameters
|
||||||
|
@ -1404,7 +1436,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteScanEnable(u8* _Input)
|
||||||
|
|
||||||
SendEventCommandComplete(HCI_CMD_WRITE_SCAN_ENABLE, &Reply, sizeof(hci_write_scan_enable_rp));
|
SendEventCommandComplete(HCI_CMD_WRITE_SCAN_ENABLE, &Reply, sizeof(hci_write_scan_enable_rp));
|
||||||
}
|
}
|
||||||
|
/////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteInquiryMode(u8* _Input)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteInquiryMode(u8* _Input)
|
||||||
|
|
|
@ -29,7 +29,7 @@ void UnloadPlugin();
|
||||||
// Function Types
|
// Function Types
|
||||||
typedef void (__cdecl* TGetDllInfo)(PLUGIN_INFO*);
|
typedef void (__cdecl* TGetDllInfo)(PLUGIN_INFO*);
|
||||||
typedef void (__cdecl* TDllConfig)(HWND);
|
typedef void (__cdecl* TDllConfig)(HWND);
|
||||||
typedef void (__cdecl* TWiimote_Initialize)(SWiimoteInitialize);
|
typedef bool (__cdecl* TWiimote_Initialize)(SWiimoteInitialize);
|
||||||
typedef void (__cdecl* TWiimote_Shutdown)();
|
typedef void (__cdecl* TWiimote_Shutdown)();
|
||||||
typedef void (__cdecl* TWiimote_Update)();
|
typedef void (__cdecl* TWiimote_Update)();
|
||||||
typedef void (__cdecl* TWiimote_Output)(u16 _channelID, const void* _pData, u32 _Size);
|
typedef void (__cdecl* TWiimote_Output)(u16 _channelID, const void* _pData, u32 _Size);
|
||||||
|
|
|
@ -30,7 +30,8 @@
|
||||||
BootManager.cpp BootCore
|
BootManager.cpp BootCore
|
||||||
Core Core.cpp Init Thread creation
|
Core Core.cpp Init Thread creation
|
||||||
EmuThread Calls CBoot::BootUp
|
EmuThread Calls CBoot::BootUp
|
||||||
Boot.cpp
|
Boot.cpp CBoot::BootUp()
|
||||||
|
CBoot::EmulatedBIOS_Wii() / GC() or Load_BIOS()
|
||||||
*/
|
*/
|
||||||
// =============
|
// =============
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@
|
||||||
#include "ConfigMain.h"
|
#include "ConfigMain.h"
|
||||||
#include "Frame.h"
|
#include "Frame.h"
|
||||||
#include "CodeWindow.h"
|
#include "CodeWindow.h"
|
||||||
|
#include "../../../../Branches/MusicMod/Common/Src/Console.h"
|
||||||
#ifdef MUSICMOD
|
#ifdef MUSICMOD
|
||||||
#include "../../../Branches/MusicMod/Main/Src/Main.h" // MusicMod
|
#include "../../../Branches/MusicMod/Main/Src/Main.h" // MusicMod
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -56,6 +56,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DolphinWX", "Core\DolphinWX
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{48AD7E0A-25B1-4974-A1E3-03F8C438D34F} = {48AD7E0A-25B1-4974-A1E3-03F8C438D34F}
|
{48AD7E0A-25B1-4974-A1E3-03F8C438D34F} = {48AD7E0A-25B1-4974-A1E3-03F8C438D34F}
|
||||||
{0318BA30-EF48-441A-9E10-DC85EFAE39F0} = {0318BA30-EF48-441A-9E10-DC85EFAE39F0}
|
{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}
|
{71B16F46-0B00-4EDA-B253-D6D9D03A215C} = {71B16F46-0B00-4EDA-B253-D6D9D03A215C}
|
||||||
{33546D62-7F34-4EA6-A88E-D538B36E16BF} = {33546D62-7F34-4EA6-A88E-D538B36E16BF}
|
{33546D62-7F34-4EA6-A88E-D538B36E16BF} = {33546D62-7F34-4EA6-A88E-D538B36E16BF}
|
||||||
{DE7C596C-CBC4-4278-8909-146D63990803} = {DE7C596C-CBC4-4278-8909-146D63990803}
|
{DE7C596C-CBC4-4278-8909-146D63990803} = {DE7C596C-CBC4-4278-8909-146D63990803}
|
||||||
|
@ -240,7 +241,6 @@ Global
|
||||||
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
|
{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}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||||
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|Win32.ActiveCfg = Release|Win32
|
{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.ActiveCfg = Release|x64
|
||||||
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|x64.Build.0 = Release|x64
|
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|x64.Build.0 = Release|x64
|
||||||
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9}.Debug|Win32.ActiveCfg = Debug|Win32
|
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
@ -322,8 +322,10 @@ Global
|
||||||
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Debug|Win32.ActiveCfg = Debug|Win32
|
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Debug|x64.ActiveCfg = Debug|x64
|
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
|
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
|
||||||
|
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.DebugFast|Win32.Build.0 = DebugFast|Win32
|
||||||
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||||
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Release|Win32.ActiveCfg = Release|Win32
|
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Release|Win32.Build.0 = Release|Win32
|
||||||
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Release|x64.ActiveCfg = Release|x64
|
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Release|x64.ActiveCfg = Release|x64
|
||||||
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Release|x64.Build.0 = Release|x64
|
{8D612734-FAA5-4B8A-804F-4DEA2367D495}.Release|x64.Build.0 = Release|x64
|
||||||
{C6CC7A52-0FDD-433A-B2CF-9C6F187DA807}.Debug|Win32.ActiveCfg = Debug|Win32
|
{C6CC7A52-0FDD-433A-B2CF-9C6F187DA807}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
@ -377,11 +379,9 @@ Global
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Debug|x64.ActiveCfg = Debug|x64
|
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Debug|x64.Build.0 = Debug|x64
|
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Debug|x64.Build.0 = Debug|x64
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.DebugFast|Win32.ActiveCfg = Debug|Win32
|
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.DebugFast|Win32.ActiveCfg = Debug|Win32
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.DebugFast|Win32.Build.0 = Debug|Win32
|
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.DebugFast|x64.ActiveCfg = Debug|x64
|
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.DebugFast|x64.ActiveCfg = Debug|x64
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.DebugFast|x64.Build.0 = Debug|x64
|
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.DebugFast|x64.Build.0 = Debug|x64
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Release|Win32.ActiveCfg = Release|Win32
|
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Release|x64.ActiveCfg = Release|x64
|
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Release|x64.ActiveCfg = Release|x64
|
||||||
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Release|x64.Build.0 = Release|x64
|
{0D14F1E9-490B-4A2D-A4EF-0535E8B3C718}.Release|x64.Build.0 = Release|x64
|
||||||
{DE7C596C-CBC4-4278-8909-146D63990803}.Debug|Win32.ActiveCfg = Debug|Win32
|
{DE7C596C-CBC4-4278-8909-146D63990803}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
//__________________________________________________________________________________________________
|
//__________________________________________________________________________________________________
|
||||||
// Common wiimote plugin spec, unversioned
|
// Common wiimote plugin spec, unversioned
|
||||||
//
|
//
|
||||||
|
@ -8,9 +26,10 @@
|
||||||
#include "PluginSpecs.h"
|
#include "PluginSpecs.h"
|
||||||
#include "ExportProlog.h"
|
#include "ExportProlog.h"
|
||||||
|
|
||||||
|
|
||||||
typedef void (*TLogv)(const char* _pMessage, int _v);
|
typedef void (*TLogv)(const char* _pMessage, int _v);
|
||||||
|
|
||||||
// Called when the Wiimote sends input reports to the Core.
|
// This is called when the Wiimote sends input reports to the Core.
|
||||||
// Payload: an L2CAP packet.
|
// Payload: an L2CAP packet.
|
||||||
typedef void (*TWiimoteInput)(u16 _channelID, const void* _pData, u32 _Size);
|
typedef void (*TWiimoteInput)(u16 _channelID, const void* _pData, u32 _Size);
|
||||||
|
|
||||||
|
@ -22,6 +41,7 @@ typedef struct
|
||||||
TWiimoteInput pWiimoteInput;
|
TWiimoteInput pWiimoteInput;
|
||||||
} SWiimoteInitialize;
|
} SWiimoteInitialize;
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// I N T E R F A C E ////////////////////////////////////////////////////////////////////////////////
|
// I N T E R F A C E ////////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -57,9 +77,9 @@ EXPORT void CALL DllDebugger(HWND _hParent, bool Show);
|
||||||
// Function:
|
// Function:
|
||||||
// Purpose:
|
// Purpose:
|
||||||
// input: WiimoteInitialize
|
// input: WiimoteInitialize
|
||||||
// output: none
|
// output: If at least one real Wiimote was found or not
|
||||||
//
|
//
|
||||||
EXPORT void CALL Wiimote_Initialize(SWiimoteInitialize _WiimoteInitialize);
|
EXPORT bool CALL Wiimote_Initialize(SWiimoteInitialize _WiimoteInitialize);
|
||||||
|
|
||||||
// __________________________________________________________________________________________________
|
// __________________________________________________________________________________________________
|
||||||
// Function: Wiimote_Shutdown
|
// Function: Wiimote_Shutdown
|
||||||
|
|
|
@ -15,12 +15,20 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Include
|
||||||
|
// ------------
|
||||||
//#include "Common.h" // for u16
|
//#include "Common.h" // for u16
|
||||||
#include "ConfigDlg.h"
|
#include "ConfigDlg.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "EmuSubroutines.h" // for WmRequestStatus
|
#include "EmuSubroutines.h" // for WmRequestStatus
|
||||||
|
/////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Event table
|
||||||
|
// ------------
|
||||||
BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
||||||
EVT_CLOSE(ConfigDialog::OnClose)
|
EVT_CLOSE(ConfigDialog::OnClose)
|
||||||
EVT_BUTTON(ID_CLOSE, ConfigDialog::CloseClick)
|
EVT_BUTTON(ID_CLOSE, ConfigDialog::CloseClick)
|
||||||
|
@ -30,6 +38,8 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
||||||
EVT_CHECKBOX(ID_NUNCHUCKCONNECTED, ConfigDialog::GeneralSettingsChanged)
|
EVT_CHECKBOX(ID_NUNCHUCKCONNECTED, ConfigDialog::GeneralSettingsChanged)
|
||||||
EVT_CHECKBOX(ID_CLASSICCONTROLLERCONNECTED, ConfigDialog::GeneralSettingsChanged)
|
EVT_CHECKBOX(ID_CLASSICCONTROLLERCONNECTED, ConfigDialog::GeneralSettingsChanged)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
/////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
|
ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
|
||||||
: wxDialog(parent, id, title, position, size, style)
|
: wxDialog(parent, id, title, position, size, style)
|
||||||
|
@ -42,6 +52,10 @@ ConfigDialog::~ConfigDialog()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Create GUI
|
||||||
|
// ------------
|
||||||
void ConfigDialog::CreateGUIControls()
|
void ConfigDialog::CreateGUIControls()
|
||||||
{
|
{
|
||||||
// Notebook
|
// Notebook
|
||||||
|
@ -120,6 +134,7 @@ void ConfigDialog::AboutClick(wxCommandEvent& WXUNUSED (event))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
|
@ -159,8 +174,12 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
|
||||||
g_Config.bClassicControllerConnected = false;
|
g_Config.bClassicControllerConnected = false;
|
||||||
// Disconnect the extension so that the game recognize the change
|
// Disconnect the extension so that the game recognize the change
|
||||||
DoExtensionConnectedDisconnected();
|
DoExtensionConnectedDisconnected();
|
||||||
|
/* It doesn't seem to be needed but shouldn't it at least take 25 ms to
|
||||||
|
reconnect an extension after we disconnected another? */
|
||||||
|
Sleep(25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update status
|
||||||
g_Config.bNunchuckConnected = m_NunchuckConnected->IsChecked();
|
g_Config.bNunchuckConnected = m_NunchuckConnected->IsChecked();
|
||||||
|
|
||||||
// Generate connect/disconnect status event
|
// Generate connect/disconnect status event
|
||||||
|
|
|
@ -16,37 +16,75 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
// --------------------
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Includes
|
// Includes
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "StringUtil.h"
|
||||||
|
|
||||||
|
#define HAVE_WX 1
|
||||||
|
#if defined(HAVE_WX) && HAVE_WX // wxWidgets
|
||||||
|
#include <wx/datetime.h> // for the timestamps
|
||||||
|
#endif
|
||||||
|
///////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Settings
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
|
|
||||||
// --------------------
|
|
||||||
// On and off
|
// On and off
|
||||||
bool g_consoleEnable = true;
|
bool g_consoleEnable = true;
|
||||||
int gSaveFile = 0;
|
bool gSaveFile = true;
|
||||||
#define DEBUG_WIIMOTE
|
#define DEBUG_WIIMOTE // On or off
|
||||||
|
const int nFiles = 1;
|
||||||
|
|
||||||
|
|
||||||
// --------------------
|
|
||||||
// Settings
|
|
||||||
int nFiles = 1;
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------
|
|
||||||
// Create handles
|
// Create handles
|
||||||
|
|
||||||
#ifdef DEBUG_WIIMOTE
|
#ifdef DEBUG_WIIMOTE
|
||||||
FILE* __fStdOut[1]; // you have to update this manually, we can't place a nFiles in there
|
FILE* __fStdOut[nFiles];
|
||||||
#endif
|
#endif
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HANDLE __hStdOut = NULL;
|
HANDLE __hStdOut = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
// =======================================================================================
|
||||||
|
/* Get Timestamp */
|
||||||
|
// -------------
|
||||||
|
std::string Tm(bool Ms)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_WX) && HAVE_WX
|
||||||
|
std::string Tmp;
|
||||||
|
if(Ms)
|
||||||
|
{
|
||||||
|
wxDateTime datetime = wxDateTime::UNow(); // Get timestamp
|
||||||
|
Tmp = StringFromFormat("%02i:%02i:%03i",
|
||||||
|
datetime.GetMinute(), datetime.GetSecond(), datetime.GetMillisecond());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxDateTime datetime = wxDateTime::Now(); // Get timestamp
|
||||||
|
Tmp = StringFromFormat("%02i:%02i",
|
||||||
|
datetime.GetMinute(), datetime.GetSecond());
|
||||||
|
}
|
||||||
|
return Tmp;
|
||||||
|
#else
|
||||||
|
std::string Tmp = "";
|
||||||
|
return Tmp;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// ===========================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =======================================================================================
|
// =======================================================================================
|
||||||
/* Start console window - width and height is the size of console window, if you specify
|
/* Start console window - width and height is the size of console window, if you specify
|
||||||
|
@ -69,7 +107,7 @@ void startConsoleWin(int width, int height, char* fname)
|
||||||
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
|
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
// Write to a file
|
// Create a file for this
|
||||||
if(fname)
|
if(fname)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < nFiles; i++)
|
for(int i = 0; i < nFiles; i++)
|
||||||
|
@ -107,6 +145,7 @@ int aprintf(int a, char *fmt, ...)
|
||||||
if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL
|
if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL
|
||||||
//to make it work
|
//to make it work
|
||||||
fprintf(__fStdOut[a], s);
|
fprintf(__fStdOut[a], s);
|
||||||
|
fflush(__fStdOut[0]); // Write file now, don't wait
|
||||||
// -------------
|
// -------------
|
||||||
|
|
||||||
return(cnt);
|
return(cnt);
|
||||||
|
@ -135,14 +174,20 @@ int wprintf(const char *fmt, ...)
|
||||||
cnt = vsnprintf(s, 500, fmt, argptr);
|
cnt = vsnprintf(s, 500, fmt, argptr);
|
||||||
va_end(argptr);
|
va_end(argptr);
|
||||||
|
|
||||||
DWORD cCharsWritten;
|
DWORD cCharsWritten; // We will get a value back here
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
// ------------------------------------------
|
||||||
|
// Write to console
|
||||||
|
// ----------------
|
||||||
if(__hStdOut)
|
if(__hStdOut)
|
||||||
{
|
{
|
||||||
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
|
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
|
||||||
}
|
}
|
||||||
// -------------
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Write to file
|
||||||
|
// ----------------
|
||||||
|
aprintf(0, s);
|
||||||
|
|
||||||
return(cnt);
|
return(cnt);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -15,7 +15,19 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#ifndef WIIMOTE_CONSOLE_H
|
||||||
|
#define WIIMOTE_CONSOLE_H
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Includes
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
|
#include <iostream>
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Declarations
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
|
std::string Tm(bool Ms = false);
|
||||||
void startConsoleWin(int width, int height, char* fname);
|
void startConsoleWin(int width, int height, char* fname);
|
||||||
int wprintf(const char *fmt, ...);
|
int wprintf(const char *fmt, ...);
|
||||||
int aprintf(int a, const char *fmt, ...);
|
int aprintf(int a, const char *fmt, ...);
|
||||||
|
@ -24,3 +36,6 @@ void ClearScreen();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HWND GetConsoleHwnd(void);
|
HWND GetConsoleHwnd(void);
|
||||||
#endif
|
#endif
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
#endif // WIIMOTE_CONSOLE_H
|
|
@ -20,14 +20,18 @@
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
/* Data reports guide. The different structures location in the Input reports. The ? in
|
/* Data reports guide. The different structures location in the Input reports. The ? in
|
||||||
the IR coordinates is the High coordinates that are four in one byte. */
|
the IR coordinates is the High coordinates that are four in one byte.
|
||||||
|
|
||||||
|
0x37: For the data reportingmode 0x37 there are five unused IR bytes in the end (represented)
|
||||||
|
by "..." below, it seems like they can be set to either 0xff or 0x00 without affecting the
|
||||||
|
IR emulation. */
|
||||||
// ----------------
|
// ----------------
|
||||||
|
|
||||||
/* 0x33
|
/* 0x33
|
||||||
[c.left etc] [c.a etc] acc.x y z ir0.x y ? ir1.x y ? ir2.x y ? ir3.x y ?
|
[c.left etc] [c.a etc] acc.x y z ir0.x y ? ir1.x y ? ir2.x y ? ir3.x y ?
|
||||||
|
|
||||||
0x37
|
0x37
|
||||||
[c.left etc] [c.a etc] acc.x y z ir0.x1 y1 ? x2 y2 ir1.x1 y1 ? x2 y2 ext.jx jy ax ay az bt
|
[c.left etc] [c.a etc] acc.x y z ir0.x1 y1 ? x2 y2 ir1.x1 y1 ? x2 y2 ... ext.jx jy ax ay az bt
|
||||||
|
|
||||||
|
|
||||||
The Data Report's path from here is
|
The Data Report's path from here is
|
||||||
|
@ -43,23 +47,32 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Includes
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
#include "pluginspecs_wiimote.h"
|
#include "pluginspecs_wiimote.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Common.h"
|
|
||||||
#include "wiimote_hid.h"
|
#include "Common.h" // Common
|
||||||
|
#include "StringUtil.h" // for ArrayToString
|
||||||
|
|
||||||
|
#include "wiimote_hid.h" // Local
|
||||||
#include "EmuMain.h"
|
#include "EmuMain.h"
|
||||||
#include "EmuSubroutines.h"
|
#include "EmuSubroutines.h"
|
||||||
#include "EmuDefinitions.h"
|
#include "EmuDefinitions.h"
|
||||||
#include "Encryption.h" // for extension encryption
|
#include "Encryption.h" // for extension encryption
|
||||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||||
#include "Config.h" // for g_Config
|
#include "Config.h" // for g_Config
|
||||||
|
///////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Declarations and definitions
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||||
//extern void __Log(int log, const char *format, ...);
|
///////////////////////////////
|
||||||
//extern void __Log(int log, int v, const char *format, ...);
|
|
||||||
|
|
||||||
|
|
||||||
namespace WiiMoteEmu
|
namespace WiiMoteEmu
|
||||||
|
@ -78,13 +91,13 @@ void WmDataReporting(u16 _channelID, wm_data_reporting* dr)
|
||||||
LOG(WII_IPC_WIIMOTE, " Continuous: %x", dr->continuous);
|
LOG(WII_IPC_WIIMOTE, " Continuous: %x", dr->continuous);
|
||||||
LOG(WII_IPC_WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time);
|
LOG(WII_IPC_WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time);
|
||||||
LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode);
|
LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode);
|
||||||
wprintf("\nData reporting mode: 0x%02x", dr->mode);
|
//wprintf("Data reporting mode: 0x%02x\n", dr->mode);
|
||||||
wprintf("\nData reporting channel: 0x%04x\n", _channelID);
|
//wprintf("Data reporting channel: 0x%04x\n", _channelID);
|
||||||
|
|
||||||
|
|
||||||
g_ReportingMode = dr->mode;
|
g_ReportingMode = dr->mode;
|
||||||
g_ReportingChannel = _channelID;
|
g_ReportingChannel = _channelID;
|
||||||
switch(dr->mode) { //see Wiimote_Update()
|
switch(dr->mode) // See Wiimote_Update()
|
||||||
|
{
|
||||||
case WM_REPORT_CORE:
|
case WM_REPORT_CORE:
|
||||||
case WM_REPORT_CORE_ACCEL:
|
case WM_REPORT_CORE_ACCEL:
|
||||||
case WM_REPORT_CORE_ACCEL_IR12:
|
case WM_REPORT_CORE_ACCEL_IR12:
|
||||||
|
@ -270,7 +283,7 @@ void SendReportCoreAccelIr10Ext(u16 _channelID)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/*if(GetAsyncKeyState('V'))
|
/*if(GetAsyncKeyState('V'))
|
||||||
{
|
{
|
||||||
std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30);
|
std::string Temp = ArrayToString(DataFrame, Offset, 0, 30);
|
||||||
wprintf("DataFrame: %s\n", Temp.c_str());
|
wprintf("DataFrame: %s\n", Temp.c_str());
|
||||||
}*/
|
}*/
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,8 +15,11 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _EMU_DECLARATIONS_
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#define _EMU_DECLARATIONS_
|
// Includes
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
|
#ifndef _EMU_DEFINITIONS_
|
||||||
|
#define _EMU_DEFINITIONS_
|
||||||
|
|
||||||
#include "pluginspecs_wiimote.h"
|
#include "pluginspecs_wiimote.h"
|
||||||
|
|
||||||
|
@ -27,6 +30,7 @@
|
||||||
#include "EmuDefinitions.h"
|
#include "EmuDefinitions.h"
|
||||||
#include "Encryption.h"
|
#include "Encryption.h"
|
||||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||||
|
|
||||||
|
@ -43,16 +47,18 @@ u8 g_SpeakerVoice = 0x1; // 1 = on
|
||||||
u8 g_IR = 0x1; // 1 = on
|
u8 g_IR = 0x1; // 1 = on
|
||||||
|
|
||||||
u8 g_Eeprom[WIIMOTE_EEPROM_SIZE];
|
u8 g_Eeprom[WIIMOTE_EEPROM_SIZE];
|
||||||
|
|
||||||
u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE];
|
u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE];
|
||||||
u8 g_RegExt[WIIMOTE_REG_EXT_SIZE];
|
u8 g_RegExt[WIIMOTE_REG_EXT_SIZE];
|
||||||
u8 g_RegExtTmp[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_RegIr[WIIMOTE_REG_IR_SIZE];
|
||||||
|
|
||||||
u8 g_ReportingMode; // the reporting mode and channel id
|
u8 g_ReportingMode; // The reporting mode and channel id
|
||||||
u16 g_ReportingChannel;
|
u16 g_ReportingChannel;
|
||||||
|
|
||||||
wiimote_key g_ExtKey; // the extension encryption key
|
std::vector<wm_ackdelay> AckDelay;
|
||||||
|
|
||||||
|
wiimote_key g_ExtKey; // The extension encryption key
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -15,15 +15,18 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _EMU_DEFINITIONS_
|
#ifndef _EMU_DECLARATIONS_
|
||||||
#define _EMU_DEFINITIONS_
|
#define _EMU_DECLARATIONS_
|
||||||
|
|
||||||
#include "pluginspecs_wiimote.h"
|
#include "pluginspecs_wiimote.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
#include "wiimote_hid.h"
|
#include "wiimote_hid.h"
|
||||||
|
#include "Encryption.h"
|
||||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||||
|
|
||||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||||
|
@ -52,12 +55,106 @@ namespace WiiMoteEmu
|
||||||
#define wBOTTOM 625
|
#define wBOTTOM 625
|
||||||
#define wSENSOR_BAR_RADIUS 200
|
#define wSENSOR_BAR_RADIUS 200
|
||||||
|
|
||||||
// vars
|
// Registry sizes
|
||||||
#define WIIMOTE_EEPROM_SIZE (16*1024)
|
#define WIIMOTE_EEPROM_SIZE (16*1024)
|
||||||
#define WIIMOTE_REG_SPEAKER_SIZE 10
|
#define WIIMOTE_REG_SPEAKER_SIZE 10
|
||||||
#define WIIMOTE_REG_EXT_SIZE 0x100
|
#define WIIMOTE_REG_EXT_SIZE 0x100
|
||||||
#define WIIMOTE_REG_IR_SIZE 0x34
|
#define WIIMOTE_REG_IR_SIZE 0x34
|
||||||
|
|
||||||
|
extern u8 g_Leds;
|
||||||
|
extern u8 g_Speaker;
|
||||||
|
extern u8 g_SpeakerVoice;
|
||||||
|
extern u8 g_IR;
|
||||||
|
|
||||||
|
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;
|
||||||
|
extern u16 g_ReportingChannel;
|
||||||
|
|
||||||
|
struct wm_ackdelay // Ack delay
|
||||||
|
{
|
||||||
|
u8 Delay;
|
||||||
|
u8 ReportID;
|
||||||
|
u16 ChannelID;
|
||||||
|
bool Sent;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::vector<wm_ackdelay> AckDelay;
|
||||||
|
|
||||||
|
extern wiimote_key g_ExtKey; // extension encryption key
|
||||||
|
|
||||||
|
static const u8 EepromData_0[] = {
|
||||||
|
0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30,
|
||||||
|
0xA7, 0x74, 0xD3, 0xA1, 0xAA, 0x8B, 0x99, 0xAE,
|
||||||
|
0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3, 0x82, 0x82,
|
||||||
|
0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E,
|
||||||
|
0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38,
|
||||||
|
0x40, 0x3E
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u8 EepromData_16D0[] = {
|
||||||
|
0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00,
|
||||||
|
0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99,
|
||||||
|
0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Default calibration for the nunchuck. It should be written to 0x20 - 0x3f of the
|
||||||
|
extension register. 0x80 is the neutral x and y accelerators and 0xb3 is the
|
||||||
|
neutral z accelerometer that is adjusted for gravity. */
|
||||||
|
static const u8 nunchuck_calibration[] =
|
||||||
|
{
|
||||||
|
0x80,0x80,0x80,0x00, 0xb3,0xb3,0xb3,0x00,
|
||||||
|
0xe0,0x20,0x80,0xe0, 0x20,0x80,0xee,0x43,
|
||||||
|
0x80,0x80,0x80,0x00, 0xb3,0xb3,0xb3,0x00,
|
||||||
|
0xe0,0x20,0x80,0xe0, 0x20,0x80,0xee,0x43
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Classic Controller calibration. 0x80 is the neutral for the analog triggers and
|
||||||
|
sticks. The left analog range is 0x1c - 0xe4 and the right is 0x28 - 0xd8.
|
||||||
|
We use this range because it's closest to the GC controller range. */
|
||||||
|
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,
|
||||||
|
0x80,0xd8,0x28,0x80, 0x20,0x20,0x95,0xea
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* The Nunchuck id. It should be written to the last bytes of the
|
||||||
|
extension register */
|
||||||
|
static const u8 nunchuck_id[] =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0xa4, 0x20, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The Classic Controller id. It should be written to the last bytes of the
|
||||||
|
extension register */
|
||||||
|
static const u8 classic_id[] =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0xa4, 0x20, 0x01, 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The id for nothing inserted */
|
||||||
|
static const u8 nothing_id[] =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x2e, 0x2e
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The id for a partially inserted extension */
|
||||||
|
static const u8 partially_id[] =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Includes
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
#include "pluginspecs_wiimote.h"
|
#include "pluginspecs_wiimote.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -31,492 +34,341 @@
|
||||||
#include "Encryption.h" // for extension encryption
|
#include "Encryption.h" // for extension encryption
|
||||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||||
#include "Config.h" // for g_Config
|
#include "Config.h" // for g_Config
|
||||||
|
////////////////////////////////////
|
||||||
|
|
||||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||||
|
|
||||||
|
|
||||||
namespace WiiMoteEmu
|
namespace WiiMoteEmu
|
||||||
{
|
{
|
||||||
|
|
||||||
//******************************************************************************
|
|
||||||
// Subroutines
|
|
||||||
//******************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
/* Here we process the Output Reports that the Wii sends. Our response will be an Input Report
|
/* Bit shift conversions */
|
||||||
back to the Wii. Input and Output is from the Wii's perspective, Output means data to
|
|
||||||
the Wiimote (from the Wii), Input means data from the Wiimote.
|
|
||||||
|
|
||||||
The call browser:
|
|
||||||
|
|
||||||
1. Wiimote_InterruptChannel > InterruptChannel > HidOutputReport
|
|
||||||
2. Wiimote_ControlChannel > ControlChannel > HidOutputReport */
|
|
||||||
// ----------------
|
|
||||||
void HidOutputReport(u16 _channelID, wm_report* sr) {
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport (0x%02x)", sr->channel);
|
|
||||||
|
|
||||||
switch(sr->channel)
|
|
||||||
{
|
|
||||||
case 0x10:
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport: unknown sr->channel 0x10");
|
|
||||||
break;
|
|
||||||
case WM_LEDS: // 0x11
|
|
||||||
WmLeds(_channelID, (wm_leds*)sr->data);
|
|
||||||
break;
|
|
||||||
case WM_DATA_REPORTING: // 0x12
|
|
||||||
WmDataReporting(_channelID, (wm_data_reporting*)sr->data);
|
|
||||||
break;
|
|
||||||
case WM_REQUEST_STATUS: // 0x15
|
|
||||||
WmRequestStatus(_channelID, (wm_request_status*)sr->data);
|
|
||||||
break;
|
|
||||||
case WM_READ_DATA: // 0x17
|
|
||||||
WmReadData(_channelID, (wm_read_data*)sr->data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* This enables or disables the IR lights, we update the global variable g_IR
|
|
||||||
so that WmRequestStatus() knows about it */
|
|
||||||
case WM_IR_PIXEL_CLOCK: // 0x13
|
|
||||||
case WM_IR_LOGIC: // 0x1a
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " IR Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]);
|
|
||||||
//wprintf("IR Enable/Disable 0x%02x: 0x%02x\n", sr->channel, sr->data[0]);
|
|
||||||
if(sr->data[0] == 0x02) g_IR = 0;
|
|
||||||
else if(sr->data[0] == 0x06) g_IR = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_WRITE_DATA: // 0x16
|
|
||||||
WmWriteData(_channelID, (wm_write_data*)sr->data);
|
|
||||||
break;
|
|
||||||
case WM_SPEAKER_ENABLE: // 0x14
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 1, " WM Speaker Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]);
|
|
||||||
//wprintf("Speaker Enable/Disable 0x%02x: 0x%02x\n", sr->channel, sr->data[0]);
|
|
||||||
if(sr->data[0] == 0x02) g_Speaker = 0;
|
|
||||||
else if(sr->data[0] == 0x06) g_Speaker = 1;
|
|
||||||
break;
|
|
||||||
case WM_SPEAKER_MUTE:
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 1, " WM Mute Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]);
|
|
||||||
//wprintf("Speaker Mute/Unmute 0x%02x: 0x%02x\n", sr->channel, sr->data[0]);
|
|
||||||
if(sr->data[0] == 0x02) g_SpeakerVoice = 0;
|
|
||||||
else if(sr->data[0] == 0x06) g_SpeakerVoice = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->channel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
|
||||||
/* Generate the right address for wm reports. */
|
|
||||||
// ----------------
|
|
||||||
int WriteWmReport(u8* dst, u8 channel) {
|
|
||||||
u32 Offset = 0;
|
|
||||||
hid_packet* pHidHeader = (hid_packet*)(dst + Offset);
|
|
||||||
Offset += sizeof(hid_packet);
|
|
||||||
pHidHeader->type = HID_TYPE_DATA;
|
|
||||||
pHidHeader->param = HID_PARAM_INPUT;
|
|
||||||
|
|
||||||
wm_report* pReport = (wm_report*)(dst + Offset);
|
|
||||||
Offset += sizeof(wm_report);
|
|
||||||
pReport->channel = channel;
|
|
||||||
return Offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
|
||||||
/* LED (blue lights) report. */
|
|
||||||
// ----------------
|
|
||||||
void WmLeds(u16 _channelID, wm_leds* leds) {
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Set LEDs");
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Leds: %x", leds->leds);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Rumble: %x", leds->rumble);
|
|
||||||
|
|
||||||
g_Leds = leds->leds;
|
|
||||||
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
|
||||||
/* This will generate the 0x22 acknowledgment after all Input reports. It will
|
|
||||||
have the form a1 22 00 00 _reportID 00. The first two bytes are unknown but
|
|
||||||
00 00 seems to work fine. */
|
|
||||||
// ----------------
|
|
||||||
void WmSendAck(u16 _channelID, u8 _reportID, u32 address)
|
|
||||||
{
|
|
||||||
u8 DataFrame[1024];
|
|
||||||
u32 Offset = 0;
|
|
||||||
|
|
||||||
// Header
|
|
||||||
hid_packet* pHidHeader = (hid_packet*)(DataFrame + Offset);
|
|
||||||
pHidHeader->type = HID_TYPE_DATA;
|
|
||||||
pHidHeader->param = HID_PARAM_INPUT;
|
|
||||||
Offset += sizeof(hid_packet);
|
|
||||||
|
|
||||||
wm_acknowledge* pData = (wm_acknowledge*)(DataFrame + Offset);
|
|
||||||
pData->Channel = WM_WRITE_DATA_REPLY;
|
|
||||||
pData->unk0 = 0;
|
|
||||||
pData->unk1 = 0;
|
|
||||||
pData->reportID = _reportID;
|
|
||||||
pData->errorID = 0;
|
|
||||||
Offset += sizeof(wm_acknowledge);
|
|
||||||
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 2, " WMSendAck()");
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 2, " Report ID: %02x", _reportID);
|
|
||||||
//std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0);
|
|
||||||
//LOGV(WII_IPC_WIIMOTE, 2, " Data: %s", Temp.c_str());
|
|
||||||
|
|
||||||
/* Debug. Write the report for extension registry writes.
|
|
||||||
if((_reportID == 0x16 || _reportID == 0x17) && ((address >> 16) & 0xfe) == 0xa4)
|
|
||||||
{
|
|
||||||
wprintf("\nWMSendAck Report ID: %02x Encryption: %02x\n", _reportID, g_RegExt[0xf0]);
|
|
||||||
wprintf("Data: %s\n", Temp.c_str());
|
|
||||||
}*/
|
|
||||||
|
|
||||||
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
|
||||||
/* Read data from Wiimote and Extensions registers. */
|
|
||||||
// ----------------
|
|
||||||
void WmReadData(u16 _channelID, wm_read_data* rd)
|
|
||||||
{
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
|
||||||
u32 address = convert24bit(rd->address);
|
|
||||||
u16 size = convert16bit(rd->size);
|
|
||||||
std::string Temp;
|
|
||||||
LOG(WII_IPC_WIIMOTE, "Read data");
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Address space: %x", rd->space);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Address: 0x%06x", address);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Size: 0x%04x", size);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Rumble: %x", rd->rumble);
|
|
||||||
|
|
||||||
//u32 _address = address;
|
|
||||||
|
|
||||||
/* Now we determine what address space we are reading from. Space 0 is Eeprom and
|
|
||||||
space 1 and 2 is the registers. */
|
|
||||||
if(rd->space == 0)
|
|
||||||
{
|
|
||||||
if (address + size > WIIMOTE_EEPROM_SIZE)
|
|
||||||
{
|
|
||||||
PanicAlert("WmReadData: address + size out of bounds!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SendReadDataReply(_channelID, g_Eeprom+address, address, (u8)size);
|
|
||||||
}
|
|
||||||
else if(rd->space == WM_SPACE_REGS1 || rd->space == WM_SPACE_REGS2)
|
|
||||||
{
|
|
||||||
u8* block;
|
|
||||||
u32 blockSize;
|
|
||||||
switch((address >> 16) & 0xFE)
|
|
||||||
{
|
|
||||||
case 0xA2:
|
|
||||||
block = g_RegSpeaker;
|
|
||||||
blockSize = WIIMOTE_REG_SPEAKER_SIZE;
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: g_RegSpeaker");
|
|
||||||
//Temp = WiiMoteEmu::ArrayToString(g_RegSpeaker, size, (address & 0xffff));
|
|
||||||
//LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
|
|
||||||
break;
|
|
||||||
case 0xA4:
|
|
||||||
block = g_RegExt;
|
|
||||||
blockSize = WIIMOTE_REG_EXT_SIZE;
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: Read ExtReg ****************************");
|
|
||||||
//Temp = WiiMoteEmu::ArrayToString(g_RegExt, size, (address & 0xffff));
|
|
||||||
//LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
|
|
||||||
break;
|
|
||||||
case 0xB0:
|
|
||||||
block = g_RegIr;
|
|
||||||
blockSize = WIIMOTE_REG_IR_SIZE;
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Case: 0xb0 g_RegIr");
|
|
||||||
//Temp = WiiMoteEmu::ArrayToString(g_RegIr, size, (address & 0xffff));
|
|
||||||
//LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PanicAlert("WmWriteData: bad register block!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
// Encrypt data that is read from the Wiimote Extension Register
|
|
||||||
// -------------
|
// -------------
|
||||||
if(((address >> 16) & 0xfe) == 0xa4)
|
u32 convert24bit(const u8* src) {
|
||||||
{
|
return (src[0] << 16) | (src[1] << 8) | src[2];
|
||||||
wprintf("\n\nWmReadData Address: %08x Offset: %08x Size: %i byte\n",
|
|
||||||
address, address & 0xffff, (u8)size);
|
|
||||||
|
|
||||||
/* Debugging
|
|
||||||
u32 offset = address & 0xffff;
|
|
||||||
std::string Temp = WiiMoteEmu::ArrayToString(g_RegExt, size, offset);
|
|
||||||
wprintf("Unencrypted data:\n%s\n", Temp.c_str());*/
|
|
||||||
|
|
||||||
// Check if encrypted reads is on
|
|
||||||
if(g_RegExt[0xf0] == 0xaa)
|
|
||||||
{
|
|
||||||
// Copy g_RegExt to g_RegExtTmp
|
|
||||||
memcpy(g_RegExtTmp, g_RegExt, sizeof(g_RegExt));
|
|
||||||
|
|
||||||
// Copy the registry to a temporary space
|
|
||||||
memcpy(g_RegExtTmp, g_RegExt, sizeof(g_RegExt));
|
|
||||||
|
|
||||||
// Encrypt the read
|
|
||||||
wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[address & 0xffff], (address & 0xffff), (u8)size);
|
|
||||||
|
|
||||||
/* Debugging
|
|
||||||
wprintf("\nEncrypted data:\n");
|
|
||||||
for (int i = 0; i < (u8)size; i++)
|
|
||||||
{
|
|
||||||
wprintf("%02x ", g_RegExtTmp[i + offset]);
|
|
||||||
if((i + 1) % 20 == 0) wprintf("\n");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// Update the block that SendReadDataReply will eventually send to the Wii
|
|
||||||
block = g_RegExtTmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//---------
|
|
||||||
|
|
||||||
|
|
||||||
address &= 0xFFFF;
|
|
||||||
if(address + size > blockSize) {
|
|
||||||
PanicAlert("WmReadData: address + size out of bounds!");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let this function process the message and send it to the Wii
|
u16 convert16bit(const u8* src) {
|
||||||
SendReadDataReply(_channelID, block+address, address, (u8)size);
|
return (src[0] << 8) | src[1];
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
// ==============
|
||||||
{
|
|
||||||
PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x!", size, rd->space);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Acknowledge the 0x17 read, we will do this from InterruptChannel()
|
|
||||||
//WmSendAck(_channelID, WM_READ_DATA, _address);
|
|
||||||
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
/* Write data to Wiimote and Extensions registers. */
|
/* Calibrate the mouse position to the emulation window. */
|
||||||
// ----------------
|
// ----------------
|
||||||
void WmWriteData(u16 _channelID, wm_write_data* wd)
|
void GetMousePos(float& x, float& y)
|
||||||
{
|
{
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "========================================================");
|
#ifdef _WIN32
|
||||||
u32 address = convert24bit(wd->address);
|
POINT point;
|
||||||
LOG(WII_IPC_WIIMOTE, "Write data");
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Address space: %x", wd->space);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Address: 0x%06x", address);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Size: 0x%02x", wd->size);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Rumble: %x", wd->rumble);
|
|
||||||
//std::string Temp = ArrayToString(wd->data, wd->size);
|
|
||||||
//LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
|
|
||||||
|
|
||||||
// Write to EEPROM
|
GetCursorPos(&point);
|
||||||
if(wd->size <= 16 && wd->space == WM_SPACE_EEPROM)
|
ScreenToClient(g_WiimoteInitialize.hWnd, &point);
|
||||||
{
|
|
||||||
if(address + wd->size > WIIMOTE_EEPROM_SIZE) {
|
|
||||||
PanicAlert("WmWriteData: address + size out of bounds!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memcpy(g_Eeprom + address, wd->data, wd->size);
|
|
||||||
}
|
|
||||||
// Write to registers
|
|
||||||
else if(wd->size <= 16 && (wd->space == WM_SPACE_REGS1 || wd->space == WM_SPACE_REGS2))
|
|
||||||
{
|
|
||||||
u8* block;
|
|
||||||
u32 blockSize;
|
|
||||||
switch((address >> 16) & 0xFE)
|
|
||||||
{
|
|
||||||
case 0xA2:
|
|
||||||
block = g_RegSpeaker;
|
|
||||||
blockSize = WIIMOTE_REG_SPEAKER_SIZE;
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: RegSpeaker");
|
|
||||||
//wprintf("\n\nWrite to RegSpeaker: Size: %i, Address: %08x, Offset: %08x\n",
|
|
||||||
// wd->size, address, (address & 0xffff));
|
|
||||||
//wprintf("Data: %s\n", Temp.c_str());
|
|
||||||
break;
|
|
||||||
case 0xA4:
|
|
||||||
block = g_RegExt; // Extension Controller register
|
|
||||||
blockSize = WIIMOTE_REG_EXT_SIZE;
|
|
||||||
//LOGV(WII_IPC_WIIMOTE, 0, " *******************************************************");
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: ExtReg");
|
|
||||||
//LOGV(WII_IPC_WIIMOTE, 0, " *******************************************************");
|
|
||||||
//wprintf("\n\nWmWriteData Size: %i Address: %08x Offset: %08x \n",
|
|
||||||
// wd->size, address, (address & 0xffff));
|
|
||||||
break;
|
|
||||||
case 0xB0:
|
|
||||||
block = g_RegIr;
|
|
||||||
blockSize = WIIMOTE_REG_IR_SIZE;
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xb0: RegIr");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PanicAlert("WmWriteData: bad register block!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
RECT Rect;
|
||||||
|
GetClientRect(g_WiimoteInitialize.hWnd, &Rect);
|
||||||
|
|
||||||
// Remove for example 0xa40000 from the address
|
int width = Rect.right - Rect.left;
|
||||||
address &= 0xFFFF;
|
int height = Rect.bottom - Rect.top;
|
||||||
|
|
||||||
// Check if the address is within bounds
|
x = point.x / (float)width;
|
||||||
if(address + wd->size > blockSize) {
|
y = point.y / (float)height;
|
||||||
PanicAlert("WmWriteData: address + size out of bounds!");
|
#else
|
||||||
return;
|
// TODO fix on linux
|
||||||
}
|
x = 0.5f;
|
||||||
|
y = 0.5f;
|
||||||
// Finally write the registers to the right structure
|
#endif
|
||||||
memcpy(block + address, wd->data, wd->size);
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
// Generate key for the Wiimote Extension
|
|
||||||
// -------------
|
|
||||||
if(blockSize == WIIMOTE_REG_EXT_SIZE)
|
|
||||||
{
|
|
||||||
/* Debugging. Write the data.
|
|
||||||
wprintf("Data: %s\n", Temp.c_str());
|
|
||||||
wprintf("Current address: %08x\n", address); */
|
|
||||||
|
|
||||||
/* Run the key generation on all writes in the key area, it doesn't matter
|
|
||||||
that we send it parts of a key, only the last full key will have an
|
|
||||||
effect */
|
|
||||||
if(address >= 0x40 && address <= 0x4c)
|
|
||||||
wiimote_gen_key(&g_ExtKey, &g_RegExt[0x40]);
|
|
||||||
}
|
|
||||||
// -------------
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
PanicAlert("WmWriteData: unimplemented parameters!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Just added for home brew... Isn't it enough that we call this from
|
|
||||||
InterruptChannel()? Or is there a separate route here that don't pass though
|
|
||||||
InterruptChannel()? */
|
|
||||||
//WmSendAck(_channelID, WM_WRITE_DATA, _address);
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "==========================================================");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
/* Here we produce the actual 0x21 Input report that we send to the Wii. The message
|
/* Homebrew encryption for 0x00000000 encryption keys. */
|
||||||
is divided into 16 bytes pieces and sent piece by piece. There will be five formatting
|
|
||||||
bytes at the begging of all reports. A common format is 00 00 f0 00 20, the 00 00
|
|
||||||
means that no buttons are pressed, the f means 16 bytes in the message, the 0
|
|
||||||
means no error, the 00 20 means that the message is at the 00 20 offest in the
|
|
||||||
registry that was read. */
|
|
||||||
// ----------------
|
// ----------------
|
||||||
void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size)
|
void CryptBuffer(u8* _buffer, u8 _size)
|
||||||
{
|
{
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "=========================================");
|
for (int i=0; i<_size; i++)
|
||||||
int dataOffset = 0;
|
|
||||||
while (_Size > 0)
|
|
||||||
{
|
{
|
||||||
u8 DataFrame[1024];
|
_buffer[i] = ((_buffer[i] - 0x17) ^ 0x17) & 0xFF;
|
||||||
u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY);
|
}
|
||||||
|
|
||||||
int copySize = _Size;
|
|
||||||
if (copySize > 16)
|
|
||||||
{
|
|
||||||
copySize = 16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset);
|
void WriteCrypted16(u8* _baseBlock, u16 _address, u16 _value)
|
||||||
Offset += sizeof(wm_read_data_reply);
|
|
||||||
pReply->buttons = 0;
|
|
||||||
pReply->error = 0;
|
|
||||||
pReply->size = (copySize - 1) & 0xF;
|
|
||||||
pReply->address = Common::swap16(_Address + dataOffset);
|
|
||||||
|
|
||||||
|
|
||||||
// Write a pice
|
|
||||||
memcpy(pReply->data + dataOffset, _Base, copySize);
|
|
||||||
|
|
||||||
if(copySize < 16) // check if we have less than 16 bytes left to send
|
|
||||||
{
|
{
|
||||||
memset(pReply->data + copySize, 0, 16 - copySize);
|
u16 cryptedValue = _value;
|
||||||
}
|
CryptBuffer((u8*)&cryptedValue, sizeof(u16));
|
||||||
dataOffset += copySize;
|
|
||||||
|
|
||||||
|
*(u16*)(_baseBlock + _address) = cryptedValue;
|
||||||
LOG(WII_IPC_WIIMOTE, " SendReadDataReply()");
|
//PanicAlert("Converted %04x to %04x", _value, cryptedValue);
|
||||||
LOG(WII_IPC_WIIMOTE, " Buttons: 0x%04x", pReply->buttons);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Error: 0x%x", pReply->error);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Size: 0x%x", pReply->size);
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Address: 0x%04x", pReply->address);
|
|
||||||
|
|
||||||
// Send a piece
|
|
||||||
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
|
|
||||||
|
|
||||||
_Size -= copySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_Size != 0)
|
|
||||||
{
|
|
||||||
PanicAlert("WiiMote-Plugin: SendReadDataReply() failed");
|
|
||||||
}
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "==========================================");
|
|
||||||
}
|
}
|
||||||
// ================
|
// ================
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
/* Here we produce a status report to send to the Wii. We currently ignore the status
|
/* Write initial values to Eeprom and registers. */
|
||||||
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 Initialize()
|
||||||
{
|
{
|
||||||
//PanicAlert("WmRequestStatus");
|
memset(g_Eeprom, 0, WIIMOTE_EEPROM_SIZE);
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "================================================");
|
memcpy(g_Eeprom, EepromData_0, sizeof(EepromData_0));
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Request Status");
|
memcpy(g_Eeprom + 0x16D0, EepromData_16D0, sizeof(EepromData_16D0));
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Rumble: %x", rs->rumble);
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Channel: %04x", _channelID);
|
|
||||||
|
|
||||||
//SendStatusReport();
|
g_ReportingMode = 0;
|
||||||
u8 DataFrame[1024];
|
|
||||||
u32 Offset = WriteWmReport(DataFrame, WM_STATUS_REPORT);
|
|
||||||
|
|
||||||
wm_status_report* pStatus = (wm_status_report*)(DataFrame + Offset);
|
|
||||||
Offset += sizeof(wm_status_report);
|
|
||||||
memset(pStatus, 0, sizeof(wm_status_report)); // fill the status report with zeroes
|
|
||||||
|
|
||||||
// Status values
|
/* Extension data for homebrew applications that use the 0x00000000 key. This
|
||||||
pStatus->battery_low = 0; // battery is okay
|
writes 0x0000 in encrypted form (0xfefe) to 0xfe in the extension register. */
|
||||||
pStatus->leds = g_Leds; // leds are 4 bit
|
//WriteCrypted16(g_RegExt, 0xfe, 0x0000); // Fully inserted Nunchuk
|
||||||
pStatus->ir = g_IR; // 1 bit
|
|
||||||
pStatus->speaker = g_Speaker; // 1 bit
|
|
||||||
/* Battery levels in voltage
|
|
||||||
0x00 - 0x32: level 1
|
|
||||||
0x33 - 0x43: level 2
|
|
||||||
0x33 - 0x54: level 3
|
|
||||||
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;
|
|
||||||
else
|
|
||||||
pStatus->extension = 0;
|
|
||||||
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Extension: %x", pStatus->extension);
|
// Copy extension id and calibration to its register
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " SendStatusReport()");
|
if(g_Config.bNunchuckConnected)
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Flags: 0x%02x", pStatus->padding1[2]);
|
{
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, " Battery: %d", pStatus->battery);
|
memcpy(g_RegExt + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||||
|
memcpy(g_RegExt + 0xfa, nunchuck_id, sizeof(nunchuck_id));
|
||||||
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 0, "=================================================");
|
|
||||||
}
|
}
|
||||||
|
else if(g_Config.bClassicControllerConnected)
|
||||||
|
{
|
||||||
|
memcpy(g_RegExt + 0x20, classic_calibration, sizeof(classic_calibration));
|
||||||
|
memcpy(g_RegExt + 0xfa, classic_id, sizeof(classic_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// g_RegExt[0xfd] = 0x1e;
|
||||||
|
// g_RegExt[0xfc] = 0x9a;
|
||||||
|
}
|
||||||
|
// ================
|
||||||
|
|
||||||
|
|
||||||
|
void DoState(void* ptr, int mode)
|
||||||
|
{
|
||||||
|
//TODO: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We don't need to do anything here. All values will be reset as FreeLibrary() is called
|
||||||
|
when we stop a game */
|
||||||
|
void Shutdown(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* An ack delay of 1 was not small enough, but 2 seemed to work, that was about between 20 ms and
|
||||||
|
100 ms in my case. I'm not sure what it means in frame delays. */
|
||||||
|
// ----------------
|
||||||
|
void CreateAckDelay(u8 _ChannelID, u16 _ReportID)
|
||||||
|
{
|
||||||
|
// Settings
|
||||||
|
int GlobalDelay = 2;
|
||||||
|
|
||||||
|
// Queue an acknowledgment
|
||||||
|
wm_ackdelay Tmp;
|
||||||
|
Tmp.Delay = GlobalDelay;
|
||||||
|
Tmp.ChannelID = _ChannelID;
|
||||||
|
Tmp.ReportID = _ReportID;
|
||||||
|
AckDelay.push_back(Tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CheckAckDelay()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < AckDelay.size(); i++)
|
||||||
|
{
|
||||||
|
// See if there are any acks to send
|
||||||
|
if (AckDelay.at(i).Delay >= 0)
|
||||||
|
{
|
||||||
|
if(AckDelay.at(i).Delay == 0)
|
||||||
|
{
|
||||||
|
WmSendAck(AckDelay.at(i).ChannelID, AckDelay.at(i).ReportID, 0);
|
||||||
|
AckDelay.erase(AckDelay.begin() + i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AckDelay.at(i).Delay--;
|
||||||
|
|
||||||
|
//wprintf("%i 0x%04x 0x%02x", i, AckDelay.at(i).ChannelID, AckDelay.at(i).ReportID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ================
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* This function produce Wiimote Input, i.e. reports from the Wiimote in response
|
||||||
|
to Output from the Wii. */
|
||||||
|
// ----------------
|
||||||
|
void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
|
||||||
|
{
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_Input");
|
||||||
|
const u8* data = (const u8*)_pData;
|
||||||
|
|
||||||
|
// -----------------------------------------------------
|
||||||
|
/* Debugging. We have not yet decided how much of 'data' we will use, it's not determined
|
||||||
|
by sizeof(data). We have to determine it by looking at the data cases. */
|
||||||
|
// -----------------
|
||||||
|
/*int size;
|
||||||
|
switch(data[1])
|
||||||
|
{
|
||||||
|
case 0x10:
|
||||||
|
size = 4; // I don't know the size
|
||||||
|
break;
|
||||||
|
case WM_LEDS: // 0x11
|
||||||
|
size = sizeof(wm_leds);
|
||||||
|
break;
|
||||||
|
case WM_DATA_REPORTING: // 0x12
|
||||||
|
size = sizeof(wm_data_reporting);
|
||||||
|
break;
|
||||||
|
case WM_REQUEST_STATUS: // 0x15
|
||||||
|
size = sizeof(wm_request_status);
|
||||||
|
break;
|
||||||
|
case WM_WRITE_DATA: // 0x16
|
||||||
|
size = sizeof(wm_write_data);
|
||||||
|
break;
|
||||||
|
case WM_READ_DATA: // 0x17
|
||||||
|
size = sizeof(wm_read_data);
|
||||||
|
break;
|
||||||
|
case WM_IR_PIXEL_CLOCK: // 0x13
|
||||||
|
case WM_IR_LOGIC: // 0x1a
|
||||||
|
case WM_SPEAKER_ENABLE: // 0x14
|
||||||
|
case WM_SPEAKER_MUTE:
|
||||||
|
size = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PanicAlert("HidOutputReport: Unknown channel 0x%02x", data[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string Temp = ArrayToString(data, size + 2, 0, 30);
|
||||||
|
//LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str());
|
||||||
|
wprintf("\n%s: InterruptChannel: %s\n", Tm(true).c_str(), Temp.c_str());*/
|
||||||
|
// -----------------------------------
|
||||||
|
|
||||||
|
hid_packet* hidp = (hid_packet*) data;
|
||||||
|
|
||||||
|
switch(hidp->type)
|
||||||
|
{
|
||||||
|
case HID_TYPE_DATA:
|
||||||
|
{
|
||||||
|
switch(hidp->param)
|
||||||
|
{
|
||||||
|
case HID_PARAM_OUTPUT:
|
||||||
|
{
|
||||||
|
wm_report* sr = (wm_report*)hidp->data;
|
||||||
|
HidOutputReport(_channelID, sr);
|
||||||
|
|
||||||
|
/* This is the 0x22 answer to all Inputs. In most games it didn't matter
|
||||||
|
if it was written before or after HidOutputReport(), but Wii Sports
|
||||||
|
and Mario Galaxy would stop working if it was placed before
|
||||||
|
HidOutputReport(). Zelda - TP is even more sensitive and require
|
||||||
|
a delay after the Input for the Nunchuck to work. It seemed to be
|
||||||
|
enough to delay only the Nunchuck registry reads and writes but
|
||||||
|
for now I'm delaying all inputs. Both for status changes and Eeprom
|
||||||
|
and registry reads and writes. */
|
||||||
|
|
||||||
|
// Limit the delay to certain registry reads and writes
|
||||||
|
//if((data[1] == WM_WRITE_DATA || data[1] == WM_READ_DATA)
|
||||||
|
// && data[3] == 0xa4)
|
||||||
|
//{
|
||||||
|
CreateAckDelay(_channelID, sr->channel);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
//wm_write_data *wd = (wm_write_data*)sr->data;
|
||||||
|
//u32 address = convert24bit(wd->address);
|
||||||
|
//WmSendAck(_channelID, sr->channel, address);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
PanicAlert("HidInput: HID_TYPE_DATA - param 0x%02x", hidp->type, hidp->param);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
PanicAlert("HidInput: Unknown type 0x%02x and param 0x%02x", hidp->type, hidp->param);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ControlChannel(u16 _channelID, const void* _pData, u32 _Size)
|
||||||
|
{
|
||||||
|
const u8* data = (const u8*)_pData;
|
||||||
|
// dump raw data
|
||||||
|
{
|
||||||
|
LOG(WII_IPC_WIIMOTE, "Wiimote_ControlChannel");
|
||||||
|
std::string Temp = ArrayToString(data, 0, _Size);
|
||||||
|
wprintf("\n%s: ControlChannel: %s\n", Tm().c_str(), Temp.c_str());
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Data: %s", Temp.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
hid_packet* hidp = (hid_packet*) data;
|
||||||
|
switch(hidp->type)
|
||||||
|
{
|
||||||
|
case HID_TYPE_HANDSHAKE:
|
||||||
|
if (hidp->param == HID_PARAM_INPUT)
|
||||||
|
{
|
||||||
|
PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_INPUT");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_OUTPUT");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HID_TYPE_SET_REPORT:
|
||||||
|
if (hidp->param == HID_PARAM_INPUT)
|
||||||
|
{
|
||||||
|
PanicAlert("HID_TYPE_SET_REPORT input");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HidOutputReport(_channelID, (wm_report*)hidp->data);
|
||||||
|
|
||||||
|
//return handshake
|
||||||
|
u8 handshake = 0;
|
||||||
|
g_WiimoteInitialize.pWiimoteInput(_channelID, &handshake, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HID_TYPE_DATA:
|
||||||
|
PanicAlert("HID_TYPE_DATA %s", hidp->type, hidp->param == HID_PARAM_INPUT ? "input" : "output");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
PanicAlert("HidControlChanel: Unknown type %x and param %x", hidp->type, hidp->param);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* This is called from Wiimote_Update(). See SystemTimers.cpp for a documentation. I'm
|
||||||
|
not sure exactly how often this function is called but I think it's tied to the frame
|
||||||
|
rate of the game rather than a certain amount of times per second. */
|
||||||
|
// ----------------
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
//LOG(WII_IPC_WIIMOTE, "Wiimote_Update");
|
||||||
|
|
||||||
|
switch(g_ReportingMode)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case WM_REPORT_CORE: SendReportCore(g_ReportingChannel); break;
|
||||||
|
case WM_REPORT_CORE_ACCEL: SendReportCoreAccel(g_ReportingChannel); break;
|
||||||
|
case WM_REPORT_CORE_ACCEL_IR12: SendReportCoreAccelIr12(g_ReportingChannel);break;
|
||||||
|
case WM_REPORT_CORE_ACCEL_EXT16: SendReportCoreAccelExt16(g_ReportingChannel);break;
|
||||||
|
case WM_REPORT_CORE_ACCEL_IR10_EXT6: SendReportCoreAccelIr10Ext(g_ReportingChannel);break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Potentially send a delayed acknowledgement to an InterruptChannel() Output
|
||||||
|
CheckAckDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
namespace WiiMoteEmu
|
namespace WiiMoteEmu
|
||||||
{
|
{
|
||||||
|
|
||||||
|
u32 convert24bit(const u8* src);
|
||||||
|
u16 convert16bit(const u8* src);
|
||||||
|
void GetMousePos(float& x, float& y);
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
void DoState(void* ptr, int mode);
|
void DoState(void* ptr, int mode);
|
||||||
void Shutdown(void);
|
void Shutdown(void);
|
||||||
|
|
|
@ -36,7 +36,9 @@
|
||||||
// ================
|
// ================
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Includes
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
#include "pluginspecs_wiimote.h"
|
#include "pluginspecs_wiimote.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -51,243 +53,504 @@
|
||||||
#include "EmuDefinitions.h"
|
#include "EmuDefinitions.h"
|
||||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||||
#include "Config.h" // for g_Config
|
#include "Config.h" // for g_Config
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||||
|
|
||||||
namespace WiiMoteEmu
|
namespace WiiMoteEmu
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
// Subroutine declarations
|
// Subroutines
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
|
|
||||||
u32 convert24bit(const u8* src) {
|
|
||||||
return (src[0] << 16) | (src[1] << 8) | src[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 convert16bit(const u8* src) {
|
|
||||||
return (src[0] << 8) | src[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
/* Calibrate the mouse position to the emulation window. */
|
/* Here we process the Output Reports that the Wii sends. Our response will be an Input Report
|
||||||
|
back to the Wii. Input and Output is from the Wii's perspective, Output means data to
|
||||||
|
the Wiimote (from the Wii), Input means data from the Wiimote.
|
||||||
|
|
||||||
|
The call browser:
|
||||||
|
|
||||||
|
1. Wiimote_InterruptChannel > InterruptChannel > HidOutputReport
|
||||||
|
2. Wiimote_ControlChannel > ControlChannel > HidOutputReport
|
||||||
|
|
||||||
|
The IR lights and speaker enable/disable and mute/unmute values are
|
||||||
|
0x2 = Disable
|
||||||
|
0x6 = Enable */
|
||||||
// ----------------
|
// ----------------
|
||||||
void GetMousePos(float& x, float& y)
|
void HidOutputReport(u16 _channelID, wm_report* sr) {
|
||||||
{
|
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
||||||
#ifdef _WIN32
|
LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport (0x%02x)", sr->channel);
|
||||||
POINT point;
|
|
||||||
|
|
||||||
GetCursorPos(&point);
|
|
||||||
ScreenToClient(g_WiimoteInitialize.hWnd, &point);
|
|
||||||
|
|
||||||
RECT Rect;
|
|
||||||
GetClientRect(g_WiimoteInitialize.hWnd, &Rect);
|
|
||||||
|
|
||||||
int width = Rect.right - Rect.left;
|
|
||||||
int height = Rect.bottom - Rect.top;
|
|
||||||
|
|
||||||
x = point.x / (float)width;
|
|
||||||
y = point.y / (float)height;
|
|
||||||
#else
|
|
||||||
// TODO fix on linux
|
|
||||||
x = 0.5f;
|
|
||||||
y = 0.5f;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
|
||||||
/* Homebrew encryption for 0x00000000 encryption keys. */
|
|
||||||
// ----------------
|
|
||||||
void CryptBuffer(u8* _buffer, u8 _size)
|
|
||||||
{
|
|
||||||
for (int i=0; i<_size; i++)
|
|
||||||
{
|
|
||||||
_buffer[i] = ((_buffer[i] - 0x17) ^ 0x17) & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteCrypted16(u8* _baseBlock, u16 _address, u16 _value)
|
|
||||||
{
|
|
||||||
u16 cryptedValue = _value;
|
|
||||||
CryptBuffer((u8*)&cryptedValue, sizeof(u16));
|
|
||||||
|
|
||||||
*(u16*)(_baseBlock + _address) = cryptedValue;
|
|
||||||
//PanicAlert("Converted %04x to %04x", _value, cryptedValue);
|
|
||||||
}
|
|
||||||
// ================
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
|
||||||
/* Write initial values to Eeprom and registers. */
|
|
||||||
// ----------------
|
|
||||||
void Initialize()
|
|
||||||
{
|
|
||||||
memset(g_Eeprom, 0, WIIMOTE_EEPROM_SIZE);
|
|
||||||
memcpy(g_Eeprom, EepromData_0, sizeof(EepromData_0));
|
|
||||||
memcpy(g_Eeprom + 0x16D0, EepromData_16D0, sizeof(EepromData_16D0));
|
|
||||||
|
|
||||||
g_ReportingMode = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* Extension data for homebrew applications that use the 0x00000000 key. This
|
|
||||||
writes 0x0000 in encrypted form (0xfefe) to 0xfe in the extension register. */
|
|
||||||
//WriteCrypted16(g_RegExt, 0xfe, 0x0000); // Fully inserted Nunchuk
|
|
||||||
|
|
||||||
|
|
||||||
// Copy extension id and calibration to its register
|
|
||||||
if(g_Config.bNunchuckConnected)
|
|
||||||
{
|
|
||||||
memcpy(g_RegExt + 0x20, 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 + 0xfa, classic_id, sizeof(classic_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// g_RegExt[0xfd] = 0x1e;
|
|
||||||
// g_RegExt[0xfc] = 0x9a;
|
|
||||||
}
|
|
||||||
// ================
|
|
||||||
|
|
||||||
|
|
||||||
void DoState(void* ptr, int mode)
|
|
||||||
{
|
|
||||||
//TODO: implement
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shutdown(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
|
||||||
/* This function produce Wiimote Input, i.e. reports from the Wiimote in response
|
|
||||||
to Output from the Wii. */
|
|
||||||
// ----------------
|
|
||||||
void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
|
|
||||||
{
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
|
|
||||||
const u8* data = (const u8*)_pData;
|
|
||||||
|
|
||||||
// Debugging. Dump raw data.
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_Input");
|
|
||||||
//std::string Temp = ArrayToString(data, sizeof(data), 0, 30);
|
|
||||||
//LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str());
|
|
||||||
|
|
||||||
hid_packet* hidp = (hid_packet*) data;
|
|
||||||
|
|
||||||
switch(hidp->type)
|
|
||||||
{
|
|
||||||
case HID_TYPE_DATA:
|
|
||||||
{
|
|
||||||
switch(hidp->param)
|
|
||||||
{
|
|
||||||
case HID_PARAM_OUTPUT:
|
|
||||||
{
|
|
||||||
wm_report* sr = (wm_report*)hidp->data;
|
|
||||||
HidOutputReport(_channelID, sr);
|
|
||||||
|
|
||||||
/* This is the 0x22 answer to all Inputs. In most games it didn't matter
|
|
||||||
if it was written before or after HidOutputReport(), but Wii Sports
|
|
||||||
and Mario Galaxy would stop working if it was placed before
|
|
||||||
HidOutputReport(). */
|
|
||||||
wm_write_data *wd = (wm_write_data*)sr->data;
|
|
||||||
u32 address = convert24bit(wd->address);
|
|
||||||
WmSendAck(_channelID, sr->channel, address);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
PanicAlert("HidInput: HID_TYPE_DATA - param 0x%02x", hidp->type, hidp->param);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
PanicAlert("HidInput: Unknown type 0x%02x and param 0x%02x", hidp->type, hidp->param);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ControlChannel(u16 _channelID, const void* _pData, u32 _Size)
|
|
||||||
{
|
|
||||||
const u8* data = (const u8*)_pData;
|
|
||||||
// dump raw data
|
|
||||||
{
|
|
||||||
LOG(WII_IPC_WIIMOTE, "Wiimote_ControlChannel");
|
|
||||||
std::string Temp;
|
std::string Temp;
|
||||||
for (u32 j=0; j<_Size; j++)
|
|
||||||
{
|
|
||||||
char Buffer[128];
|
|
||||||
sprintf(Buffer, "%02x ", data[j]);
|
|
||||||
Temp.append(Buffer);
|
|
||||||
}
|
|
||||||
LOG(WII_IPC_WIIMOTE, " Data: %s", Temp.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
hid_packet* hidp = (hid_packet*) data;
|
switch(sr->channel)
|
||||||
switch(hidp->type)
|
|
||||||
{
|
{
|
||||||
case HID_TYPE_HANDSHAKE:
|
case 0x10:
|
||||||
if (hidp->param == HID_PARAM_INPUT)
|
LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport: unknown sr->channel 0x10");
|
||||||
{
|
break;
|
||||||
PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_INPUT");
|
case WM_LEDS: // 0x11
|
||||||
}
|
WmLeds(_channelID, (wm_leds*)sr->data);
|
||||||
else
|
break;
|
||||||
{
|
case WM_DATA_REPORTING: // 0x12
|
||||||
PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_OUTPUT");
|
WmDataReporting(_channelID, (wm_data_reporting*)sr->data);
|
||||||
}
|
break;
|
||||||
|
case WM_REQUEST_STATUS: // 0x15
|
||||||
|
WmRequestStatus(_channelID, (wm_request_status*)sr->data);
|
||||||
|
//Temp = ArrayToString(sr->data, sizeof(wm_request_status), 0);
|
||||||
|
//wprintf("\n%s: InterruptChannel: %s\n", Tm().c_str(), Temp.c_str());
|
||||||
|
break;
|
||||||
|
case WM_READ_DATA: // 0x17
|
||||||
|
WmReadData(_channelID, (wm_read_data*)sr->data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HID_TYPE_SET_REPORT:
|
/* This enables or disables the IR lights, we update the global variable g_IR
|
||||||
if (hidp->param == HID_PARAM_INPUT)
|
so that WmRequestStatus() knows about it */
|
||||||
{
|
case WM_IR_PIXEL_CLOCK: // 0x13
|
||||||
PanicAlert("HID_TYPE_SET_REPORT input");
|
case WM_IR_LOGIC: // 0x1a
|
||||||
}
|
LOGV(WII_IPC_WIIMOTE, 0, " IR Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]);
|
||||||
else
|
wprintf("IR Enable/Disable 0x%02x: 0x%02x\n", sr->channel, sr->data[0]);
|
||||||
{
|
if(sr->data[0] == 0x02) g_IR = 0;
|
||||||
HidOutputReport(_channelID, (wm_report*)hidp->data);
|
else if(sr->data[0] == 0x06) g_IR = 1;
|
||||||
|
|
||||||
//return handshake
|
|
||||||
u8 handshake = 0;
|
|
||||||
g_WiimoteInitialize.pWiimoteInput(_channelID, &handshake, 1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HID_TYPE_DATA:
|
case WM_WRITE_DATA: // 0x16
|
||||||
PanicAlert("HID_TYPE_DATA %s", hidp->type, hidp->param == HID_PARAM_INPUT ? "input" : "output");
|
WmWriteData(_channelID, (wm_write_data*)sr->data);
|
||||||
|
break;
|
||||||
|
case WM_SPEAKER_ENABLE: // 0x14
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 1, " WM Speaker Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]);
|
||||||
|
wprintf("Speaker Enable/Disable 0x%02x: 0x%02x\n", sr->channel, sr->data[0]);
|
||||||
|
if(sr->data[0] == 0x02) g_Speaker = 0;
|
||||||
|
else if(sr->data[0] == 0x06) g_Speaker = 1;
|
||||||
|
break;
|
||||||
|
case WM_SPEAKER_MUTE:
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 1, " WM Mute Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]);
|
||||||
|
wprintf("Speaker Mute/Unmute 0x%02x: 0x%02x\n", sr->channel, sr->data[0]);
|
||||||
|
if(sr->data[0] == 0x02) g_SpeakerVoice = 0; // g_SpeakerVoice
|
||||||
|
else if(sr->data[0] == 0x06) g_SpeakerVoice = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PanicAlert("HidControlChanel: Unknown type %x and param %x", hidp->type, hidp->param);
|
PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->channel);
|
||||||
break;
|
return;
|
||||||
|
}
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* Generate the right address for wm reports. */
|
||||||
|
// ----------------
|
||||||
|
int WriteWmReport(u8* dst, u8 channel) {
|
||||||
|
u32 Offset = 0;
|
||||||
|
hid_packet* pHidHeader = (hid_packet*)(dst + Offset);
|
||||||
|
Offset += sizeof(hid_packet);
|
||||||
|
pHidHeader->type = HID_TYPE_DATA;
|
||||||
|
pHidHeader->param = HID_PARAM_INPUT;
|
||||||
|
|
||||||
|
wm_report* pReport = (wm_report*)(dst + Offset);
|
||||||
|
Offset += sizeof(wm_report);
|
||||||
|
pReport->channel = channel;
|
||||||
|
return Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
|
||||||
|
// ===================================================
|
||||||
|
/* LED (blue lights) report. */
|
||||||
|
// ----------------
|
||||||
|
void WmLeds(u16 _channelID, wm_leds* leds) {
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Set LEDs");
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Leds: %x", leds->leds);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Rumble: %x", leds->rumble);
|
||||||
|
|
||||||
|
g_Leds = leds->leds;
|
||||||
|
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* This will generate the 0x22 acknowledgment after all Input reports. It will
|
||||||
|
have the form a1 22 00 00 _reportID 00. The first two bytes are the core buttons data,
|
||||||
|
they are 00 00 when nothing is pressed. The last byte is the success code 00. */
|
||||||
|
// ----------------
|
||||||
|
void WmSendAck(u16 _channelID, u8 _reportID, u32 address)
|
||||||
{
|
{
|
||||||
//LOG(WII_IPC_WIIMOTE, "Wiimote_Update");
|
u8 DataFrame[1024];
|
||||||
|
u32 Offset = 0;
|
||||||
|
|
||||||
switch(g_ReportingMode) {
|
// Header
|
||||||
case 0:
|
hid_packet* pHidHeader = (hid_packet*)(DataFrame + Offset);
|
||||||
|
pHidHeader->type = HID_TYPE_DATA;
|
||||||
|
pHidHeader->param = HID_PARAM_INPUT;
|
||||||
|
Offset += sizeof(hid_packet);
|
||||||
|
|
||||||
|
wm_acknowledge* pData = (wm_acknowledge*)(DataFrame + Offset);
|
||||||
|
pData->Channel = WM_WRITE_DATA_REPLY;
|
||||||
|
pData->unk0 = 0;
|
||||||
|
pData->unk1 = 0;
|
||||||
|
pData->reportID = _reportID;
|
||||||
|
pData->errorID = 0;
|
||||||
|
Offset += sizeof(wm_acknowledge);
|
||||||
|
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 2, " WMSendAck()");
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 2, " Report ID: %02x", _reportID);
|
||||||
|
//std::string Temp = ArrayToString(DataFrame, Offset, 0);
|
||||||
|
//LOGV(WII_IPC_WIIMOTE, 2, " Data: %s", Temp.c_str());
|
||||||
|
//wprintf("%s: WMSendAck: %s\n", Tm(true).c_str(), Temp.c_str());
|
||||||
|
|
||||||
|
/* Debug. Write the report for extension registry writes.
|
||||||
|
if((_reportID == 0x16 || _reportID == 0x17) && ((address >> 16) & 0xfe) == 0xa4)
|
||||||
|
{
|
||||||
|
wprintf("\nWMSendAck Report ID: %02x Encryption: %02x\n", _reportID, g_RegExt[0xf0]);
|
||||||
|
wprintf("Data: %s\n", Temp.c_str());
|
||||||
|
}*/
|
||||||
|
|
||||||
|
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* Read data from Wiimote and Extensions registers. */
|
||||||
|
// ----------------
|
||||||
|
void WmReadData(u16 _channelID, wm_read_data* rd)
|
||||||
|
{
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
||||||
|
u32 address = convert24bit(rd->address);
|
||||||
|
u16 size = convert16bit(rd->size);
|
||||||
|
std::string Temp;
|
||||||
|
LOG(WII_IPC_WIIMOTE, "Read data");
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Address space: %x", rd->space);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Address: 0x%06x", address);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Size: 0x%04x", size);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Rumble: %x", rd->rumble);
|
||||||
|
|
||||||
|
//u32 _address = address;
|
||||||
|
std::string Tmp; // Debugging
|
||||||
|
|
||||||
|
/* Now we determine what address space we are reading from. Space 0 is Eeprom and
|
||||||
|
space 1 and 2 is the registers. */
|
||||||
|
if(rd->space == 0)
|
||||||
|
{
|
||||||
|
if (address + size > WIIMOTE_EEPROM_SIZE)
|
||||||
|
{
|
||||||
|
PanicAlert("WmReadData: address + size out of bounds!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SendReadDataReply(_channelID, g_Eeprom+address, address, (u8)size);
|
||||||
|
}
|
||||||
|
else if(rd->space == WM_SPACE_REGS1 || rd->space == WM_SPACE_REGS2)
|
||||||
|
{
|
||||||
|
u8* block;
|
||||||
|
u32 blockSize;
|
||||||
|
switch((address >> 16) & 0xFE)
|
||||||
|
{
|
||||||
|
case 0xA2:
|
||||||
|
block = g_RegSpeaker;
|
||||||
|
blockSize = WIIMOTE_REG_SPEAKER_SIZE;
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: g_RegSpeaker");
|
||||||
|
//Tmp = ArrayToString(g_RegSpeaker, size, (address & 0xffff));
|
||||||
|
//LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
|
||||||
|
//wprintf("Read RegSpkr: Size %i Address %08x Offset %08x\nData %s\n",
|
||||||
|
// size, address, (address & 0xffff), Tmp.c_str());
|
||||||
break;
|
break;
|
||||||
case WM_REPORT_CORE: SendReportCore(g_ReportingChannel); break;
|
case 0xA4:
|
||||||
case WM_REPORT_CORE_ACCEL: SendReportCoreAccel(g_ReportingChannel); break;
|
block = g_RegExt;
|
||||||
case WM_REPORT_CORE_ACCEL_IR12: SendReportCoreAccelIr12(g_ReportingChannel);break;
|
blockSize = WIIMOTE_REG_EXT_SIZE;
|
||||||
case WM_REPORT_CORE_ACCEL_EXT16: SendReportCoreAccelExt16(g_ReportingChannel);break;
|
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: Read ExtReg ****************************");
|
||||||
case WM_REPORT_CORE_ACCEL_IR10_EXT6: SendReportCoreAccelIr10Ext(g_ReportingChannel);break;
|
//Tmp = ArrayToString(g_RegExt, size, (address & 0xffff));
|
||||||
}
|
//LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
|
||||||
// g_ReportingMode = 0;
|
//wprintf("Read RegExt: Size %i Address %08x Offset %08x\nData %s\n",
|
||||||
|
// size, address, (address & 0xffff), Tmp.c_str());
|
||||||
|
break;
|
||||||
|
case 0xB0:
|
||||||
|
block = g_RegIr;
|
||||||
|
blockSize = WIIMOTE_REG_IR_SIZE;
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Case: 0xb0 g_RegIr");
|
||||||
|
//Tmp = ArrayToString(g_RegIr, size, (address & 0xffff));
|
||||||
|
//LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
|
||||||
|
//wprintf("Read RegIR: Size %i Address %08x Offset %08x\nData %s\n",
|
||||||
|
// size, address, (address & 0xffff), Tmp.c_str());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PanicAlert("WmWriteData: bad register block!");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
// Encrypt data that is read from the Wiimote Extension Register
|
||||||
|
// -------------
|
||||||
|
if(((address >> 16) & 0xfe) == 0xa4)
|
||||||
|
{
|
||||||
|
/* Debugging
|
||||||
|
wprintf("\n\nWmReadData Address: %08x Offset: %08x Size: %i byte\n",
|
||||||
|
address, address & 0xffff, (u8)size);
|
||||||
|
// Debugging
|
||||||
|
u32 offset = address & 0xffff;
|
||||||
|
std::string Temp = ArrayToString(g_RegExt, size, offset);
|
||||||
|
wprintf("Unencrypted data:\n%s\n", Temp.c_str());*/
|
||||||
|
|
||||||
|
// Check if encrypted reads is on
|
||||||
|
if(g_RegExt[0xf0] == 0xaa)
|
||||||
|
{
|
||||||
|
/* Copy the registry to a temporary space. We don't want to change the unencrypted
|
||||||
|
data in the registry */
|
||||||
|
memcpy(g_RegExtTmp, g_RegExt, sizeof(g_RegExt));
|
||||||
|
|
||||||
|
// Encrypt g_RegExtTmp at that location
|
||||||
|
wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[address & 0xffff], (address & 0xffff), (u8)size);
|
||||||
|
|
||||||
|
/* Debugging: Show the encrypted data
|
||||||
|
std::string Temp = ArrayToString(g_RegExtTmp, size, offset);
|
||||||
|
wprintf("Encrypted data:\n%s\n", Temp.c_str());*/
|
||||||
|
|
||||||
|
// Update the block that SendReadDataReply will eventually send to the Wii
|
||||||
|
block = g_RegExtTmp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//---------
|
||||||
|
|
||||||
|
|
||||||
|
address &= 0xFFFF;
|
||||||
|
if(address + size > blockSize) {
|
||||||
|
PanicAlert("WmReadData: address + size out of bounds!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let this function process the message and send it to the Wii
|
||||||
|
SendReadDataReply(_channelID, block+address, address, (u8)size);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x!", size, rd->space);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acknowledge the 0x17 read, we will do this from InterruptChannel()
|
||||||
|
//WmSendAck(_channelID, WM_READ_DATA, _address);
|
||||||
|
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* Write data to Wiimote and Extensions registers. */
|
||||||
|
// ----------------
|
||||||
|
void WmWriteData(u16 _channelID, wm_write_data* wd)
|
||||||
|
{
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "========================================================");
|
||||||
|
u32 address = convert24bit(wd->address);
|
||||||
|
LOG(WII_IPC_WIIMOTE, "Write data");
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Address space: %x", wd->space);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Address: 0x%06x", address);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Size: 0x%02x", wd->size);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Rumble: %x", wd->rumble);
|
||||||
|
//std::string Temp = ArrayToString(wd->data, wd->size);
|
||||||
|
//LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
|
||||||
|
|
||||||
|
// Write to EEPROM
|
||||||
|
if(wd->size <= 16 && wd->space == WM_SPACE_EEPROM)
|
||||||
|
{
|
||||||
|
if(address + wd->size > WIIMOTE_EEPROM_SIZE) {
|
||||||
|
PanicAlert("WmWriteData: address + size out of bounds!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(g_Eeprom + address, wd->data, wd->size);
|
||||||
|
}
|
||||||
|
// Write to registers
|
||||||
|
else if(wd->size <= 16 && (wd->space == WM_SPACE_REGS1 || wd->space == WM_SPACE_REGS2))
|
||||||
|
{
|
||||||
|
u8* block;
|
||||||
|
u32 blockSize;
|
||||||
|
switch((address >> 16) & 0xFE)
|
||||||
|
{
|
||||||
|
case 0xA2:
|
||||||
|
block = g_RegSpeaker;
|
||||||
|
blockSize = WIIMOTE_REG_SPEAKER_SIZE;
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: RegSpeaker");
|
||||||
|
//wprintf("Write RegSpeaker: Size: %i, Address: %08x, Offset: %08x\n",
|
||||||
|
// wd->size, address, (address & 0xffff));
|
||||||
|
//wprintf("Data: %s\n", Temp.c_str());
|
||||||
|
break;
|
||||||
|
case 0xA4:
|
||||||
|
block = g_RegExt; // Extension Controller register
|
||||||
|
blockSize = WIIMOTE_REG_EXT_SIZE;
|
||||||
|
//LOGV(WII_IPC_WIIMOTE, 0, " *******************************************************");
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: ExtReg");
|
||||||
|
//LOGV(WII_IPC_WIIMOTE, 0, " *******************************************************");
|
||||||
|
/*wprintf("Write RegExt Size: %i Address: %08x Offset: %08x \n",
|
||||||
|
wd->size, address, (address & 0xffff));
|
||||||
|
wprintf("Data: %s\n", Temp.c_str());*/
|
||||||
|
break;
|
||||||
|
case 0xB0:
|
||||||
|
block = g_RegIr;
|
||||||
|
blockSize = WIIMOTE_REG_IR_SIZE;
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xb0: RegIr");
|
||||||
|
/*wprintf("Write RegIR Size: %i Address: %08x Offset: %08x \n",
|
||||||
|
wd->size, address, (address & 0xffff));
|
||||||
|
wprintf("Data: %s\n", Temp.c_str());*/
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PanicAlert("WmWriteData: bad register block!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Remove for example 0xa40000 from the address
|
||||||
|
address &= 0xFFFF;
|
||||||
|
|
||||||
|
// Check if the address is within bounds
|
||||||
|
if(address + wd->size > blockSize) {
|
||||||
|
PanicAlert("WmWriteData: address + size out of bounds!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally write the registers to the right structure
|
||||||
|
memcpy(block + address, wd->data, wd->size);
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
// Generate key for the Wiimote Extension
|
||||||
|
// -------------
|
||||||
|
if(blockSize == WIIMOTE_REG_EXT_SIZE)
|
||||||
|
{
|
||||||
|
/* Debugging. Write the data.
|
||||||
|
wprintf("Data: %s\n", Temp.c_str());
|
||||||
|
wprintf("Current address: %08x\n", address); */
|
||||||
|
|
||||||
|
/* Run the key generation on all writes in the key area, it doesn't matter
|
||||||
|
that we send it parts of a key, only the last full key will have an
|
||||||
|
effect */
|
||||||
|
if(address >= 0x40 && address <= 0x4c)
|
||||||
|
wiimote_gen_key(&g_ExtKey, &g_RegExt[0x40]);
|
||||||
|
}
|
||||||
|
// -------------
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
PanicAlert("WmWriteData: unimplemented parameters!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just added for home brew... Isn't it enough that we call this from
|
||||||
|
InterruptChannel()? Or is there a separate route here that don't pass though
|
||||||
|
InterruptChannel()? */
|
||||||
|
//WmSendAck(_channelID, WM_WRITE_DATA, _address);
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "==========================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* Here we produce the actual 0x21 Input report that we send to the Wii. The message
|
||||||
|
is divided into 16 bytes pieces and sent piece by piece. There will be five formatting
|
||||||
|
bytes at the begging of all reports. A common format is 00 00 f0 00 20, the 00 00
|
||||||
|
means that no buttons are pressed, the f means 16 bytes in the message, the 0
|
||||||
|
means no error, the 00 20 means that the message is at the 00 20 offest in the
|
||||||
|
registry that was read. */
|
||||||
|
// ----------------
|
||||||
|
void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size)
|
||||||
|
{
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "=========================================");
|
||||||
|
int dataOffset = 0;
|
||||||
|
while (_Size > 0)
|
||||||
|
{
|
||||||
|
u8 DataFrame[1024];
|
||||||
|
u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY);
|
||||||
|
|
||||||
|
int copySize = _Size;
|
||||||
|
if (copySize > 16)
|
||||||
|
{
|
||||||
|
copySize = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset);
|
||||||
|
Offset += sizeof(wm_read_data_reply);
|
||||||
|
pReply->buttons = 0;
|
||||||
|
pReply->error = 0;
|
||||||
|
pReply->size = (copySize - 1) & 0xF;
|
||||||
|
pReply->address = Common::swap16(_Address + dataOffset);
|
||||||
|
|
||||||
|
|
||||||
|
// Write a pice
|
||||||
|
memcpy(pReply->data + dataOffset, _Base, copySize);
|
||||||
|
|
||||||
|
if(copySize < 16) // check if we have less than 16 bytes left to send
|
||||||
|
{
|
||||||
|
memset(pReply->data + copySize, 0, 16 - copySize);
|
||||||
|
}
|
||||||
|
dataOffset += copySize;
|
||||||
|
|
||||||
|
|
||||||
|
LOG(WII_IPC_WIIMOTE, " SendReadDataReply()");
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Buttons: 0x%04x", pReply->buttons);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Error: 0x%x", pReply->error);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Size: 0x%x", pReply->size);
|
||||||
|
LOG(WII_IPC_WIIMOTE, " Address: 0x%04x", pReply->address);
|
||||||
|
|
||||||
|
// Send a piece
|
||||||
|
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
|
||||||
|
|
||||||
|
_Size -= copySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_Size != 0)
|
||||||
|
{
|
||||||
|
PanicAlert("WiiMote-Plugin: SendReadDataReply() failed");
|
||||||
|
}
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "==========================================");
|
||||||
|
}
|
||||||
|
// ================
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* Here we produce a status report to send to the Wii. We currently ignore the status
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
//PanicAlert("WmRequestStatus");
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "================================================");
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Request Status");
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Rumble: %x", rs->rumble);
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Channel: %04x", _channelID);
|
||||||
|
|
||||||
|
//SendStatusReport();
|
||||||
|
u8 DataFrame[1024];
|
||||||
|
u32 Offset = WriteWmReport(DataFrame, WM_STATUS_REPORT);
|
||||||
|
|
||||||
|
wm_status_report* pStatus = (wm_status_report*)(DataFrame + Offset);
|
||||||
|
Offset += sizeof(wm_status_report);
|
||||||
|
memset(pStatus, 0, sizeof(wm_status_report)); // fill the status report with zeroes
|
||||||
|
|
||||||
|
// Status values
|
||||||
|
pStatus->battery_low = 0; // battery is okay
|
||||||
|
pStatus->leds = g_Leds; // leds are 4 bit
|
||||||
|
pStatus->ir = g_IR; // 1 bit
|
||||||
|
pStatus->speaker = g_Speaker; // 1 bit
|
||||||
|
/* Battery levels in voltage
|
||||||
|
0x00 - 0x32: level 1
|
||||||
|
0x33 - 0x43: level 2
|
||||||
|
0x33 - 0x54: level 3
|
||||||
|
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;
|
||||||
|
else
|
||||||
|
pStatus->extension = 0;
|
||||||
|
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Extension: %x", pStatus->extension);
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " SendStatusReport()");
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Flags: 0x%02x", pStatus->padding1[2]);
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, " Battery: %d", pStatus->battery);
|
||||||
|
|
||||||
|
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
|
||||||
|
LOGV(WII_IPC_WIIMOTE, 0, "=================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // WiiMoteEmu
|
||||||
|
|
|
@ -15,116 +15,39 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _EMU_DECLARATIONS_
|
|
||||||
#define _EMU_DECLARATIONS_
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Include
|
||||||
|
// ¯¯¯¯¯¯¯¯¯
|
||||||
|
#ifndef _EMU_SUBFUNCTIONS_
|
||||||
|
#define _EMU_SUBFUNCTIONS_
|
||||||
|
|
||||||
#include "pluginspecs_wiimote.h"
|
#include "pluginspecs_wiimote.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Common.h"
|
|
||||||
#include "wiimote_hid.h"
|
#include "Common.h" // Common
|
||||||
|
|
||||||
|
#include "wiimote_hid.h" // Local
|
||||||
#include "EmuDefinitions.h"
|
#include "EmuDefinitions.h"
|
||||||
#include "Encryption.h"
|
#include "Encryption.h"
|
||||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Declarations and definitions
|
||||||
|
// ¯¯¯¯¯¯¯¯¯
|
||||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||||
//extern void __Log(int log, const char *format, ...);
|
//extern void __Log(int log, const char *format, ...);
|
||||||
//extern void __Log(int log, int v, const char *format, ...);
|
//extern void __Log(int log, int v, const char *format, ...);
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
namespace WiiMoteEmu
|
namespace WiiMoteEmu
|
||||||
{
|
{
|
||||||
|
|
||||||
//******************************************************************************
|
|
||||||
// Definitions and variable declarations
|
|
||||||
//******************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
extern u8 g_Leds;
|
|
||||||
extern u8 g_Speaker;
|
|
||||||
extern u8 g_SpeakerVoice;
|
|
||||||
extern u8 g_IR;
|
|
||||||
|
|
||||||
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_RegIr[WIIMOTE_REG_IR_SIZE];
|
|
||||||
|
|
||||||
extern u8 g_ReportingMode;
|
|
||||||
extern u16 g_ReportingChannel;
|
|
||||||
|
|
||||||
extern wiimote_key g_ExtKey; // extension encryption key
|
|
||||||
|
|
||||||
|
|
||||||
static const u8 EepromData_0[] = {
|
|
||||||
0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30,
|
|
||||||
0xA7, 0x74, 0xD3, 0xA1, 0xAA, 0x8B, 0x99, 0xAE,
|
|
||||||
0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3, 0x82, 0x82,
|
|
||||||
0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E,
|
|
||||||
0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38,
|
|
||||||
0x40, 0x3E
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u8 EepromData_16D0[] = {
|
|
||||||
0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00,
|
|
||||||
0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99,
|
|
||||||
0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Default calibration for the nunchuck. It should be written to 0x20 - 0x3f of the
|
|
||||||
extension register. 0x80 is the neutral x and y accelerators and 0xb3 is the
|
|
||||||
neutral z accelerometer that is adjusted for gravity. */
|
|
||||||
static const u8 nunchuck_calibration[] =
|
|
||||||
{
|
|
||||||
0x80,0x80,0x80,0x00, 0xb3,0xb3,0xb3,0x00,
|
|
||||||
0xe0,0x20,0x80,0xe0, 0x20,0x80,0xee,0x43,
|
|
||||||
0x80,0x80,0x80,0x00, 0xb3,0xb3,0xb3,0x00,
|
|
||||||
0xe0,0x20,0x80,0xe0, 0x20,0x80,0xee,0x43
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Classic Controller calibration. 0x80 is the neutral for the analog triggers and
|
|
||||||
sticks. The left analog range is 0x1c - 0xe4 and the right is 0x28 - 0xd8.
|
|
||||||
We use this range because it's closest to the GC controller range. */
|
|
||||||
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,
|
|
||||||
0x80,0xd8,0x28,0x80, 0x20,0x20,0x95,0xea
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The Nunchuck id. It should be written to the last bytes of the
|
|
||||||
extension register */
|
|
||||||
static const u8 nunchuck_id[] =
|
|
||||||
{
|
|
||||||
0x00, 0x00, 0xa4, 0x20, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The Classic Controller id. It should be written to the last bytes of the
|
|
||||||
extension register */
|
|
||||||
static const u8 classic_id[] =
|
|
||||||
{
|
|
||||||
0x00, 0x00, 0xa4, 0x20, 0x01, 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The id for nothing inserted */
|
|
||||||
static const u8 nothing_id[] =
|
|
||||||
{
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x2e, 0x2e
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The id for a partially inserted extension */
|
|
||||||
static const u8 partially_id[] =
|
|
||||||
{
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void HidOutputReport(u16 _channelID, wm_report* sr);
|
void HidOutputReport(u16 _channelID, wm_report* sr);
|
||||||
|
|
||||||
void WmLeds(u16 _channelID, wm_leds* leds);
|
void WmLeds(u16 _channelID, wm_leds* leds);
|
||||||
|
@ -144,7 +67,6 @@ void SendReportCoreAccelIr10Ext(u16 _channelID);
|
||||||
int WriteWmReport(u8* dst, u8 channel);
|
int WriteWmReport(u8* dst, u8 channel);
|
||||||
void WmSendAck(u16 _channelID, u8 _reportID, u32 address);
|
void WmSendAck(u16 _channelID, u8 _reportID, u32 address);
|
||||||
|
|
||||||
|
|
||||||
void FillReportAcc(wm_accel& _acc);
|
void FillReportAcc(wm_accel& _acc);
|
||||||
void FillReportInfo(wm_core& _core);
|
void FillReportInfo(wm_core& _core);
|
||||||
void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1);
|
void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1);
|
||||||
|
@ -152,10 +74,6 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1);
|
||||||
void FillReportExtension(wm_extension& _ext);
|
void FillReportExtension(wm_extension& _ext);
|
||||||
void FillReportClassicExtension(wm_classic_extension& _ext);
|
void FillReportClassicExtension(wm_classic_extension& _ext);
|
||||||
|
|
||||||
u32 convert24bit(const u8* src);
|
|
||||||
u16 convert16bit(const u8* src);
|
|
||||||
void GetMousePos(float& x, float& y);
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif //_EMU_DECLARATIONS_
|
#endif //_EMU_DECLARATIONS_
|
||||||
|
|
|
@ -16,22 +16,28 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Includes
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
|
|
||||||
#include "pluginspecs_wiimote.h"
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Common.h"
|
|
||||||
|
#include "Common.h" // Common
|
||||||
|
#include "pluginspecs_wiimote.h"
|
||||||
|
#include "StringUtil.h" // For ArrayToString
|
||||||
|
|
||||||
#include "wiimote_hid.h"
|
#include "wiimote_hid.h"
|
||||||
|
#include "EmuMain.h"
|
||||||
#include "EmuSubroutines.h"
|
#include "EmuSubroutines.h"
|
||||||
#include "EmuDefinitions.h"
|
#include "EmuDefinitions.h"
|
||||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
#include "Console.h" // For startConsoleWin, wprintf, GetConsoleHwnd
|
||||||
#include "Config.h" // for g_Config
|
#include "Config.h" // For g_Config
|
||||||
|
//////////////////////////////////
|
||||||
|
|
||||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||||
|
|
||||||
|
|
||||||
namespace WiiMoteEmu
|
namespace WiiMoteEmu
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -42,10 +48,12 @@ namespace WiiMoteEmu
|
||||||
|
|
||||||
void FillReportInfo(wm_core& _core)
|
void FillReportInfo(wm_core& _core)
|
||||||
{
|
{
|
||||||
|
/* This has to be filled with zeroes because when no buttons are pressed the
|
||||||
|
value is 00 00 */
|
||||||
memset(&_core, 0x00, sizeof(wm_core));
|
memset(&_core, 0x00, sizeof(wm_core));
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// allow both mouse buttons and keyboard to press a and b
|
// Allow both mouse buttons and keyboard to press a and b
|
||||||
if(GetAsyncKeyState(VK_LBUTTON) ? 1 : 0 || GetAsyncKeyState('A') ? 1 : 0)
|
if(GetAsyncKeyState(VK_LBUTTON) ? 1 : 0 || GetAsyncKeyState('A') ? 1 : 0)
|
||||||
_core.a = 1;
|
_core.a = 1;
|
||||||
|
|
||||||
|
@ -295,9 +303,9 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
|
||||||
Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS;
|
Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill with 0xff if empty
|
// Fill with 0xff (0r 0x00?) if empty
|
||||||
memset(&_ir0, 0xFF, sizeof(wm_ir_extended));
|
memset(&_ir0, 0x00, sizeof(wm_ir_extended));
|
||||||
memset(&_ir1, 0xFF, sizeof(wm_ir_extended));
|
memset(&_ir1, 0x00, sizeof(wm_ir_extended));
|
||||||
|
|
||||||
float MouseX, MouseY;
|
float MouseX, MouseY;
|
||||||
GetMousePos(MouseX, MouseY);
|
GetMousePos(MouseX, MouseY);
|
||||||
|
@ -378,9 +386,9 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
|
||||||
Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS;
|
Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill with 0xff if empty
|
// Fill with 0x00 if empty
|
||||||
memset(&_ir0, 0xff, sizeof(wm_ir_basic));
|
memset(&_ir0, 0x00, sizeof(wm_ir_basic));
|
||||||
memset(&_ir1, 0xff, sizeof(wm_ir_basic));
|
memset(&_ir1, 0x00, sizeof(wm_ir_basic));
|
||||||
|
|
||||||
float MouseX, MouseY;
|
float MouseX, MouseY;
|
||||||
GetMousePos(MouseX, MouseY);
|
GetMousePos(MouseX, MouseY);
|
||||||
|
@ -449,7 +457,7 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
|
||||||
);*/
|
);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int abc = 0;
|
||||||
// ===================================================
|
// ===================================================
|
||||||
/* Generate the 6 byte extension report, encrypted. The bytes are JX JY AX AY AZ BT. */
|
/* Generate the 6 byte extension report, encrypted. The bytes are JX JY AX AY AZ BT. */
|
||||||
// ----------------
|
// ----------------
|
||||||
|
@ -463,6 +471,12 @@ void FillReportExtension(wm_extension& _ext)
|
||||||
_ext.az = 0xb3;
|
_ext.az = 0xb3;
|
||||||
|
|
||||||
|
|
||||||
|
_ext.ax += abc;
|
||||||
|
|
||||||
|
abc ++;
|
||||||
|
if (abc > 50) abc = 0;
|
||||||
|
|
||||||
|
|
||||||
_ext.jx = 0x80; // these are the default values unless we use them
|
_ext.jx = 0x80; // these are the default values unless we use them
|
||||||
_ext.jy = 0x80;
|
_ext.jy = 0x80;
|
||||||
_ext.bt = 0x03; // 0x03 means no button pressed, the button is zero active
|
_ext.bt = 0x03; // 0x03 means no button pressed, the button is zero active
|
||||||
|
@ -496,19 +510,30 @@ void FillReportExtension(wm_extension& _ext)
|
||||||
// TODO linux port
|
// TODO linux port
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Clear g_RegExtTmp by copying zeroes to it
|
/* Here we use g_RegExtTmpReport as a temporary storage for the enryption function because
|
||||||
memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp));
|
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
|
/* 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
|
0x00, the important thing is that we begin at an address evenly divisible
|
||||||
by 0x08 */
|
by 0x08 */
|
||||||
memcpy(g_RegExtTmp + 0x08, &_ext, sizeof(_ext));
|
memcpy(g_RegExtTmpReport + 0x08, &_ext, sizeof(_ext));
|
||||||
|
|
||||||
|
/**/if(GetAsyncKeyState('V')) // Log
|
||||||
|
{
|
||||||
|
std::string Temp = ArrayToString(g_RegExtTmpReport, sizeof(_ext), 0x08);
|
||||||
|
wprintf("Nunchuck DataFrame: %s\n", Temp.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// Encrypt it
|
// Encrypt it
|
||||||
wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[0x08], 0x08, sizeof(_ext));
|
wiimote_encrypt(&g_ExtKey, &g_RegExtTmpReport[0x08], 0x08, sizeof(_ext));
|
||||||
|
|
||||||
// Write it back
|
// Write it back to the extension
|
||||||
memcpy(&_ext, &g_RegExtTmp[0x08], sizeof(_ext));
|
memcpy(&_ext, &g_RegExtTmpReport[0x08], sizeof(_ext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -675,18 +700,17 @@ void FillReportClassicExtension(wm_classic_extension& _ext)
|
||||||
// TODO linux port
|
// TODO linux port
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Clear g_RegExtTmp by copying zeroes to it
|
// Clear g_RegExtTmp by copying zeroes to it
|
||||||
memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp));
|
memset(g_RegExtTmpReport, 0, sizeof(g_RegExtTmp));
|
||||||
|
|
||||||
/* Write the nunchuck inputs to it. We begin writing at 0x08, see comment above. */
|
/* Write the nunchuck inputs to it. We begin writing at 0x08, see comment above. */
|
||||||
memcpy(g_RegExtTmp + 0x08, &_ext, sizeof(_ext));
|
memcpy(g_RegExtTmpReport + 0x08, &_ext, sizeof(_ext));
|
||||||
|
|
||||||
// Encrypt it
|
// Encrypt it
|
||||||
wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[0x08], 0x08, 0x06);
|
wiimote_encrypt(&g_ExtKey, &g_RegExtTmpReport[0x08], 0x08, 0x06);
|
||||||
|
|
||||||
// Write it back
|
// Write it back
|
||||||
memcpy(&_ext, &g_RegExtTmp[0x08], sizeof(_ext));
|
memcpy(&_ext, &g_RegExtTmpReport[0x08], sizeof(_ext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Includes
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
|
@ -34,7 +37,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||||
|
///////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Declarations and definitions
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
SWiimoteInitialize g_WiimoteInitialize;
|
SWiimoteInitialize g_WiimoteInitialize;
|
||||||
|
|
||||||
bool g_UseRealWiiMote = false;
|
bool g_UseRealWiiMote = false;
|
||||||
|
@ -53,7 +61,12 @@ IMPLEMENT_APP_NO_MAIN(wxDLLApp)
|
||||||
|
|
||||||
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
||||||
#endif
|
#endif
|
||||||
|
////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Main function and WxWidgets initialization
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
|
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
|
||||||
DWORD dwReason, // reason called
|
DWORD dwReason, // reason called
|
||||||
|
@ -83,6 +96,9 @@ BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
// Exports
|
// Exports
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
|
@ -119,13 +135,26 @@ extern "C" void DllConfig(HWND _hParent)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Wiimote_Initialize(SWiimoteInitialize _WiimoteInitialize)
|
extern "C" bool Wiimote_Initialize(SWiimoteInitialize _WiimoteInitialize)
|
||||||
{
|
{
|
||||||
|
// ----------------------------------------
|
||||||
|
// Debugging window
|
||||||
|
// ----------
|
||||||
|
/*startConsoleWin(100, 750, "Wiimote"); // give room for 20 rows
|
||||||
|
wprintf("Wiimote console opened\n");
|
||||||
|
|
||||||
|
// Move window, TODO: make this
|
||||||
|
//MoveWindow(GetConsoleHwnd(), 0,400, 100*8,10*14, true); // small window
|
||||||
|
MoveWindow(GetConsoleHwnd(), 400,0, 100*8,70*14, true); // big window*/
|
||||||
|
// ---------------
|
||||||
|
|
||||||
g_WiimoteInitialize = _WiimoteInitialize;
|
g_WiimoteInitialize = _WiimoteInitialize;
|
||||||
|
|
||||||
/* We will run WiiMoteReal::Initialize() even if we are not using a real wiimote,
|
/* We will run WiiMoteReal::Initialize() even if we are not using a real wiimote,
|
||||||
we will initiate wiiuse.dll, but we will return before creating a new thread
|
we will initiate wiiuse.dll, but we will return before creating a new thread
|
||||||
for it in that case */
|
for it if we find no real Wiimotes. Then g_UseRealWiiMote will also be false
|
||||||
|
This function call will be done instantly if there is no real Wiimote connected.
|
||||||
|
I'm not sure how long time it takes if a Wiimote is connected. */
|
||||||
#if HAVE_WIIUSE
|
#if HAVE_WIIUSE
|
||||||
g_UseRealWiiMote = WiiMoteReal::Initialize() > 0;
|
g_UseRealWiiMote = WiiMoteReal::Initialize() > 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -133,13 +162,7 @@ extern "C" void Wiimote_Initialize(SWiimoteInitialize _WiimoteInitialize)
|
||||||
|
|
||||||
WiiMoteEmu::Initialize();
|
WiiMoteEmu::Initialize();
|
||||||
|
|
||||||
// Debugging window
|
return g_UseRealWiiMote;
|
||||||
/*startConsoleWin(100, 750, "Wiimote"); // give room for 20 rows
|
|
||||||
wprintf("Wiimote console opened\n");
|
|
||||||
|
|
||||||
// move window, TODO: make this
|
|
||||||
//MoveWindow(GetConsoleHwnd(), 0,400, 100*8,10*14, true); // small window
|
|
||||||
MoveWindow(GetConsoleHwnd(), 400,0, 100*8,70*14, true); // big window*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,6 +199,7 @@ extern "C" void Wiimote_InterruptChannel(u16 _channelID, const void* _pData, u32
|
||||||
LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str());
|
LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decice where to send the message
|
||||||
if (! g_UseRealWiiMote)
|
if (! g_UseRealWiiMote)
|
||||||
WiiMoteEmu::InterruptChannel(_channelID, _pData, _Size);
|
WiiMoteEmu::InterruptChannel(_channelID, _pData, _Size);
|
||||||
#if HAVE_WIIUSE
|
#if HAVE_WIIUSE
|
||||||
|
@ -209,6 +233,11 @@ extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _
|
||||||
LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
|
LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
/* This sends a Data Report from the Wiimote. See SystemTimers.cpp for the documentation of this
|
||||||
|
update. */
|
||||||
|
// ----------------
|
||||||
extern "C" void Wiimote_Update()
|
extern "C" void Wiimote_Update()
|
||||||
{
|
{
|
||||||
if (! g_UseRealWiiMote)
|
if (! g_UseRealWiiMote)
|
||||||
|
@ -223,6 +252,7 @@ extern "C" unsigned int Wiimote_GetAttachedControllers()
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
// ================
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
|
|
|
@ -101,7 +101,7 @@ struct wm_write_data
|
||||||
struct wm_acknowledge
|
struct wm_acknowledge
|
||||||
{
|
{
|
||||||
u8 Channel;
|
u8 Channel;
|
||||||
u8 unk0;
|
u8 unk0; // Core buttons state (wm_core), can be zero
|
||||||
u8 unk1;
|
u8 unk1;
|
||||||
u8 reportID;
|
u8 reportID;
|
||||||
u8 errorID;
|
u8 errorID;
|
||||||
|
|
|
@ -214,6 +214,8 @@ namespace WiiMoteReal
|
||||||
int Initialize()
|
int Initialize()
|
||||||
{
|
{
|
||||||
memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES);
|
memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES);
|
||||||
|
|
||||||
|
// Call Wiiuse.dll
|
||||||
g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES);
|
g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES);
|
||||||
g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5);
|
g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue