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)
|
||||
{
|
||||
fprintf(__fStdOut, s);
|
||||
//fflush(__fStdOut); // Write file now, don't wait
|
||||
fflush(__fStdOut); // Write file now, don't wait
|
||||
}
|
||||
|
||||
return(cnt);
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#ifndef MM_COMMON_H
|
||||
#define MM_COMMON_H
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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, ...);
|
||||
//////////////////////////////////
|
||||
|
||||
|
||||
#endif // MM_COMMON_H
|
|
@ -442,7 +442,11 @@ void CFrame::MM_OnLog(wxCommandEvent& event)
|
|||
MusicMod::bShowConsole = !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
|
||||
{
|
||||
#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
|
||||
|
@ -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
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
|
|
@ -15,6 +15,19 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// 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>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
@ -27,6 +40,9 @@
|
|||
#include "FileUtil.h"
|
||||
#include "StringUtil.h"
|
||||
#include "DynamicLibrary.h"
|
||||
#include "../../../../Branches/MusicMod/Common/Src/Console.h"
|
||||
///////////////////////////////////
|
||||
|
||||
|
||||
DynamicLibrary::DynamicLibrary()
|
||||
{
|
||||
|
@ -138,9 +154,10 @@ void* DynamicLibrary::Get(const char* funcname) const
|
|||
retval = dlsym(library, funcname);
|
||||
#endif
|
||||
|
||||
if (!retval) {
|
||||
if (!retval)
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -121,6 +121,10 @@ bool CBoot::LoadMapFromFilename(const std::string &_rFilename, const char *_game
|
|||
return success;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Load a GC or Wii BIOS file
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
bool CBoot::Load_BIOS(const std::string& _rBiosFilename)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
@ -129,6 +133,7 @@ bool CBoot::Load_BIOS(const std::string& _rBiosFilename)
|
|||
{
|
||||
if (pFile->GetSize() >= 1024*1024*2)
|
||||
{
|
||||
// Write it to memory
|
||||
u32 CopySize = (u32)pFile->GetSize() - 0x820;
|
||||
u8* pData = pFile->Lock(0x820, CopySize);
|
||||
Memory::WriteBigEData(pData, 0x81300000, CopySize);
|
||||
|
@ -143,7 +148,12 @@ bool CBoot::Load_BIOS(const std::string& _rBiosFilename)
|
|||
delete pFile;
|
||||
return bResult;
|
||||
}
|
||||
/////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Third boot step after BootManager and Core. See Call schedule in BootManager.cpp
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
bool CBoot::BootUp(const SCoreStartupParameter& _StartupPara)
|
||||
{
|
||||
const bool bDebugIsoBootup = false;
|
||||
|
@ -188,6 +198,7 @@ bool CBoot::BootUp(const SCoreStartupParameter& _StartupPara)
|
|||
}
|
||||
else
|
||||
{
|
||||
// If we can't load the BIOS file we use the HLE BIOS instead
|
||||
if (!Load_BIOS(_StartupPara.m_strBios))
|
||||
{
|
||||
// fails to load a BIOS so HLE it
|
||||
|
|
|
@ -41,7 +41,9 @@ void CBoot::RunFunction(u32 _iAddr)
|
|||
PowerPC::SingleStep();
|
||||
}
|
||||
|
||||
// BIOS HLE:
|
||||
// __________________________________________________________________________________________________
|
||||
//
|
||||
// GameCube BIOS HLE:
|
||||
// copy the apploader to 0x81200000
|
||||
// execute the apploader, function by function, using the above utility.
|
||||
void CBoot::EmulatedBIOS(bool _bDebug)
|
||||
|
@ -159,7 +161,7 @@ void CBoot::EmulatedBIOS(bool _bDebug)
|
|||
|
||||
// __________________________________________________________________________________________________
|
||||
//
|
||||
// BIOS HLE:
|
||||
// Wii BIOS HLE:
|
||||
// copy the apploader to 0x81200000
|
||||
// execute the apploader
|
||||
//
|
||||
|
@ -167,6 +169,7 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
|
|||
{
|
||||
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");
|
||||
if (pDump != NULL)
|
||||
{
|
||||
|
@ -301,10 +304,11 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
|
|||
after this check during booting. */
|
||||
VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
|
||||
Memory::Write_U8(0x80, 0x00003184);
|
||||
// ================
|
||||
}
|
||||
}
|
||||
|
||||
// apploader
|
||||
// Execute the apploader
|
||||
if (VolumeHandler::IsValid() && VolumeHandler::IsWii())
|
||||
{
|
||||
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);
|
||||
|
||||
// iAppLoaderInit
|
||||
LOG(BOOT, "Call iAppLoaderInit");
|
||||
LOG(BOOT, "Run iAppLoaderInit");
|
||||
PowerPC::ppcState.gpr[3] = 0x81300000;
|
||||
RunFunction(iAppLoaderInit);
|
||||
|
||||
// iAppLoaderMain
|
||||
LOG(BOOT, "Call iAppLoaderMain");
|
||||
/* Let the apploader load the exe to memory. At this point I get an unknwon IPC command
|
||||
(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
|
||||
{
|
||||
PowerPC::ppcState.gpr[3] = 0x81300004;
|
||||
|
@ -368,7 +376,7 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
|
|||
} while(PowerPC::ppcState.gpr[3] != 0x00);
|
||||
|
||||
// iAppLoaderClose
|
||||
LOG(BOOT, "call iAppLoaderClose");
|
||||
LOG(BOOT, "Run iAppLoaderClose");
|
||||
RunFunction(iAppLoaderClose);
|
||||
|
||||
// Load patches and run startup patches
|
||||
|
|
|
@ -94,7 +94,6 @@ void Callback_WiimoteInput(u16 _channelID, const void* _pData, u32 _Size);
|
|||
|
||||
// For keyboard shortcuts.
|
||||
void Callback_KeyPress(int key, bool shift, bool control);
|
||||
|
||||
TPeekMessages Callback_PeekMessages = NULL;
|
||||
TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL;
|
||||
|
||||
|
@ -106,6 +105,7 @@ TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL;
|
|||
void Stop();
|
||||
|
||||
bool g_bHwInit = false;
|
||||
bool g_bRealWiimote = false;
|
||||
HWND g_pWindowHandle = 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)
|
||||
{
|
||||
DisplayMessage(text, 3000);
|
||||
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)
|
||||
{
|
||||
if (g_pThread != NULL) {
|
||||
|
@ -153,6 +190,7 @@ bool Init(const SCoreStartupParameter _CoreParameter)
|
|||
|
||||
emuThreadGoing.Init();
|
||||
|
||||
// This will execute EmuThread() further down in this file
|
||||
g_pThread = new Common::Thread(EmuThread, (void*)&g_CoreStartupParameter);
|
||||
|
||||
emuThreadGoing.Wait();
|
||||
|
@ -168,16 +206,6 @@ bool Init(const SCoreStartupParameter _CoreParameter)
|
|||
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
|
||||
void Stop() // - Hammertime!
|
||||
|
@ -213,21 +241,6 @@ void Stop() // - Hammertime!
|
|||
Host_SetWaitCursor(false);
|
||||
}
|
||||
|
||||
void Callback_DebuggerBreak()
|
||||
{
|
||||
CCPU::EnableStepping(true);
|
||||
}
|
||||
|
||||
const SCoreStartupParameter& GetStartupParameter()
|
||||
{
|
||||
return g_CoreStartupParameter;
|
||||
}
|
||||
|
||||
void* GetWindowHandle()
|
||||
{
|
||||
return g_pWindowHandle;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Create the CPU thread
|
||||
|
@ -280,7 +293,7 @@ THREAD_RETURN CpuThread(void *pArg)
|
|||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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. */
|
||||
THREAD_RETURN EmuThread(void *pArg)
|
||||
{
|
||||
|
@ -348,7 +361,8 @@ THREAD_RETURN EmuThread(void *pArg)
|
|||
WiimoteInitialize.hWnd = g_pWindowHandle;
|
||||
WiimoteInitialize.pLog = Callback_WiimoteLog;
|
||||
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.
|
||||
|
|
|
@ -51,13 +51,14 @@ namespace Core
|
|||
void SaveState();
|
||||
void LoadState();
|
||||
|
||||
// get core parameters
|
||||
// Get core parameters
|
||||
extern SCoreStartupParameter g_CoreStartupParameter; //uck
|
||||
const SCoreStartupParameter& GetStartupParameter();
|
||||
|
||||
// make a screen shot
|
||||
// Make a screen shot
|
||||
bool MakeScreenshot(const std::string& _rFilename);
|
||||
void* GetWindowHandle();
|
||||
bool GetRealWiimote();
|
||||
|
||||
extern bool bReadTrace;
|
||||
extern bool bWriteTrace;
|
||||
|
|
|
@ -15,6 +15,51 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// 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 "../PatchEngine.h"
|
||||
#include "SystemTimers.h"
|
||||
|
@ -32,10 +77,15 @@
|
|||
#include "../IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Thread.h"
|
||||
#include "Timer.h"
|
||||
/////////////////////////////
|
||||
|
||||
|
||||
namespace SystemTimers
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations and definitions
|
||||
// -------------
|
||||
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||
|
||||
s64 fakeDec;
|
||||
|
@ -85,6 +135,8 @@ int
|
|||
// 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.
|
||||
FAKE_GP_WATCHDOG_PERIOD = GetTicksPerSecond() / 30;
|
||||
///////////////////////////////////
|
||||
|
||||
|
||||
u32 GetTicksPerSecond()
|
||||
{
|
||||
|
|
|
@ -399,8 +399,11 @@ void ExecuteCommand(u32 _Address)
|
|||
break;
|
||||
|
||||
default:
|
||||
_dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown Command %i (0x%08x)", Command, _Address);
|
||||
CCPU::Break();
|
||||
_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();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,16 +15,28 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Include
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#include "WII_IPC_HLE_Device_usb.h"
|
||||
#include "../Plugins/Plugin_Wiimote.h"
|
||||
|
||||
#include "../Core.h" // Local core functions
|
||||
#include "../Debugger/Debugger_SymbolMap.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_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)
|
||||
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
|
||||
, 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()
|
||||
{}
|
||||
///////////////////////////
|
||||
|
||||
|
||||
// ===================================================
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
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
|
||||
static int counter = 1000;
|
||||
/* I disabled this and disable m_ScanEnable instead to avoid running SendEventRequestConnection()
|
||||
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--;
|
||||
if (counter < 0)
|
||||
{
|
||||
test = false;
|
||||
//test = false;
|
||||
for (size_t i=0; i < m_WiiMotes.size(); i++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
/* 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)
|
||||
{
|
||||
// We have to disable scan now to avoid running this function over and over again
|
||||
m_ScanEnable = 0;
|
||||
|
||||
SQueuedEvent Event(sizeof(SHCIEventRequestConnection), 0);
|
||||
|
||||
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;
|
||||
};
|
||||
//////////////////////////////
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
|
||||
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteInquiryMode(u8* _Input)
|
||||
|
|
|
@ -29,7 +29,7 @@ void UnloadPlugin();
|
|||
// Function Types
|
||||
typedef void (__cdecl* TGetDllInfo)(PLUGIN_INFO*);
|
||||
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_Update)();
|
||||
typedef void (__cdecl* TWiimote_Output)(u16 _channelID, const void* _pData, u32 _Size);
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
BootManager.cpp BootCore
|
||||
Core Core.cpp Init Thread creation
|
||||
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 "Frame.h"
|
||||
#include "CodeWindow.h"
|
||||
#include "../../../../Branches/MusicMod/Common/Src/Console.h"
|
||||
#ifdef MUSICMOD
|
||||
#include "../../../Branches/MusicMod/Main/Src/Main.h" // MusicMod
|
||||
#endif
|
||||
|
|
|
@ -56,6 +56,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DolphinWX", "Core\DolphinWX
|
|||
ProjectSection(ProjectDependencies) = postProject
|
||||
{48AD7E0A-25B1-4974-A1E3-03F8C438D34F} = {48AD7E0A-25B1-4974-A1E3-03F8C438D34F}
|
||||
{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}
|
||||
{33546D62-7F34-4EA6-A88E-D538B36E16BF} = {33546D62-7F34-4EA6-A88E-D538B36E16BF}
|
||||
{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|x64.ActiveCfg = DebugFast|x64
|
||||
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|Win32.Build.0 = Release|Win32
|
||||
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|x64.ActiveCfg = Release|x64
|
||||
{CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|x64.Build.0 = Release|x64
|
||||
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
|
@ -322,8 +322,10 @@ Global
|
|||
{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}.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}.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.Build.0 = Release|x64
|
||||
{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.Build.0 = Debug|x64
|
||||
{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.Build.0 = Debug|x64
|
||||
{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.Build.0 = Release|x64
|
||||
{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
|
||||
//
|
||||
|
@ -8,9 +26,10 @@
|
|||
#include "PluginSpecs.h"
|
||||
#include "ExportProlog.h"
|
||||
|
||||
|
||||
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.
|
||||
typedef void (*TWiimoteInput)(u16 _channelID, const void* _pData, u32 _Size);
|
||||
|
||||
|
@ -22,6 +41,7 @@ typedef struct
|
|||
TWiimoteInput pWiimoteInput;
|
||||
} SWiimoteInitialize;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// I N T E R F A C E ////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -57,9 +77,9 @@ EXPORT void CALL DllDebugger(HWND _hParent, bool Show);
|
|||
// Function:
|
||||
// Purpose:
|
||||
// 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
|
||||
|
|
|
@ -15,12 +15,20 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Include
|
||||
// ------------
|
||||
//#include "Common.h" // for u16
|
||||
#include "ConfigDlg.h"
|
||||
#include "Config.h"
|
||||
#include "EmuSubroutines.h" // for WmRequestStatus
|
||||
/////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Event table
|
||||
// ------------
|
||||
BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
||||
EVT_CLOSE(ConfigDialog::OnClose)
|
||||
EVT_BUTTON(ID_CLOSE, ConfigDialog::CloseClick)
|
||||
|
@ -30,6 +38,8 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
|||
EVT_CHECKBOX(ID_NUNCHUCKCONNECTED, ConfigDialog::GeneralSettingsChanged)
|
||||
EVT_CHECKBOX(ID_CLASSICCONTROLLERCONNECTED, ConfigDialog::GeneralSettingsChanged)
|
||||
END_EVENT_TABLE()
|
||||
/////////////////////////////
|
||||
|
||||
|
||||
ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
|
||||
: wxDialog(parent, id, title, position, size, style)
|
||||
|
@ -42,6 +52,10 @@ ConfigDialog::~ConfigDialog()
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Create GUI
|
||||
// ------------
|
||||
void ConfigDialog::CreateGUIControls()
|
||||
{
|
||||
// Notebook
|
||||
|
@ -120,6 +134,7 @@ void ConfigDialog::AboutClick(wxCommandEvent& WXUNUSED (event))
|
|||
{
|
||||
|
||||
}
|
||||
//////////////////////////
|
||||
|
||||
|
||||
// ===================================================
|
||||
|
@ -159,8 +174,12 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
|
|||
g_Config.bClassicControllerConnected = false;
|
||||
// Disconnect the extension so that the game recognize the change
|
||||
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();
|
||||
|
||||
// Generate connect/disconnect status event
|
||||
|
|
|
@ -16,37 +16,75 @@
|
|||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
// --------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <windows.h>
|
||||
#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
|
||||
bool g_consoleEnable = true;
|
||||
int gSaveFile = 0;
|
||||
#define DEBUG_WIIMOTE
|
||||
bool gSaveFile = true;
|
||||
#define DEBUG_WIIMOTE // On or off
|
||||
const int nFiles = 1;
|
||||
|
||||
|
||||
// --------------------
|
||||
// Settings
|
||||
int nFiles = 1;
|
||||
|
||||
|
||||
// --------------------
|
||||
// Create handles
|
||||
|
||||
#ifdef DEBUG_WIIMOTE
|
||||
FILE* __fStdOut[1]; // you have to update this manually, we can't place a nFiles in there
|
||||
FILE* __fStdOut[nFiles];
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
HANDLE __hStdOut = NULL;
|
||||
#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
|
||||
|
@ -69,7 +107,7 @@ void startConsoleWin(int width, int height, char* fname)
|
|||
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// Write to a file
|
||||
// Create a file for this
|
||||
if(fname)
|
||||
{
|
||||
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
|
||||
//to make it work
|
||||
fprintf(__fStdOut[a], s);
|
||||
fflush(__fStdOut[0]); // Write file now, don't wait
|
||||
// -------------
|
||||
|
||||
return(cnt);
|
||||
|
@ -135,14 +174,20 @@ int wprintf(const char *fmt, ...)
|
|||
cnt = vsnprintf(s, 500, fmt, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
DWORD cCharsWritten;
|
||||
DWORD cCharsWritten; // We will get a value back here
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// ------------------------------------------
|
||||
// Write to console
|
||||
// ----------------
|
||||
if(__hStdOut)
|
||||
{
|
||||
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
|
||||
}
|
||||
// -------------
|
||||
|
||||
// ----------------------------------------
|
||||
// Write to file
|
||||
// ----------------
|
||||
aprintf(0, s);
|
||||
|
||||
return(cnt);
|
||||
#else
|
||||
|
|
|
@ -15,7 +15,19 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// 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);
|
||||
int wprintf(const char *fmt, ...);
|
||||
int aprintf(int a, const char *fmt, ...);
|
||||
|
@ -24,3 +36,6 @@ void ClearScreen();
|
|||
#ifdef _WIN32
|
||||
HWND GetConsoleHwnd(void);
|
||||
#endif
|
||||
///////////////////////////////
|
||||
|
||||
#endif // WIIMOTE_CONSOLE_H
|
|
@ -20,14 +20,18 @@
|
|||
|
||||
// ===================================================
|
||||
/* 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
|
||||
[c.left etc] [c.a etc] acc.x y z ir0.x y ? ir1.x y ? ir2.x y ? ir3.x y ?
|
||||
|
||||
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
|
||||
|
@ -43,23 +47,32 @@
|
|||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include <vector>
|
||||
#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 "EmuSubroutines.h"
|
||||
#include "EmuDefinitions.h"
|
||||
#include "Encryption.h" // for extension encryption
|
||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||
#include "Config.h" // for g_Config
|
||||
///////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations and definitions
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
//extern void __Log(int log, const char *format, ...);
|
||||
//extern void __Log(int log, int v, const char *format, ...);
|
||||
///////////////////////////////
|
||||
|
||||
|
||||
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, " All The Time: %x (not only on data change)", dr->all_the_time);
|
||||
LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode);
|
||||
wprintf("\nData reporting mode: 0x%02x", dr->mode);
|
||||
wprintf("\nData reporting channel: 0x%04x\n", _channelID);
|
||||
//wprintf("Data reporting mode: 0x%02x\n", dr->mode);
|
||||
//wprintf("Data reporting channel: 0x%04x\n", _channelID);
|
||||
|
||||
|
||||
g_ReportingMode = dr->mode;
|
||||
g_ReportingChannel = _channelID;
|
||||
switch(dr->mode) { //see Wiimote_Update()
|
||||
switch(dr->mode) // See Wiimote_Update()
|
||||
{
|
||||
case WM_REPORT_CORE:
|
||||
case WM_REPORT_CORE_ACCEL:
|
||||
case WM_REPORT_CORE_ACCEL_IR12:
|
||||
|
@ -270,7 +283,7 @@ void SendReportCoreAccelIr10Ext(u16 _channelID)
|
|||
#ifdef _WIN32
|
||||
/*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());
|
||||
}*/
|
||||
#endif
|
||||
|
|
|
@ -15,8 +15,11 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _EMU_DECLARATIONS_
|
||||
#define _EMU_DECLARATIONS_
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#ifndef _EMU_DEFINITIONS_
|
||||
#define _EMU_DEFINITIONS_
|
||||
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
|
@ -27,6 +30,7 @@
|
|||
#include "EmuDefinitions.h"
|
||||
#include "Encryption.h"
|
||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||
//////////////////////////
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
|
@ -43,16 +47,18 @@ u8 g_SpeakerVoice = 0x1; // 1 = on
|
|||
u8 g_IR = 0x1; // 1 = on
|
||||
|
||||
u8 g_Eeprom[WIIMOTE_EEPROM_SIZE];
|
||||
|
||||
u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE];
|
||||
u8 g_RegExt[WIIMOTE_REG_EXT_SIZE];
|
||||
u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE];
|
||||
u8 g_RegExtTmpReport[WIIMOTE_REG_EXT_SIZE];
|
||||
u8 g_RegIr[WIIMOTE_REG_IR_SIZE];
|
||||
|
||||
u8 g_ReportingMode; // the reporting mode and channel id
|
||||
u8 g_ReportingMode; // The reporting mode and channel id
|
||||
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
|
||||
|
||||
|
|
|
@ -15,15 +15,18 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _EMU_DEFINITIONS_
|
||||
#define _EMU_DEFINITIONS_
|
||||
#ifndef _EMU_DECLARATIONS_
|
||||
#define _EMU_DECLARATIONS_
|
||||
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "wiimote_hid.h"
|
||||
#include "Encryption.h"
|
||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
@ -52,12 +55,106 @@ namespace WiiMoteEmu
|
|||
#define wBOTTOM 625
|
||||
#define wSENSOR_BAR_RADIUS 200
|
||||
|
||||
// vars
|
||||
// Registry sizes
|
||||
#define WIIMOTE_EEPROM_SIZE (16*1024)
|
||||
#define WIIMOTE_REG_SPEAKER_SIZE 10
|
||||
#define WIIMOTE_REG_EXT_SIZE 0x100
|
||||
#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
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include <vector>
|
||||
|
@ -31,492 +34,341 @@
|
|||
#include "Encryption.h" // for extension encryption
|
||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||
#include "Config.h" // for g_Config
|
||||
////////////////////////////////////
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
//******************************************************************************
|
||||
// Subroutines
|
||||
//******************************************************************************
|
||||
|
||||
|
||||
|
||||
// ===================================================
|
||||
/* 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 */
|
||||
// ----------------
|
||||
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, "===========================================================");
|
||||
/* Bit shift conversions */
|
||||
// -------------
|
||||
u32 convert24bit(const u8* src) {
|
||||
return (src[0] << 16) | (src[1] << 8) | src[2];
|
||||
}
|
||||
|
||||
|
||||
// ===================================================
|
||||
/* 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;
|
||||
u16 convert16bit(const u8* src) {
|
||||
return (src[0] << 8) | src[1];
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// ===================================================
|
||||
/* LED (blue lights) report. */
|
||||
/* Calibrate the mouse position to the emulation window. */
|
||||
// ----------------
|
||||
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)
|
||||
void GetMousePos(float& x, float& y)
|
||||
{
|
||||
u8 DataFrame[1024];
|
||||
u32 Offset = 0;
|
||||
#ifdef _WIN32
|
||||
POINT point;
|
||||
|
||||
// Header
|
||||
hid_packet* pHidHeader = (hid_packet*)(DataFrame + Offset);
|
||||
pHidHeader->type = HID_TYPE_DATA;
|
||||
pHidHeader->param = HID_PARAM_INPUT;
|
||||
Offset += sizeof(hid_packet);
|
||||
GetCursorPos(&point);
|
||||
ScreenToClient(g_WiimoteInitialize.hWnd, &point);
|
||||
|
||||
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);
|
||||
RECT Rect;
|
||||
GetClientRect(g_WiimoteInitialize.hWnd, &Rect);
|
||||
|
||||
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());
|
||||
int width = Rect.right - Rect.left;
|
||||
int height = Rect.bottom - Rect.top;
|
||||
|
||||
/* 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);
|
||||
x = point.x / (float)width;
|
||||
y = point.y / (float)height;
|
||||
#else
|
||||
// TODO fix on linux
|
||||
x = 0.5f;
|
||||
y = 0.5f;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ===================================================
|
||||
/* Read data from Wiimote and Extensions registers. */
|
||||
/* Homebrew encryption for 0x00000000 encryption keys. */
|
||||
// ----------------
|
||||
void WmReadData(u16 _channelID, wm_read_data* rd)
|
||||
void CryptBuffer(u8* _buffer, u8 _size)
|
||||
{
|
||||
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)
|
||||
for (int i=0; i<_size; i++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
SendReadDataReply(_channelID, block+address, address, (u8)size);
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x!", size, rd->space);
|
||||
_buffer[i] = ((_buffer[i] - 0x17) ^ 0x17) & 0xFF;
|
||||
}
|
||||
|
||||
// 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)
|
||||
void WriteCrypted16(u8* _baseBlock, u16 _address, u16 _value)
|
||||
{
|
||||
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());
|
||||
u16 cryptedValue = _value;
|
||||
CryptBuffer((u8*)&cryptedValue, sizeof(u16));
|
||||
|
||||
// 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("\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;
|
||||
}
|
||||
|
||||
|
||||
// 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, "==========================================");
|
||||
*(u16*)(_baseBlock + _address) = cryptedValue;
|
||||
//PanicAlert("Converted %04x to %04x", _value, cryptedValue);
|
||||
}
|
||||
// ================
|
||||
|
||||
|
||||
// ===================================================
|
||||
/* 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. */
|
||||
/* Write initial values to Eeprom and registers. */
|
||||
// ----------------
|
||||
void WmRequestStatus(u16 _channelID, wm_request_status* rs)
|
||||
void Initialize()
|
||||
{
|
||||
//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);
|
||||
memset(g_Eeprom, 0, WIIMOTE_EEPROM_SIZE);
|
||||
memcpy(g_Eeprom, EepromData_0, sizeof(EepromData_0));
|
||||
memcpy(g_Eeprom + 0x16D0, EepromData_16D0, sizeof(EepromData_16D0));
|
||||
|
||||
//SendStatusReport();
|
||||
u8 DataFrame[1024];
|
||||
u32 Offset = WriteWmReport(DataFrame, WM_STATUS_REPORT);
|
||||
g_ReportingMode = 0;
|
||||
|
||||
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
|
||||
/* 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
|
||||
|
||||
// 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);
|
||||
// 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_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
|
||||
LOGV(WII_IPC_WIIMOTE, 0, "=================================================");
|
||||
|
||||
// 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
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
u32 convert24bit(const u8* src);
|
||||
u16 convert16bit(const u8* src);
|
||||
void GetMousePos(float& x, float& y);
|
||||
|
||||
void Initialize();
|
||||
void DoState(void* ptr, int mode);
|
||||
void Shutdown(void);
|
||||
|
|
|
@ -36,7 +36,9 @@
|
|||
// ================
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include <vector>
|
||||
|
@ -51,243 +53,504 @@
|
|||
#include "EmuDefinitions.h"
|
||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||
#include "Config.h" // for g_Config
|
||||
/////////////////////////////////
|
||||
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
POINT point;
|
||||
void HidOutputReport(u16 _channelID, wm_report* sr) {
|
||||
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
||||
LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport (0x%02x)", sr->channel);
|
||||
std::string Temp;
|
||||
|
||||
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++)
|
||||
switch(sr->channel)
|
||||
{
|
||||
_buffer[i] = ((_buffer[i] - 0x17) ^ 0x17) & 0xFF;
|
||||
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);
|
||||
//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;
|
||||
|
||||
/* 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; // g_SpeakerVoice
|
||||
else if(sr->data[0] == 0x06) g_SpeakerVoice = 1;
|
||||
break;
|
||||
default:
|
||||
PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->channel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
||||
}
|
||||
|
||||
|
||||
// ===================================================
|
||||
/* This function produce Wiimote Input, i.e. reports from the Wiimote in response
|
||||
to Output from the Wii. */
|
||||
/* Generate the right address for wm reports. */
|
||||
// ----------------
|
||||
void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
|
||||
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 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)
|
||||
{
|
||||
LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
|
||||
const u8* data = (const u8*)_pData;
|
||||
u8 DataFrame[1024];
|
||||
u32 Offset = 0;
|
||||
|
||||
// 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());
|
||||
// Header
|
||||
hid_packet* pHidHeader = (hid_packet*)(DataFrame + Offset);
|
||||
pHidHeader->type = HID_TYPE_DATA;
|
||||
pHidHeader->param = HID_PARAM_INPUT;
|
||||
Offset += sizeof(hid_packet);
|
||||
|
||||
hid_packet* hidp = (hid_packet*) data;
|
||||
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);
|
||||
|
||||
switch(hidp->type)
|
||||
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)
|
||||
{
|
||||
case HID_TYPE_DATA:
|
||||
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)
|
||||
{
|
||||
switch(hidp->param)
|
||||
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;
|
||||
case 0xA4:
|
||||
block = g_RegExt;
|
||||
blockSize = WIIMOTE_REG_EXT_SIZE;
|
||||
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: Read ExtReg ****************************");
|
||||
//Tmp = ArrayToString(g_RegExt, size, (address & 0xffff));
|
||||
//LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
|
||||
//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)
|
||||
{
|
||||
case HID_PARAM_OUTPUT:
|
||||
{
|
||||
wm_report* sr = (wm_report*)hidp->data;
|
||||
HidOutputReport(_channelID, sr);
|
||||
/* 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));
|
||||
|
||||
/* 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;
|
||||
// Encrypt g_RegExtTmp at that location
|
||||
wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[address & 0xffff], (address & 0xffff), (u8)size);
|
||||
|
||||
default:
|
||||
PanicAlert("HidInput: HID_TYPE_DATA - param 0x%02x", hidp->type, hidp->param);
|
||||
break;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
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
|
||||
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
|
||||
{
|
||||
LOG(WII_IPC_WIIMOTE, "Wiimote_ControlChannel");
|
||||
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());
|
||||
PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x!", size, rd->space);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// Acknowledge the 0x17 read, we will do this from InterruptChannel()
|
||||
//WmSendAck(_channelID, WM_READ_DATA, _address);
|
||||
|
||||
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
|
||||
}
|
||||
|
||||
void Update()
|
||||
|
||||
|
||||
// ===================================================
|
||||
/* Write data to Wiimote and Extensions registers. */
|
||||
// ----------------
|
||||
void WmWriteData(u16 _channelID, wm_write_data* wd)
|
||||
{
|
||||
//LOG(WII_IPC_WIIMOTE, "Wiimote_Update");
|
||||
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());
|
||||
|
||||
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;
|
||||
// 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);
|
||||
}
|
||||
// g_ReportingMode = 0;
|
||||
// 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,115 +15,38 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// 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 <vector>
|
||||
#include <string>
|
||||
#include "Common.h"
|
||||
#include "wiimote_hid.h"
|
||||
|
||||
#include "Common.h" // Common
|
||||
|
||||
#include "wiimote_hid.h" // Local
|
||||
#include "EmuDefinitions.h"
|
||||
#include "Encryption.h"
|
||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||
////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations and definitions
|
||||
// ¯¯¯¯¯¯¯¯¯
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
//extern void __Log(int log, const char *format, ...);
|
||||
//extern void __Log(int log, int v, const char *format, ...);
|
||||
///////////////////////////////
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
@ -144,7 +67,6 @@ void SendReportCoreAccelIr10Ext(u16 _channelID);
|
|||
int WriteWmReport(u8* dst, u8 channel);
|
||||
void WmSendAck(u16 _channelID, u8 _reportID, u32 address);
|
||||
|
||||
|
||||
void FillReportAcc(wm_accel& _acc);
|
||||
void FillReportInfo(wm_core& _core);
|
||||
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 FillReportClassicExtension(wm_classic_extension& _ext);
|
||||
|
||||
u32 convert24bit(const u8* src);
|
||||
u16 convert16bit(const u8* src);
|
||||
void GetMousePos(float& x, float& y);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //_EMU_DECLARATIONS_
|
||||
|
|
|
@ -16,22 +16,28 @@
|
|||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "Common.h"
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "pluginspecs_wiimote.h"
|
||||
#include "StringUtil.h" // For ArrayToString
|
||||
|
||||
#include "wiimote_hid.h"
|
||||
#include "EmuMain.h"
|
||||
#include "EmuSubroutines.h"
|
||||
#include "EmuDefinitions.h"
|
||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||
#include "Config.h" // for g_Config
|
||||
#include "Console.h" // For startConsoleWin, wprintf, GetConsoleHwnd
|
||||
#include "Config.h" // For g_Config
|
||||
//////////////////////////////////
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
|
@ -42,10 +48,12 @@ namespace WiiMoteEmu
|
|||
|
||||
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));
|
||||
|
||||
#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)
|
||||
_core.a = 1;
|
||||
|
||||
|
@ -295,9 +303,9 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
|
|||
Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS;
|
||||
}
|
||||
|
||||
// Fill with 0xff if empty
|
||||
memset(&_ir0, 0xFF, sizeof(wm_ir_extended));
|
||||
memset(&_ir1, 0xFF, sizeof(wm_ir_extended));
|
||||
// Fill with 0xff (0r 0x00?) if empty
|
||||
memset(&_ir0, 0x00, sizeof(wm_ir_extended));
|
||||
memset(&_ir1, 0x00, sizeof(wm_ir_extended));
|
||||
|
||||
float 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;
|
||||
}
|
||||
|
||||
// Fill with 0xff if empty
|
||||
memset(&_ir0, 0xff, sizeof(wm_ir_basic));
|
||||
memset(&_ir1, 0xff, sizeof(wm_ir_basic));
|
||||
// Fill with 0x00 if empty
|
||||
memset(&_ir0, 0x00, sizeof(wm_ir_basic));
|
||||
memset(&_ir1, 0x00, sizeof(wm_ir_basic));
|
||||
|
||||
float 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. */
|
||||
// ----------------
|
||||
|
@ -463,6 +471,12 @@ void FillReportExtension(wm_extension& _ext)
|
|||
_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.jy = 0x80;
|
||||
_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
|
||||
#endif
|
||||
|
||||
// Clear g_RegExtTmp by copying zeroes to it
|
||||
memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp));
|
||||
/* Here we use g_RegExtTmpReport as a temporary storage for the enryption function because
|
||||
the type if array may have some importance for wiimote_encrypt(). We avoid using
|
||||
g_RegExtTmp that is used in EmuMain.cpp because if this runs on a different thread
|
||||
there is a small chance that they may interfer with each other. */
|
||||
|
||||
// Clear g_RegExtTmpReport by copying zeroes to it, this may not be needed
|
||||
memset(g_RegExtTmpReport, 0, sizeof(g_RegExtTmp));
|
||||
|
||||
/* Write the nunchuck inputs to it. We begin writing at 0x08, but it could also be
|
||||
0x00, the important thing is that we begin at an address evenly divisible
|
||||
by 0x08 */
|
||||
memcpy(g_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
|
||||
wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[0x08], 0x08, sizeof(_ext));
|
||||
wiimote_encrypt(&g_ExtKey, &g_RegExtTmpReport[0x08], 0x08, sizeof(_ext));
|
||||
|
||||
// Write it back
|
||||
memcpy(&_ext, &g_RegExtTmp[0x08], sizeof(_ext));
|
||||
// Write it back to the extension
|
||||
memcpy(&_ext, &g_RegExtTmpReport[0x08], sizeof(_ext));
|
||||
}
|
||||
|
||||
|
||||
|
@ -675,18 +700,17 @@ void FillReportClassicExtension(wm_classic_extension& _ext)
|
|||
// TODO linux port
|
||||
#endif
|
||||
|
||||
|
||||
// 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. */
|
||||
memcpy(g_RegExtTmp + 0x08, &_ext, sizeof(_ext));
|
||||
memcpy(g_RegExtTmpReport + 0x08, &_ext, sizeof(_ext));
|
||||
|
||||
// Encrypt it
|
||||
wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[0x08], 0x08, 0x06);
|
||||
wiimote_encrypt(&g_ExtKey, &g_RegExtTmpReport[0x08], 0x08, 0x06);
|
||||
|
||||
// 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/
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#include "Common.h"
|
||||
#include "Config.h"
|
||||
#include "StringUtil.h"
|
||||
|
@ -34,7 +37,12 @@
|
|||
#endif
|
||||
|
||||
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
|
||||
///////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations and definitions
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
bool g_UseRealWiiMote = false;
|
||||
|
@ -53,7 +61,12 @@ IMPLEMENT_APP_NO_MAIN(wxDLLApp)
|
|||
|
||||
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
||||
#endif
|
||||
////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Main function and WxWidgets initialization
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#ifdef _WIN32
|
||||
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
|
||||
DWORD dwReason, // reason called
|
||||
|
@ -83,6 +96,9 @@ BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
|
|||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
/////////////////////////////////////
|
||||
|
||||
|
||||
//******************************************************************************
|
||||
// Exports
|
||||
//******************************************************************************
|
||||
|
@ -119,27 +135,34 @@ extern "C" void DllConfig(HWND _hParent)
|
|||
#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;
|
||||
|
||||
/* 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
|
||||
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
|
||||
g_UseRealWiiMote = WiiMoteReal::Initialize() > 0;
|
||||
#endif
|
||||
g_Config.Load(); // load config settings
|
||||
|
||||
WiiMoteEmu::Initialize();
|
||||
WiiMoteEmu::Initialize();
|
||||
|
||||
// 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*/
|
||||
return g_UseRealWiiMote;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
// Decice where to send the message
|
||||
if (! g_UseRealWiiMote)
|
||||
WiiMoteEmu::InterruptChannel(_channelID, _pData, _Size);
|
||||
#if HAVE_WIIUSE
|
||||
|
@ -209,6 +233,11 @@ extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _
|
|||
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()
|
||||
{
|
||||
if (! g_UseRealWiiMote)
|
||||
|
@ -223,6 +252,7 @@ extern "C" unsigned int Wiimote_GetAttachedControllers()
|
|||
{
|
||||
return 1;
|
||||
}
|
||||
// ================
|
||||
|
||||
|
||||
// ===================================================
|
||||
|
|
|
@ -101,7 +101,7 @@ struct wm_write_data
|
|||
struct wm_acknowledge
|
||||
{
|
||||
u8 Channel;
|
||||
u8 unk0;
|
||||
u8 unk0; // Core buttons state (wm_core), can be zero
|
||||
u8 unk1;
|
||||
u8 reportID;
|
||||
u8 errorID;
|
||||
|
|
|
@ -214,6 +214,8 @@ namespace WiiMoteReal
|
|||
int Initialize()
|
||||
{
|
||||
memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES);
|
||||
|
||||
// Call Wiiuse.dll
|
||||
g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES);
|
||||
g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5);
|
||||
|
||||
|
|
Loading…
Reference in New Issue