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 c5d440852c..88e72da3a3 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 @@ -327,18 +327,24 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() #ifdef _WIN32 + // FiRES: TODO find a good solution to do this static bool test = true; - if (test && GetAsyncKeyState(VK_LBUTTON) && GetAsyncKeyState(VK_RBUTTON)) + static int counter = 1000; + if (test && !stricmp(m_LocalName, "Wii") && (m_ScanEnable & 0x2)) { - test = false; - for (size_t i=0; iscan_enable]); SendEventCommandComplete(HCI_CMD_WRITE_SCAN_ENABLE, &Reply, sizeof(hci_write_scan_enable_rp)); - - return; - - // TODO: fix this ugly request connection hack :) - //for homebrew works this - for (size_t i=0; iscan_enable)) - { - SendEventRequestConnection(m_WiiMotes[i]); - } - } } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteInquiryMode(u8* _Input) @@ -1673,7 +1667,16 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDisconnect(u8* _Input) pWiimote->EventDisconnect(); } - PanicAlert("disconnect"); + static bool OneShotMessage = true; + if (OneShotMessage) + { + OneShotMessage = false; + PanicAlert("IPC CommandDisconnect: WiiMote emulation is out of sync.\n" + "This message will be shot one time only, because dolphin\n" + "executes the disconnect at all and some times you can play\n" + "anyway. It is strongly recommed to save and/or restart the" + "emulation."); + } } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkSupervisionTimeout(u8* _Input) diff --git a/Source/Plugins/Plugin_Wiimote_Test/Plugin_Wiimote_Test.vcproj b/Source/Plugins/Plugin_Wiimote_Test/Plugin_Wiimote_Test.vcproj index d806b8c20b..ca81032276 100644 --- a/Source/Plugins/Plugin_Wiimote_Test/Plugin_Wiimote_Test.vcproj +++ b/Source/Plugins/Plugin_Wiimote_Test/Plugin_Wiimote_Test.vcproj @@ -44,7 +44,7 @@ + + + + + + + + + + diff --git a/Source/Plugins/Plugin_Wiimote_Test/Src/main.cpp b/Source/Plugins/Plugin_Wiimote_Test/Src/main.cpp new file mode 100644 index 0000000000..16f158ae2e --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote_Test/Src/main.cpp @@ -0,0 +1,206 @@ +// 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/ + + +#if !defined(OSX64) +#include +#endif + +#include "Common.h" +#include "StringUtil.h" + +#include "pluginspecs_wiimote.h" + +#include "wiimote_emu.h" +#include "wiimote_real.h" + +SWiimoteInitialize g_WiimoteInitialize; +#define VERSION_STRING "0.1" + +bool g_UseRealWiiMote = false; + +HINSTANCE g_hInstance; + + + +class wxDLLApp : public wxApp +{ + bool OnInit() + { + return true; + } +}; +IMPLEMENT_APP_NO_MAIN(wxDLLApp) + +WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); + +#ifdef _WIN32 +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + { //use wxInitialize() if you don't want GUI instead of the following 12 lines + wxSetInstance((HINSTANCE)hinstDLL); + int argc = 0; + char **argv = NULL; + wxEntryStart(argc, argv); + if ( !wxTheApp || !wxTheApp->CallOnInit() ) + return FALSE; + } + break; + + case DLL_PROCESS_DETACH: + wxEntryCleanup(); //use wxUninitialize() if you don't want GUI + break; + default: + break; + } + + g_hInstance = hinstDLL; + return TRUE; +} +#endif +//****************************************************************************** +// Exports +//****************************************************************************** +extern "C" void GetDllInfo (PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_WIIMOTE; +#ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "Wiimote Test (DebugFast) " VERSION_STRING); +#else +#ifndef _DEBUG + sprintf(_PluginInfo->Name, "Wiimote Test " VERSION_STRING); +#else + sprintf(_PluginInfo->Name, "Wiimote Test (Debug) " VERSION_STRING); +#endif +#endif +} + + +extern "C" void DllAbout(HWND _hParent) +{ +#if !defined(OSX64) + wxAboutDialogInfo info; + info.SetName(_T("Wiimote test plugin")); + info.AddDeveloper(_T("masken (masken3@gmail.com)")); + info.SetDescription(_T("Wiimote test plugin")); + wxAboutBox(info); +#endif +} + +extern "C" void DllConfig(HWND _hParent) +{ +} + +extern "C" void Wiimote_Initialize(SWiimoteInitialize _WiimoteInitialize) +{ + g_WiimoteInitialize = _WiimoteInitialize; + + g_UseRealWiiMote = WiiMoteReal::Initialize() > 0; + + + WiiMoteEmu::Initialize(); +} + +extern "C" void Wiimote_DoState(void* ptr, int mode) +{ + WiiMoteReal::DoState(ptr, mode); + WiiMoteEmu::DoState(ptr, mode); +} + +extern "C" void Wiimote_Shutdown(void) +{ + WiiMoteReal::Shutdown(); + WiiMoteEmu::Shutdown(); +} + +extern "C" void Wiimote_InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) +{ + const u8* data = (const u8*)_pData; + + // dump raw data + { + LOG(WII_IPC_WIIMOTE, "Wiimote_Input"); + 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()); + } + + if (g_UseRealWiiMote) + WiiMoteReal::InterruptChannel(_channelID, _pData, _Size); + else + WiiMoteEmu::InterruptChannel(_channelID, _pData, _Size); + +} + +extern "C" void Wiimote_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; + 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()); + } + + if (g_UseRealWiiMote) + WiiMoteReal::ControlChannel(_channelID, _pData, _Size); + else + WiiMoteEmu::ControlChannel(_channelID, _pData, _Size); +} + +extern "C" void Wiimote_Update() +{ + if (g_UseRealWiiMote) + WiiMoteReal::Update(); + else + WiiMoteEmu::Update(); +} + +extern "C" unsigned int Wiimote_GetAttachedControllers() +{ + return 1; +} + + +void __Log(int log, const char *_fmt, ...) +{ + char Msg[512]; + va_list ap; + + va_start( ap, _fmt ); + vsprintf( Msg, _fmt, ap ); + va_end( ap ); + + g_WiimoteInitialize.pLog(Msg); +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_emu.cpp b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_emu.cpp new file mode 100644 index 0000000000..50f5b18c07 --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_emu.cpp @@ -0,0 +1,729 @@ +// 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/ + + +#include "pluginspecs_wiimote.h" + +#include +#include "common.h" +#include "wiimote_hid.h" + +extern SWiimoteInitialize g_WiimoteInitialize; +extern void __Log(int log, const char *format, ...); + +namespace WiiMoteEmu +{ + +//****************************************************************************** +// Definitions and variable declarations +//****************************************************************************** + +//libogc bounding box, in smoothed IR coordinates: 232,284 792,704 +//we'll use it to scale our mouse coordinates +#define LEFT 232 +#define TOP 284 +#define RIGHT 792 +#define BOTTOM 704 +#define SENSOR_BAR_RADIUS 200 + +// vars +#define WIIMOTE_EEPROM_SIZE (16*1024) +#define WIIMOTE_REG_SPEAKER_SIZE 10 +#define WIIMOTE_REG_EXT_SIZE 0x100 +#define WIIMOTE_REG_IR_SIZE 0x34 + +u8 g_Leds = 0x1; + +u8 g_Eeprom[WIIMOTE_EEPROM_SIZE]; + +u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE]; +u8 g_RegExt[WIIMOTE_REG_EXT_SIZE]; +u8 g_RegIr[WIIMOTE_REG_IR_SIZE]; + +u8 g_ReportingMode; +u16 g_ReportingChannel; + +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 +}; + +//****************************************************************************** +// Subroutine declarations +//****************************************************************************** + + +void HidOutputReport(u16 _channelID, wm_report* sr); + +void WmLeds(u16 _channelID, wm_leds* leds); +void WmReadData(u16 _channelID, wm_read_data* rd); +void WmWriteData(u16 _channelID, wm_write_data* wd); +void WmRequestStatus(u16 _channelID, wm_request_status* rs); +void WmDataReporting(u16 _channelID, wm_data_reporting* dr); + +void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size); +void SendReportCoreAccel(u16 _channelID); +void SendReportCoreAccelIr12(u16 _channelID); +void SendReportCore(u16 _channelID); +void SendReportCoreAccelIr10Ext(u16 _channelID); + +int WriteWmReport(u8* dst, u8 channel); +void WmSendAck(u16 _channelID, u8 _reportID); + +static u32 convert24bit(const u8* src) { + return (src[0] << 16) | (src[1] << 8) | src[2]; +} + +static u16 convert16bit(const u8* src) { + return (src[0] << 8) | src[1]; +} + +void GetMousePos(float& x, float& y) +{ +#ifdef _WIN32 + POINT point; + + GetCursorPos(&point); + ScreenToClient(g_WiimoteInitialize.hWnd, &point); + + RECT Rect; + GetClientRect(g_WiimoteInitialize.hWnd, &Rect); + + int width = Rect.right - Rect.left; + int height = Rect.bottom - Rect.top; + + x = point.x / (float)width; + y = point.y / (float)height; +#else + x = 0.5f; + y = 0.5f; +#endif +} + + +void CryptBuffer(u8* _buffer, u8 _size) +{ + for (int i=0; i<_size; i++) + { + _buffer[i] = ((_buffer[i] - 0x17) ^ 0x17) & 0xFF; + } +} + +void WriteCryped16(u8* _baseBlock, u16 _address, u16 _value) +{ + u16 cryptedValue = _value; + CryptBuffer((u8*)&cryptedValue, sizeof(u16)); + + *(u16*)(_baseBlock + _address) = cryptedValue; +} + +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; + + + + WriteCryped16(g_RegExt, 0xfe, 0x0000); + +// g_RegExt[0xfd] = 0x1e; +// g_RegExt[0xfc] = 0x9a; + +} + +void DoState(void* ptr, int mode) +{ + //TODO: implement +} + +void Shutdown(void) +{ +} + +void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) +{ + + const u8* data = (const u8*)_pData; + + // dump raw data + { + LOG(WII_IPC_WIIMOTE, "Wiimote_Input"); + std::string Temp; + for (u32 j=0; j<_Size; j++) + { + char Buffer[128]; + sprintf(Buffer, "%02x ", data[j]); + Temp.append(Buffer); + } + LOG(WII_IPC_WIIMOTE, " Data: %s", Temp.c_str()); + } + hid_packet* hidp = (hid_packet*) data; + + switch(hidp->type) + { + case HID_TYPE_DATA: + { + switch(hidp->param) + { + case HID_PARAM_OUTPUT: + { + wm_report* sr = (wm_report*)hidp->data; + WmSendAck(_channelID, sr->channel); + HidOutputReport(_channelID, sr); + } + 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; + } +} + +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; + for (u32 j=0; j<_Size; j++) + { + char Buffer[128]; + sprintf(Buffer, "%02x ", data[j]); + Temp.append(Buffer); + } + LOG(WII_IPC_WIIMOTE, " Data: %s", Temp.c_str()); + } + + hid_packet* hidp = (hid_packet*) data; + switch(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; + } + +} + +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_IR10_EXT6: SendReportCoreAccelIr10Ext(g_ReportingChannel);break; + } + // g_ReportingMode = 0; +} + +//****************************************************************************** +// Subroutines +//****************************************************************************** +void HidOutputReport(u16 _channelID, wm_report* sr) { + LOG(WII_IPC_WIIMOTE, " HidOutputReport(0x%02x)", sr->channel); + + switch(sr->channel) + { + case 0x10: + LOG(WII_IPC_WIIMOTE, "HidOutputReport: unknown sr->channel 0x10"); + break; + case WM_LEDS: + WmLeds(_channelID, (wm_leds*)sr->data); + break; + case WM_READ_DATA: + WmReadData(_channelID, (wm_read_data*)sr->data); + break; + case WM_REQUEST_STATUS: + WmRequestStatus(_channelID, (wm_request_status*)sr->data); + break; + case WM_IR_PIXEL_CLOCK: + case WM_IR_LOGIC: + LOG(WII_IPC_WIIMOTE, " IR Enable 0x%02x 0x%02x", sr->channel, sr->data[0]); + break; + case WM_WRITE_DATA: + WmWriteData(_channelID, (wm_write_data*)sr->data); + break; + case WM_DATA_REPORTING: + WmDataReporting(_channelID, (wm_data_reporting*)sr->data); + break; + + case WM_SPEAKER_ENABLE: + LOG(WII_IPC_WIIMOTE, " WM Speaker Enable 0x%02x 0x%02x", sr->channel, sr->data[0]); + break; + + case WM_SPEAKER_MUTE: + LOG(WII_IPC_WIIMOTE, " WM Mute Enable 0x%02x 0x%02x", sr->channel, sr->data[0]); + break; + + default: + PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->channel); + return; + } +} + +void WmLeds(u16 _channelID, wm_leds* leds) { + 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; +} +void WmSendAck(u16 _channelID, u8 _reportID) +{ + u8 DataFrame[1024]; + + u32 Offset = 0; + + // header + hid_packet* pHidHeader = (hid_packet*)(DataFrame + Offset); + pHidHeader->type = HID_TYPE_DATA; + pHidHeader->param = HID_PARAM_INPUT; + Offset += sizeof(hid_packet); + + wm_acknowledge* pData = (wm_acknowledge*)(DataFrame + Offset); + pData->Channel = WM_WRITE_DATA_REPLY; + pData->unk0 = 0; + pData->unk1 = 0; + pData->reportID = _reportID; + pData->errorID = 0; + Offset += sizeof(wm_acknowledge); + + + LOG(WII_IPC_WIIMOTE, " WMSendAck()"); + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + + +void WmDataReporting(u16 _channelID, wm_data_reporting* dr) +{ + LOG(WII_IPC_WIIMOTE, " Set Data reporting mode"); + LOG(WII_IPC_WIIMOTE, " Rumble: %x", dr->rumble); + 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, " Rumble: %x", dr->rumble); + LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode); + + g_ReportingMode = dr->mode; + g_ReportingChannel = _channelID; + switch(dr->mode) { //see Wiimote_Update() + case WM_REPORT_CORE: + case WM_REPORT_CORE_ACCEL: + case WM_REPORT_CORE_ACCEL_IR12: + case WM_REPORT_CORE_ACCEL_IR10_EXT6: + break; + default: + PanicAlert("Wiimote: Unknown reporting mode 0x%x", dr->mode); + } + + // WmSendAck(_channelID, WM_DATA_REPORTING); +} + + +void FillReportInfo(wm_core& _core) +{ + memset(&_core, 0x00, sizeof(wm_core)); + +#ifdef _WIN32 + _core.a = GetAsyncKeyState(VK_LBUTTON) ? 1 : 0; + _core.b = GetAsyncKeyState(VK_RBUTTON) ? 1 : 0; +#else + // TODO: fill in +#endif +} + +void FillReportAcc(wm_accel& _acc) +{ + _acc.x = 0x00; + _acc.y = 0x00; + _acc.z = 0x00; +} + +void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1) +{ + memset(&_ir0, 0xFF, sizeof(wm_ir_extended)); + memset(&_ir1, 0xFF, sizeof(wm_ir_extended)); + + float MouseX, MouseY; + GetMousePos(MouseX, MouseY); + + int y0 = TOP + (MouseY * (BOTTOM - TOP)); + int y1 = TOP + (MouseY * (BOTTOM - TOP)); + + int x0 = LEFT + (MouseX * (RIGHT - LEFT)) - SENSOR_BAR_RADIUS; + int x1 = LEFT + (MouseX * (RIGHT - LEFT)) + SENSOR_BAR_RADIUS; + + x0 = 1023 - x0; + _ir0.x = x0 & 0xFF; + _ir0.y = y0 & 0xFF; + _ir0.size = 10; + _ir0.xHi = x0 >> 8; + _ir0.yHi = y0 >> 8; + + x1 = 1023 - x1; + _ir1.x = x1; + _ir1.y = y1 & 0xFF; + _ir1.size = 10; + _ir1.xHi = x1 >> 8; + _ir1.yHi = y1 >> 8; +} + +void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1) +{ + memset(&_ir0, 0xFF, sizeof(wm_ir_basic)); + memset(&_ir1, 0xFF, sizeof(wm_ir_basic)); + + float MouseX, MouseY; + GetMousePos(MouseX, MouseY); + + int y1 = TOP + (MouseY * (BOTTOM - TOP)); + int y2 = TOP + (MouseY * (BOTTOM - TOP)); + + int x1 = LEFT + (MouseX * (RIGHT - LEFT)) - SENSOR_BAR_RADIUS; + int x2 = LEFT + (MouseX * (RIGHT - LEFT)) + SENSOR_BAR_RADIUS; + + x1 = 1023 - x1; + _ir0.x1 = x1 & 0xFF; + _ir0.y1 = y1 & 0xFF; + _ir0.x1High = (x1 >> 8) & 0x3; + _ir0.y1High = (y1 >> 8) & 0x3; + + x2 = 1023 - x2; + _ir1.x2 = x2 & 0xFF; + _ir1.y2 = y2 & 0xFF; + _ir1.x2High = (x2 >> 8) & 0x3; + _ir1.y2High = (y2 >> 8) & 0x3; +} + + +void SendReportCore(u16 _channelID) +{ + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE); + + wm_report_core* pReport = (wm_report_core*)(DataFrame + Offset); + Offset += sizeof(wm_report_core); + memset(pReport, 0, sizeof(wm_report_core)); + + FillReportInfo(pReport->c); + + LOG(WII_IPC_WIIMOTE, " SendReportCore()"); + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + + +void SendReportCoreAccelIr12(u16 _channelID) { + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_IR12); + + wm_report_core_accel_ir12* pReport = (wm_report_core_accel_ir12*)(DataFrame + Offset); + Offset += sizeof(wm_report_core_accel_ir12); + memset(pReport, 0, sizeof(wm_report_core_accel_ir12)); + + FillReportInfo(pReport->c); + FillReportAcc(pReport->a); + FillReportIR(pReport->ir[0], pReport->ir[1]); + + LOG(WII_IPC_WIIMOTE, " SendReportCoreAccelIr12()"); + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + +void SendReportCoreAccelIr10Ext(u16 _channelID) +{ + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_IR10_EXT6); + + wm_report_core_accel_ir10_ext6* pReport = (wm_report_core_accel_ir10_ext6*)(DataFrame + Offset); + Offset += sizeof(wm_report_core_accel_ir10_ext6); + memset(pReport, 0, sizeof(wm_report_core_accel_ir10_ext6)); + + FillReportInfo(pReport->c); + FillReportAcc(pReport->a); + FillReportIRBasic(pReport->ir[0], pReport->ir[1]); + + LOG(WII_IPC_WIIMOTE, " SendReportCoreAccelIr10Ext()"); + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + + +void SendReportCoreAccel(u16 _channelID) +{ + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL); + + wm_report_core_accel* pReport = (wm_report_core_accel*)(DataFrame + Offset); + Offset += sizeof(wm_report_core_accel); + memset(pReport, 0, sizeof(wm_report_core_accel)); + + FillReportInfo(pReport->c); + FillReportAcc(pReport->a); + + LOG(WII_IPC_WIIMOTE, " SendReportCoreAccel()"); + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + +void WmReadData(u16 _channelID, wm_read_data* rd) +{ + u32 address = convert24bit(rd->address); + u16 size = convert16bit(rd->size); + 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); + + if(rd->space == 0) + { + if (address + size > WIIMOTE_EEPROM_SIZE) + { + PanicAlert("WmReadData: address + size out of bounds!"); + return; + } + SendReadDataReply(_channelID, g_Eeprom+address, address, (u8)size); + } + else if(rd->space == WM_SPACE_REGS1 || rd->space == WM_SPACE_REGS2) + { + u8* block; + u32 blockSize; + switch((address >> 16) & 0xFE) + { +/* case 0xA2: + block = g_RegSpeaker; + blockSize = WIIMOTE_REG_SPEAKER_SIZE; + break;*/ + case 0xA4: + block = g_RegExt; + blockSize = WIIMOTE_REG_EXT_SIZE; + PanicAlert("fsfsd"); + break; +/* case 0xB0: + block = g_RegIr; + blockSize = WIIMOTE_REG_IR_SIZE; + break;*/ + default: + PanicAlert("WmWriteData: bad register block!"); + return; + } + address &= 0xFFFF; + if(address + size > blockSize) { + PanicAlert("WmReadData: address + size out of bounds!"); + return; + } + + SendReadDataReply(_channelID, block+address, address, (u8)size); + } + else + { + PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x!", size, rd->space); + } +} + +void WmWriteData(u16 _channelID, wm_write_data* wd) +{ + 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); + + 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); + + // WmSendAck(_channelID, WM_WRITE_DATA); + } + 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; + break; + case 0xA4: + block = g_RegExt; + blockSize = WIIMOTE_REG_EXT_SIZE; + break; + case 0xB0: + block = g_RegIr; + blockSize = WIIMOTE_REG_IR_SIZE; + break; + default: + PanicAlert("WmWriteData: bad register block!"); + return; + } + address &= 0xFFFF; + if(address + wd->size > blockSize) { + PanicAlert("WmWriteData: address + size out of bounds!"); + return; + } + memcpy(wd->data, block + address, wd->size); + + } else { + PanicAlert("WmWriteData: unimplemented parameters!"); + } + + // just added for home brew.... hmmmm + WmSendAck(_channelID, WM_WRITE_DATA); +} + +int WriteWmReport(u8* dst, u8 channel) { + u32 Offset = 0; + hid_packet* pHidHeader = (hid_packet*)(dst + Offset); + Offset += sizeof(hid_packet); + pHidHeader->type = HID_TYPE_DATA; + pHidHeader->param = HID_PARAM_INPUT; + + wm_report* pReport = (wm_report*)(dst + Offset); + Offset += sizeof(wm_report); + pReport->channel = channel; + return Offset; +} + +void WmRequestStatus(u16 _channelID, wm_request_status* rs) { + LOG(WII_IPC_WIIMOTE, " Request Status"); + LOG(WII_IPC_WIIMOTE, " Rumble: %x", rs->rumble); + + //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)); + pStatus->leds = g_Leds; + pStatus->ir = 1; + pStatus->battery = 0x4F; //arbitrary number + pStatus->extension = 0; + + LOG(WII_IPC_WIIMOTE, " SendStatusReport()"); + LOG(WII_IPC_WIIMOTE, " Flags: 0x%02x", pStatus->padding1[2]); + LOG(WII_IPC_WIIMOTE, " Battery: %d", pStatus->battery); + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + +void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size) +{ + 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); + memcpy(pReply->data + dataOffset, _Base, copySize); + if(copySize < 16) + { + 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); + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + + _Size -= copySize; + } + + if (_Size != 0) + { + PanicAlert("WiiMote-Plugin: SendReadDataReply() failed"); + } +} + + +} // end of namespace \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_emu.h b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_emu.h new file mode 100644 index 0000000000..9263a74b8e --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_emu.h @@ -0,0 +1,37 @@ +// 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/ + +#ifndef WIIMOTE_EMU_H +#define WIIMOTE_EMU_H + +#include "wiimote_hid.h" + +namespace WiiMoteEmu +{ + +void Initialize(); +void DoState(void* ptr, int mode); +void Shutdown(void); +void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size); +void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) ; +void Update(); + +void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1); + +}; + +#endif \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_hid.h b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_hid.h index 3732fe5cc5..a4c7afee85 100644 --- a/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_hid.h +++ b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_hid.h @@ -1,3 +1,20 @@ +// 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/ + #ifndef WIIMOTE_HID_H #define WIIMOTE_HID_H diff --git a/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_real.cpp b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_real.cpp new file mode 100644 index 0000000000..8467b8b753 --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_real.cpp @@ -0,0 +1,271 @@ +// 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/ + +#include "pluginspecs_wiimote.h" + +#include + +#include "common.h" +#include "thread.h" + +#include "wiimote_hid.h" +#include "wiimote_emu.h" + + +#define WIIUSE_INTERNAL_H_INCLUDED +#define WIIUSE_COMPILE_LIB + +#include "wiiuse_012/wiiuse.h" +#include "wiiuse_012/io.h" + + +extern SWiimoteInitialize g_WiimoteInitialize; +extern void __Log(int log, const char *format, ...); + +namespace WiiMoteReal +{ +#define MAX_WIIMOTES 1 + + //****************************************************************************** + // Variable declarations + //****************************************************************************** + + wiimote_t** m_WiiMotesFromWiiUse = NULL; + Common::Thread* g_pReadThread = NULL; + Common::CriticalSection* g_pCriticalSection = NULL; + bool g_Shutdown = false; + + class CWiiMote + { + public: + + CWiiMote(u8 _WiimoteNumber, wiimote_t* _pWiimote) + : m_WiimoteNumber(_WiimoteNumber) + , m_pWiiMote(_pWiimote) + , m_LastReportValid(false) + , m_channelID(0) + { + wiiuse_set_leds(m_pWiiMote, WIIMOTE_LED_4); + +#ifdef _WIN32 + // F|RES: i dunno if we really need this + CancelIo(m_pWiiMote->dev_handle); +#endif + } + + virtual ~CWiiMote() + {}; + + // send raw HID data from the core to wiimote + void SendData(u16 _channelID, const u8* _pData, u32 _Size) + { + m_channelID = _channelID; + + g_pCriticalSection->Enter(); + { + SEvent WriteEvent; + memcpy(WriteEvent.m_PayLoad, _pData+1, _Size-1); + m_EventWriteQueue.push(WriteEvent); + } + g_pCriticalSection->Leave(); + } + + // read data from wiimote (but don't send it to the core, just filter and queue) + void ReadData() + { + g_pCriticalSection->Enter(); + + if (!m_EventWriteQueue.empty()) + { + SEvent& rEvent = m_EventWriteQueue.front(); + wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD); + m_EventWriteQueue.pop(); + } + + g_pCriticalSection->Leave(); + + memset(m_pWiiMote->event_buf, 0, MAX_PAYLOAD); + if (wiiuse_io_read(m_pWiiMote)) + { + byte* pBuffer = m_pWiiMote->event_buf; + + // check if we have a channel (connection) if so save the data... + if (m_channelID > 0) + { + g_pCriticalSection->Enter(); + + // filter out reports + if (pBuffer[0] >= 0x30) + { + memcpy(m_LastReport.m_PayLoad, pBuffer, MAX_PAYLOAD); + m_LastReportValid = true; + } + else + { + SEvent ImportantEvent; + memcpy(ImportantEvent.m_PayLoad, pBuffer, MAX_PAYLOAD); + m_EventReadQueue.push(ImportantEvent); + } + + g_pCriticalSection->Leave(); + } + } + }; + + // send queued data to the core + void Update() + { + g_pCriticalSection->Enter(); + + if (m_EventReadQueue.empty()) + { + if (m_LastReportValid) + SendEvent(m_LastReport); + } + else + { + SendEvent(m_EventReadQueue.front()); + m_EventReadQueue.pop(); + } + + g_pCriticalSection->Leave(); + }; + + private: + + struct SEvent + { + SEvent() + { + memset(m_PayLoad, 0, MAX_PAYLOAD); + } + byte m_PayLoad[MAX_PAYLOAD]; + }; + typedef std::queue CEventQueue; + + u8 m_WiimoteNumber; // just for debugging + u16 m_channelID; + wiimote_t* m_pWiiMote; + + CEventQueue m_EventReadQueue; + CEventQueue m_EventWriteQueue; + bool m_LastReportValid; + SEvent m_LastReport; + + void SendEvent(SEvent& _rEvent) + { + // we don't have an answer channel + if (m_channelID == 0) + return; + + // check event buffer; + u8 Buffer[1024]; + u32 Offset = 0; + hid_packet* pHidHeader = (hid_packet*)(Buffer + Offset); + Offset += sizeof(hid_packet); + pHidHeader->type = HID_TYPE_DATA; + pHidHeader->param = HID_PARAM_INPUT; + + memcpy(&Buffer[Offset], _rEvent.m_PayLoad, MAX_PAYLOAD); + Offset += MAX_PAYLOAD; + + g_WiimoteInitialize.pWiimoteInput(m_channelID, Buffer, Offset); + } + }; + + int g_NumberOfWiiMotes; + CWiiMote* g_WiiMotes[MAX_WIIMOTES]; + + DWORD WINAPI ReadWiimote_ThreadFunc(void* arg); + + //****************************************************************************** + // Function Definitions + //****************************************************************************** + + int Initialize() + { + memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES); + m_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES); + g_NumberOfWiiMotes= wiiuse_find(m_WiiMotesFromWiiUse, MAX_WIIMOTES, 5); + + for (int i=0; iWaitForDeath(); + + for (int i=0; iSendData(_channelID, (const u8*)_pData, _Size); + } + + void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) + { + g_WiiMotes[0]->SendData(_channelID, (const u8*)_pData, _Size); + } + + void Update() + { + for (int i=0; iUpdate(); + } + } + + DWORD WINAPI ReadWiimote_ThreadFunc(void* arg) + { + while (!g_Shutdown) + { + for (int i=0; iReadData(); + } + } + return 0; + } + +}; // end of namespace + diff --git a/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_real.h b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_real.h new file mode 100644 index 0000000000..14edd430d3 --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote_Test/Src/wiimote_real.h @@ -0,0 +1,34 @@ +// 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/ + + +#ifndef WIIMOTE_REAL_H +#define WIIMOTE_REAL_H + +namespace WiiMoteReal +{ + +int Initialize(); +void DoState(void* ptr, int mode); +void Shutdown(void); +void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size); +void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) ; +void Update(); + +}; + +#endif \ No newline at end of file