diff --git a/Branches/MusicMod/Common/Src/Console.cpp b/Branches/MusicMod/Common/Src/Console.cpp index fed086c040..aa5ad57108 100644 --- a/Branches/MusicMod/Common/Src/Console.cpp +++ b/Branches/MusicMod/Common/Src/Console.cpp @@ -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); diff --git a/Branches/MusicMod/Common/Src/Console.h b/Branches/MusicMod/Common/Src/Console.h index 8add97756b..259a795ef1 100644 --- a/Branches/MusicMod/Common/Src/Console.h +++ b/Branches/MusicMod/Common/Src/Console.h @@ -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 \ No newline at end of file diff --git a/Branches/MusicMod/Main/Src/Frame.cpp b/Branches/MusicMod/Main/Src/Frame.cpp index cd76d3a448..c3977729b6 100644 --- a/Branches/MusicMod/Main/Src/Frame.cpp +++ b/Branches/MusicMod/Main/Src/Frame.cpp @@ -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) diff --git a/Branches/MusicMod/Main/Src/Main.cpp b/Branches/MusicMod/Main/Src/Main.cpp index c55fca0401..20fb43d978 100644 --- a/Branches/MusicMod/Main/Src/Main.cpp +++ b/Branches/MusicMod/Main/Src/Main.cpp @@ -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 // --------------------------------------------------------------------------------------- diff --git a/Source/Core/Common/Src/DynamicLibrary.cpp b/Source/Core/Common/Src/DynamicLibrary.cpp index 418d015b5b..53da3e21aa 100644 --- a/Source/Core/Common/Src/DynamicLibrary.cpp +++ b/Source/Core/Common/Src/DynamicLibrary.cpp @@ -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 #ifdef _WIN32 #include @@ -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; diff --git a/Source/Core/Core/Src/Boot/Boot.cpp b/Source/Core/Core/Src/Boot/Boot.cpp index 7ad7bb8b5c..e858df55b5 100644 --- a/Source/Core/Core/Src/Boot/Boot.cpp +++ b/Source/Core/Core/Src/Boot/Boot.cpp @@ -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 diff --git a/Source/Core/Core/Src/Boot/Boot_BIOSEmu.cpp b/Source/Core/Core/Src/Boot/Boot_BIOSEmu.cpp index cf7a30f5aa..f3f54f16bf 100644 --- a/Source/Core/Core/Src/Boot/Boot_BIOSEmu.cpp +++ b/Source/Core/Core/Src/Boot/Boot_BIOSEmu.cpp @@ -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 diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index b9c471b3d2..6ab826d4a5 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -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. diff --git a/Source/Core/Core/Src/Core.h b/Source/Core/Core/Src/Core.h index 2382d0651b..c24a688a3b 100644 --- a/Source/Core/Core/Src/Core.h +++ b/Source/Core/Core/Src/Core.h @@ -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; diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp index d9ec74be3e..7cc1083534 100644 --- a/Source/Core/Core/Src/HW/SystemTimers.cpp +++ b/Source/Core/Core/Src/HW/SystemTimers.cpp @@ -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() { diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp index 1e8cc24eca..5fe313991f 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -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; } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index 801168847c..dba7cd9a87 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -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) diff --git a/Source/Core/Core/Src/Plugins/Plugin_Wiimote.h b/Source/Core/Core/Src/Plugins/Plugin_Wiimote.h index 74edc4153b..1605ba2446 100644 --- a/Source/Core/Core/Src/Plugins/Plugin_Wiimote.h +++ b/Source/Core/Core/Src/Plugins/Plugin_Wiimote.h @@ -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); diff --git a/Source/Core/DolphinWX/Src/BootManager.cpp b/Source/Core/DolphinWX/Src/BootManager.cpp index adf3624387..f7caa88d1d 100644 --- a/Source/Core/DolphinWX/Src/BootManager.cpp +++ b/Source/Core/DolphinWX/Src/BootManager.cpp @@ -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 diff --git a/Source/MusicMod.sln b/Source/MusicMod.sln index 6556e59963..46729a5da4 100644 --- a/Source/MusicMod.sln +++ b/Source/MusicMod.sln @@ -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 diff --git a/Source/PluginSpecs/pluginspecs_wiimote.h b/Source/PluginSpecs/pluginspecs_wiimote.h index 5f9ce6a0d5..9ba08baf08 100644 --- a/Source/PluginSpecs/pluginspecs_wiimote.h +++ b/Source/PluginSpecs/pluginspecs_wiimote.h @@ -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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp index 4b30f46e96..47050b911c 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp @@ -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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/Console.cpp b/Source/Plugins/Plugin_Wiimote/Src/Console.cpp index e366b498e2..438738b80d 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Console.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Console.cpp @@ -16,37 +16,75 @@ // http://code.google.com/p/dolphin-emu/ -// -------------------- + +////////////////////////////////////////////////////////////////////////////////////////// // Includes +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ #include #include #ifdef _WIN32 -#include + #include #endif +#include "StringUtil.h" + +#define HAVE_WX 1 +#if defined(HAVE_WX) && HAVE_WX // wxWidgets + #include // 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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/Console.h b/Source/Plugins/Plugin_Wiimote/Src/Console.h index 15a44b86b7..d2ba1ce5d3 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Console.h +++ b/Source/Plugins/Plugin_Wiimote/Src/Console.h @@ -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 +////////////////////////////// + +////////////////////////////////////////////////////////////////////////////////////////// +// 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 \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp index b2ab217a8f..b075609e4e 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp @@ -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 #include -#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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp index 365a2f0f57..1e72df255e 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp @@ -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 AckDelay; + +wiimote_key g_ExtKey; // The extension encryption key } // namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h index 8f47b971ad..828f7564f8 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h @@ -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 #include + #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 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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index 60fdded278..d626580995 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -16,6 +16,9 @@ // http://code.google.com/p/dolphin-emu/ +////////////////////////////////////////////////////////////////////////////////////////// +// Includes +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ #include "pluginspecs_wiimote.h" #include @@ -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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h index 0e21014e2e..a6fb370034 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h @@ -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); diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp index 996bedc0a7..f19179725a 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp @@ -36,7 +36,9 @@ // ================ - +////////////////////////////////////////////////////////////////////////////////////////// +// Includes +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ #include "pluginspecs_wiimote.h" #include @@ -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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h index f7f3b72015..20ac1f3c4f 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h @@ -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 #include -#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_ diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index 90edacbd7d..ed3270d6ba 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -16,22 +16,28 @@ // http://code.google.com/p/dolphin-emu/ +////////////////////////////////////////////////////////////////////////////////////////// +// Includes +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ #include -#include "pluginspecs_wiimote.h" - #include #include -#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)); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index cbc035fafd..ebaab22d13 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -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; } +// ================ // =================================================== diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h index 7e8c5bbdcf..b792591632 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h @@ -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; diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp index 20a8a2a7da..9a6edb8dcc 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp @@ -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);