diff --git a/Source/Core/Core/Src/HW/HW.cpp b/Source/Core/Core/Src/HW/HW.cpp index 8cfd88e20c..6a05409f76 100644 --- a/Source/Core/Core/Src/HW/HW.cpp +++ b/Source/Core/Core/Src/HW/HW.cpp @@ -62,8 +62,8 @@ namespace HW SystemTimers::Init(); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) { - WII_IPC_HLE_Interface::Init(); WII_IPCInterface::Init(); + WII_IPC_HLE_Interface::Init(); } } @@ -80,8 +80,8 @@ namespace HW if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) { - WII_IPC_HLE_Interface::Shutdown(); WII_IPCInterface::Shutdown(); + WII_IPC_HLE_Interface::Shutdown(); } State_Shutdown(); @@ -100,12 +100,17 @@ namespace HW GPFifo::DoState(p); ExpansionInterface::DoState(p); AudioInterface::DoState(p); - WII_IPCInterface::DoState(p); + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) + { + WII_IPCInterface::DoState(p); + WII_IPC_HLE_Interface::DoState(p); + } } // Restart Wiimote void InitWiimote() { WII_IPCInterface::Init(); + WII_IPC_HLE_Interface::Init(); } } diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp index b499f71feb..dbb58cdc7e 100644 --- a/Source/Core/Core/Src/HW/SystemTimers.cpp +++ b/Source/Core/Core/Src/HW/SystemTimers.cpp @@ -102,6 +102,7 @@ broadway: 729 // So, ratio is 1 / (1/4 * 1/3 = 1/12) = 12. // note: ZWW is ok and faster with TIMER_RATIO=8 though. // !!! POSSIBLE STABLE PERF BOOST HACK THERE !!! + enum { TIMER_RATIO = 12 @@ -174,15 +175,14 @@ void AudioFifoCallback(u64 userdata, int cyclesLate) void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate) { - WII_IPC_HLE_Interface::UpdateDevices(); - CoreTiming::ScheduleEvent(IPC_HLE_PERIOD-cyclesLate, et_IPC_HLE); + if (Core::GetStartupParameter().bWii) + WII_IPC_HLE_Interface::Update(); + + CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine()-cyclesLate, et_IPC_HLE); } void VICallback(u64 userdata, int cyclesLate) { - if (Core::GetStartupParameter().bWii) - WII_IPC_HLE_Interface::Update(); - VideoInterface::Update(); CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine() - cyclesLate, et_VI); } @@ -252,6 +252,9 @@ void Init() if (!UsingDSPLLE) DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f); + // AyuanX: TO BE TWEAKED + // If this update frequency is too high, WiiMote could easily jam the IPC Bus + // but if it is too low, sometimes IPC gets overflown by CPU :~~~( IPC_HLE_PERIOD = (int)(GetTicksPerSecond() * 0.003f); } else diff --git a/Source/Core/Core/Src/HW/WII_IPC.cpp b/Source/Core/Core/Src/HW/WII_IPC.cpp index fda27297db..424487fdf2 100644 --- a/Source/Core/Core/Src/HW/WII_IPC.cpp +++ b/Source/Core/Core/Src/HW/WII_IPC.cpp @@ -85,36 +85,46 @@ union UIPC_Config }; // STATE_TO_SAVE -UIPC_Status g_IPC_Status; -UIPC_Config g_IPC_Config; -UIPC_Control g_IPC_Control; - -u32 g_Address = 0; -u32 g_Reply = 0; -u32 g_SensorBarPower = 0; +bool g_ExeCmd = false; +u32 g_Address = NULL; +u32 g_Reply = NULL; +u32 g_ReplyHead = NULL; +u32 g_ReplyTail = NULL; +u32 g_SensorBarPower = NULL; +UIPC_Status g_IPC_Status(NULL); +UIPC_Config g_IPC_Config(NULL); +UIPC_Control g_IPC_Control(NULL); void DoState(PointerWrap &p) { + p.Do(g_ExeCmd); + p.Do(g_Address); + p.Do(g_Reply); + p.Do(g_ReplyHead); + p.Do(g_ReplyTail); + p.Do(g_SensorBarPower); p.Do(g_IPC_Status); p.Do(g_IPC_Config); p.Do(g_IPC_Control); - p.Do(g_Address); - p.Do(g_Reply); - p.Do(g_SensorBarPower); } -void UpdateInterrupts(); - // Init void Init() { - g_Address = 0; - g_Reply = 0; - g_SensorBarPower = 0; + g_ExeCmd = false; + g_Address = NULL; + g_Reply = NULL; + g_ReplyHead = NULL; + g_ReplyTail = NULL; + g_SensorBarPower = NULL; + g_IPC_Status = UIPC_Status(NULL); + g_IPC_Config = UIPC_Config(NULL); + g_IPC_Control = UIPC_Control(NULL); +} - g_IPC_Status = UIPC_Status(); - g_IPC_Config = UIPC_Config(); - g_IPC_Control = UIPC_Control(); +void Reset() +{ + Init(); } void Shutdown() @@ -127,16 +137,16 @@ void Read32(u32& _rReturnValue, const u32 _Address) { case IPC_CONTROL_REGISTER: _rReturnValue = g_IPC_Control.Hex; - INFO_LOG(WII_IPC, "IOP: Read32 from IPC_CONTROL_REGISTER(0x04) = 0x%08x", _rReturnValue); + INFO_LOG(WII_IPC, "IOP: Read32, IPC_CONTROL_REGISTER(0x04) = 0x%08x [R:%i A:%i E:%i]", + _rReturnValue, (_rReturnValue>>2)&1, (_rReturnValue>>1)&1, _rReturnValue&1); // if ((REASON_REG & 0x14) == 0x14) CALL IPCReplayHanlder // if ((REASON_REG & 0x22) != 0x22) Jumps to the end - break; case IPC_REPLY_REGISTER: // looks a little bit like a callback function _rReturnValue = g_Reply; - INFO_LOG(WII_IPC, "IOP: Write32 to IPC_REPLAY_REGISTER(0x08) = 0x%08x ", _rReturnValue); + INFO_LOG(WII_IPC, "IOP: Read32, IPC_REPLY_REGISTER(0x08) = 0x%08x ", _rReturnValue); break; case IPC_SENSOR_BAR_POWER_REGISTER: @@ -146,7 +156,7 @@ void Read32(u32& _rReturnValue, const u32 _Address) default: _dbg_assert_msg_(WII_IPC, 0, "IOP: Read32 from 0x%08x", _Address); break; - } + } } void Write32(const u32 _Value, const u32 _Address) @@ -157,30 +167,36 @@ void Write32(const u32 _Value, const u32 _Address) case IPC_COMMAND_REGISTER: // __ios_Ipc2 ... a value from __responses is loaded { g_Address = _Value; - INFO_LOG(WII_IPC, "IOP: Write32 to IPC_ADDRESS_REGISTER(0x00) = 0x%08x", g_Address); + INFO_LOG(WII_IPC, "IOP: Write32, IPC_ADDRESS_REGISTER(0x00) = 0x%08x", g_Address); } break; case IPC_CONTROL_REGISTER: { - INFO_LOG(WII_IPC, "IOP: Write32 to IPC_CONTROL_REGISTER(0x04) = 0x%08x (old: 0x%08x)", _Value, g_IPC_Control.Hex); + INFO_LOG(WII_IPC, "IOP: Write32, IPC_CONTROL_REGISTER(0x04) = 0x%08x [R:%i A:%i E:%i] (old: 0x%08x) ", + _Value, (_Value>>2)&1, (_Value>>1)&1, _Value&1, g_IPC_Control.Hex); UIPC_Control TempControl(_Value); _dbg_assert_msg_(WII_IPC, TempControl.pad == 0, "IOP: Write to UIPC_Control.pad", _Address); - if (TempControl.AckReady) { g_IPC_Control.AckReady = 0; } if (TempControl.ReplyReady) { g_IPC_Control.ReplyReady = 0; } - if (TempControl.Relaunch) { g_IPC_Control.Relaunch = 0; } - + + // Ayuanx: What is this Relaunch bit used for ??? + // I have done considerable amount of tests that show no use of it at all + // So I'm commenting this out + // + //if (TempControl.Relaunch) { g_IPC_Control.Relaunch = 0; } + + g_IPC_Control.Relaunch = TempControl.Relaunch; g_IPC_Control.unk5 = TempControl.unk5; g_IPC_Control.unk6 = TempControl.unk6; g_IPC_Control.pad = TempControl.pad; if (TempControl.ExecuteCmd) { - WII_IPC_HLE_Interface::AckCommand(g_Address); - } + g_ExeCmd = true; + } } break; @@ -189,21 +205,22 @@ void Write32(const u32 _Value, const u32 _Address) UIPC_Status NewStatus(_Value); if (NewStatus.INTERRUPT) g_IPC_Status.INTERRUPT = 0; // clear interrupt - INFO_LOG(WII_IPC, "IOP: Write32 to IPC_STATUS_REGISTER(0x30) = 0x%08x", _Value); + INFO_LOG(WII_IPC, "IOP: Write32, IPC_STATUS_REGISTER(0x30) = 0x%08x", _Value); } break; case IPC_CONFIG_REGISTER: // __OSInterruptInit (0x40000000) { - INFO_LOG(WII_IPC, "IOP: Write32 to IPC_CONFIG_REGISTER(0x33) = 0x%08x", _Value); + INFO_LOG(WII_IPC, "IOP: Write32, IPC_CONFIG_REGISTER(0x33) = 0x%08x", _Value); + g_IPC_Config.Hex = _Value; - - - if (_Value&0x40000000) - { - WII_IPC_HLE_Interface::Reset(); - } - + + if (_Value&0x40000000) + { + INFO_LOG(WII_IPC, "Reset triggered, Resetting ..."); + Reset(); + WII_IPC_HLE_Interface::Reset(); + } } break; @@ -217,11 +234,58 @@ void Write32(const u32 _Value, const u32 _Address) } break; } - // update the interrupts UpdateInterrupts(); } +u32 GetAddress() +{ + return ((g_ExeCmd) ? g_Address : NULL); +} + +void GenerateAck() +{ + g_ExeCmd = false; + g_IPC_Control.AckReady = 1; + UpdateInterrupts(); +} + +void GenerateReply(u32 _Address) +{ + g_Reply = _Address; + g_IPC_Control.ReplyReady = 1; + UpdateInterrupts(); +} + +void EnqReply(u32 _Address) +{ + // AyuanX: Replies are stored in a FIFO (depth 2), like ping-pong, and 2 is fairly enough + // Simple structure of fixed length will do good for DoState + // + if (g_ReplyHead == NULL) + { + g_ReplyHead = g_ReplyTail; + g_ReplyTail = _Address; + } + else + { + ERROR_LOG(WII_IPC, "Reply FIFO is full, something must be wrong!"); + PanicAlert("WII_IPC: Reply FIFO is full, something must be wrong!"); + } +} + +u32 DeqReply() +{ + u32 _Address = (g_ReplyHead) ? g_ReplyHead : g_ReplyTail; + + if (g_ReplyHead) + g_ReplyHead = NULL; + else + g_ReplyTail = NULL; + + return _Address; +} + void UpdateInterrupts() { if ((g_IPC_Control.AckReady == 1) || @@ -246,22 +310,6 @@ bool IsReady() return ((g_IPC_Control.ReplyReady == 0) && (g_IPC_Control.AckReady == 0) && (g_IPC_Status.INTERRUPT == 0)); } -void GenerateAck(u32 _AnswerAddress) -{ - g_Reply = _AnswerAddress; - g_IPC_Control.AckReady = 1; - - UpdateInterrupts(); -} - -void GenerateReply(u32 _AnswerAddress) -{ - g_Reply = _AnswerAddress; - g_IPC_Control.ReplyReady = 1; - - UpdateInterrupts(); -} - } // end of namespace IPC diff --git a/Source/Core/Core/Src/HW/WII_IPC.h b/Source/Core/Core/Src/HW/WII_IPC.h index 3ca4b012df..5b4947fa96 100644 --- a/Source/Core/Core/Src/HW/WII_IPC.h +++ b/Source/Core/Core/Src/HW/WII_IPC.h @@ -24,18 +24,23 @@ namespace WII_IPCInterface { void Init(); +void Reset(); void Shutdown(); void DoState(PointerWrap &p); -void Update(); -bool IsReady(); -void GenerateReply(u32 _AnswerAddress); -void GenerateAck(u32 _AnswerAddress); - void Read32(u32& _rReturnValue, const u32 _Address); - void Write32(const u32 _Value, const u32 _Address); +u32 GetAddress(); +void GenerateAck(); +void GenerateReply(u32 _Address); +void InsertReply(u32 _Address); +void EnqReply(u32 _Address); +u32 DeqReply(); + +void UpdateInterrupts(); +bool IsReady(); + } // end of namespace AudioInterface #endif 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 6d45e9a8c3..91e111f138 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -66,6 +66,7 @@ #include "../Debugger/Debugger_SymbolMap.h" #include "../PowerPC/PowerPC.h" + namespace WII_IPC_HLE_Interface { @@ -74,11 +75,6 @@ TDeviceMap g_DeviceMap; // STATE_TO_SAVE u32 g_LastDeviceID = 0x13370000; -std::list g_Ack; -u32 g_AckNumber = 0; -std::queue > g_ReplyQueue; -void ExecuteCommand(u32 _Address); - std::string g_DefaultContentFile; // General IPC functions @@ -89,27 +85,22 @@ void Init() void Reset() { + // AyuanX: We really should save this to state or build the map and devices statically + // Mem dynamic allocation is too risky when doing state save/load TDeviceMap::const_iterator itr = g_DeviceMap.begin(); while (itr != g_DeviceMap.end()) { - delete itr->second; - ++itr; + if (itr->second) + delete itr->second; + ++itr; } g_DeviceMap.clear(); - - while (!g_ReplyQueue.empty()) - { - g_ReplyQueue.pop(); - } - - g_Ack.clear(); } void Shutdown() { Reset(); g_LastDeviceID = 0x13370000; - g_AckNumber = 0; g_DefaultContentFile.clear(); } @@ -237,31 +228,7 @@ IWII_IPC_HLE_Device* CreateDevice(u32 _DeviceID, const std::string& _rDeviceName debugging I also noticed that the Ioctl arguments are stored temporarily in 0x933e.... with the same .... as in the _CommandAddress. */ // ---------------- -bool AckCommand(u32 _Address) -{ -#if MAX_LOG_LEVEL >= DEBUG_LEVEL - Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG); -#endif - INFO_LOG(WII_IPC_HLE, "AckCommand: 0%08x (num: %i) PC=0x%08x", _Address, g_AckNumber, PC); - std::list::iterator itr = g_Ack.begin(); - while (itr != g_Ack.end()) - { - if (*itr == _Address) - { - ERROR_LOG(WII_IPC_HLE, "execute a command two times"); - PanicAlert("execute a command two times"); - return false; - } - - itr++; - } - - g_Ack.push_back(_Address); - g_AckNumber++; - - return true; -} // Let the game read the setting.txt file void CopySettingsFile(std::string DeviceName) @@ -289,12 +256,30 @@ void CopySettingsFile(std::string DeviceName) } } +void DoState(PointerWrap &p) +{ + p.Do(g_LastDeviceID); + //p.Do(g_DefaultContentFile); + + // AyuanX: I think maybe we really should create devices statically at initilization + IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(GetDeviceIDByName(std::string("/dev/usb/oh1/57e/305"))); + if (pDevice) + pDevice->DoState(p); + else + PanicAlert("WII_IPC_HLE: Save/Load State failed, /dev/usb/oh1/57e/305 doesn't exist!"); +} + void ExecuteCommand(u32 _Address) { - bool GenerateReply = false; + bool CmdSuccess = false; u32 ClosedDeviceID = 0; ECommandType Command = static_cast(Memory::Read_U32(_Address)); + u32 DeviceID = Memory::Read_U32(_Address + 8); + IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID); + + INFO_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) ", _Address, Command, DeviceID); + switch (Command) { case COMMAND_OPEN_DEVICE: @@ -308,7 +293,7 @@ void ExecuteCommand(u32 _Address) if(DeviceName.find("setting.txt") != std::string::npos) CopySettingsFile(DeviceName); u32 Mode = Memory::Read_U32(_Address + 0x10); - u32 DeviceID = GetDeviceIDByName(DeviceName); + DeviceID = GetDeviceIDByName(DeviceName); // check if a device with this name has been created already if (DeviceID == 0) @@ -317,16 +302,16 @@ void ExecuteCommand(u32 _Address) // alternatively we could pre create all devices and put them in a directory tree structure // then this would just return a pointer to the wanted device. u32 CurrentDeviceID = g_LastDeviceID; - IWII_IPC_HLE_Device* pDevice = CreateDevice(CurrentDeviceID, DeviceName); + pDevice = CreateDevice(CurrentDeviceID, DeviceName); g_DeviceMap[CurrentDeviceID] = pDevice; g_LastDeviceID++; - GenerateReply = pDevice->Open(_Address, Mode); + CmdSuccess = pDevice->Open(_Address, Mode); if(pDevice->GetDeviceName().find("/dev/") == std::string::npos || pDevice->GetDeviceName().c_str() == std::string("/dev/fs")) { - INFO_LOG(WII_IPC_FILEIO, "IOP: Open (Device=%s, DeviceID=%08x, Mode=%i, GenerateReply=%i)", - pDevice->GetDeviceName().c_str(), CurrentDeviceID, Mode, (int)GenerateReply); + INFO_LOG(WII_IPC_FILEIO, "IOP: Open (Device=%s, DeviceID=%08x, Mode=%i, CmdSuccess=%i)", + pDevice->GetDeviceName().c_str(), CurrentDeviceID, Mode, (int)CmdSuccess); } else { @@ -337,13 +322,13 @@ void ExecuteCommand(u32 _Address) else { // The device has already been opened and was not closed, reuse the same DeviceID. + pDevice = AccessDeviceByID(DeviceID); - IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID); - // If we return -6 here after a Open > Failed > CREATE_FILE > ReOpen call + // If we return -6 here after a Open > Failed > CREATE_FILE > ReOpen call // sequence Mario Galaxy and Mario Kart Wii will not start writing to the file, // it will just (seemingly) wait for one or two seconds and then give an error // message. So I'm trying to return the DeviceID instead to make it write to the file. - // (Which was most likely the reason it created the file in the first place.) */ + // (Which was most likely the reason it created the file in the first place.) // F|RES: prolly the re-open is just a mode change @@ -359,81 +344,69 @@ void ExecuteCommand(u32 _Address) // Open > Failed > ... other stuff > ReOpen call sequence, in that case // we have no file and no file handle, so we call Open again to basically // get a -106 error so that the game call CreateFile and then ReOpen again. + if(pDevice->ReturnFileHandle()) Memory::Write_U32(DeviceID, _Address + 4); else - GenerateReply = pDevice->Open(_Address, newMode); + pDevice->Open(_Address, newMode); } else { // We have already opened this device, return -6 Memory::Write_U32(u32(-6), _Address + 4); } - GenerateReply = true; - } + CmdSuccess = true; + } } break; case COMMAND_CLOSE_DEVICE: - { - u32 DeviceID = Memory::Read_U32(_Address + 8); - - IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID); + { if (pDevice != NULL) { pDevice->Close(_Address); // Delete the device when CLOSE is called, this does not effect // GenerateReply() for any other purpose than the logging because - // it's a true / false only function // + // it's a true / false only function ClosedDeviceID = DeviceID; - GenerateReply = true; + CmdSuccess = true; } } break; case COMMAND_READ: { - u32 DeviceID = Memory::Read_U32(_Address+8); - IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID); if (pDevice != NULL) - GenerateReply = pDevice->Read(_Address); + CmdSuccess = pDevice->Read(_Address); } break; case COMMAND_WRITE: { - u32 DeviceID = Memory::Read_U32(_Address+8); - IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID); if (pDevice != NULL) - GenerateReply = pDevice->Write(_Address); + CmdSuccess = pDevice->Write(_Address); } break; case COMMAND_SEEK: { - u32 DeviceID = Memory::Read_U32(_Address+8); - IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID); if (pDevice != NULL) - GenerateReply = pDevice->Seek(_Address); + CmdSuccess = pDevice->Seek(_Address); } break; case COMMAND_IOCTL: { - u32 DeviceID = Memory::Read_U32(_Address+8); - IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID); if (pDevice != NULL) - GenerateReply = pDevice->IOCtl(_Address); + CmdSuccess = pDevice->IOCtl(_Address); } break; case COMMAND_IOCTLV: { - u32 DeviceID = Memory::Read_U32(_Address+8); - IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID); if (pDevice) - GenerateReply = pDevice->IOCtlV(_Address); + CmdSuccess = pDevice->IOCtlV(_Address); } break; @@ -443,88 +416,101 @@ void ExecuteCommand(u32 _Address) break; } + // It seems that the original hardware overwrites the command after it has been // executed. We write 8 which is not any valid command. - Memory::Write_U32(8, _Address); + // + // AyuanX: Is this really necessary? + // My experiment says no, so I'm just commenting this out + // + //Memory::Write_U32(8, _Address); - // Generate a reply to the IPC command - if (GenerateReply) + if (CmdSuccess) { - // Get device id + // Generate a reply to the IPC command + WII_IPCInterface::EnqReply(_Address); + u32 DeviceID = Memory::Read_U32(_Address + 8); - IWII_IPC_HLE_Device* pDevice = NULL; - - // Get the device from the device map - if (DeviceID != 0) { - if (g_DeviceMap.find(DeviceID) != g_DeviceMap.end()) - pDevice = g_DeviceMap[DeviceID]; - - if (pDevice != NULL) { - // Write reply, this will later be executed in Update() - g_ReplyQueue.push(std::pair(_Address, pDevice->GetDeviceName())); - } else { + // DeviceID == 0 means it's used for devices that weren't created yet + if (DeviceID != 0) + { + if (g_DeviceMap.find(DeviceID) == g_DeviceMap.end()) ERROR_LOG(WII_IPC_HLE, "IOP: Reply to unknown device ID (DeviceID=%i)", DeviceID); - g_ReplyQueue.push(std::pair(_Address, "unknown")); - } - if (ClosedDeviceID > 0 && ClosedDeviceID == DeviceID) + if (ClosedDeviceID > 0 && (ClosedDeviceID == DeviceID)) DeleteDeviceByID(DeviceID); - - } else { - // 0 is ok, as it's used for devices that weren't created yet - g_ReplyQueue.push(std::pair(_Address, "unknown")); } } + else + { + //INFO_LOG(WII_IPC_HLE, "<<-- Failed or Not Ready to Reply to Command Address: 0x%08x ", _Address); + } } // =================================================== -/* This is called continuously from SystemTimers.cpp and WII_IPCInterface::IsReady() - is controlled from WII_IPC.cpp. */ -// ---------------- -void UpdateDevices() -{ - if (WII_IPCInterface::IsReady()) - { - // check if an executed must be updated - TDeviceMap::const_iterator itr = g_DeviceMap.begin(); - while(itr != g_DeviceMap.end()) - { - u32 CommandAddr = itr->second->Update(); - if (CommandAddr != 0) - { - g_ReplyQueue.push(std::pair(CommandAddr, itr->second->GetDeviceName())); - } - ++itr; - } - } -} - +// This is called continuously from SystemTimers.cpp +// --------------------------------------------------- void Update() { - if (WII_IPCInterface::IsReady()) + if (WII_IPCInterface::IsReady() == false) + return; + + UpdateDevices(); + + // if we have a reply to send + u32 _Reply = WII_IPCInterface::DeqReply(); + if (_Reply != NULL) { - // Check if we have to execute an acknowledge command... - if (!g_ReplyQueue.empty()) - { - WII_IPCInterface::GenerateReply(g_ReplyQueue.front().first); - g_ReplyQueue.pop(); - return; - } + WII_IPCInterface::GenerateReply(_Reply); + INFO_LOG(WII_IPC_HLE, "<<-- Reply to Command Address: 0x%08x", _Reply); + return; + } - // ...no we don't, we can now execute the IPC command - if (g_ReplyQueue.empty() && !g_Ack.empty()) - { - u32 _Address = g_Ack.front(); - g_Ack.pop_front(); - DEBUG_LOG(WII_IPC_HLE, "-- Execute Ack (0x%08x)", _Address); - ExecuteCommand(_Address); - DEBUG_LOG(WII_IPC_HLE, "-- End of ExecuteAck (0x%08x)", _Address); + // If there is a a new command + u32 _Address = WII_IPCInterface::GetAddress(); + if (_Address != NULL) + { + WII_IPCInterface::GenerateAck(); + INFO_LOG(WII_IPC_HLE, "||-- Acknowledge Command Address: 0x%08x", _Address); - // Go back to WII_IPC.cpp and generate an acknowledgement - WII_IPCInterface::GenerateAck(_Address); - } + ExecuteCommand(_Address); + + // AyuanX: Since current HLE time slot is empty, we can piggyback a reply + // Besides, this trick makes a Ping-Pong Reply FIFO never get full + // I don't know whether original hardware supports this feature or not + // but it works here and we gain 1/3 extra bandwidth + // + u32 _Reply = WII_IPCInterface::DeqReply(); + if (_Reply != NULL) + { + WII_IPCInterface::GenerateReply(_Reply); + INFO_LOG(WII_IPC_HLE, "<<-- Reply to Command Address: 0x%08x", _Reply); + } + + #if MAX_LOG_LEVEL >= DEBUG_LEVEL + Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG); + #endif + + return; + } + +} + +void UpdateDevices() +{ + // check if a device must be updated + TDeviceMap::const_iterator itr = g_DeviceMap.begin(); + + while(itr != g_DeviceMap.end()) + { + if (itr->second->Update()) + { + break; + } + ++itr; } } + } // end of namespace IPC diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.h index 4c86ebd5be..6941eb0238 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.h @@ -18,9 +18,10 @@ #ifndef _WII_IPC_HLE_H_ #define _WII_IPC_HLE_H_ +#include "ChunkFile.h" + namespace WII_IPC_HLE_Interface { - // Init void Init(); @@ -30,6 +31,9 @@ void Shutdown(); // Reset void Reset(); +// Do State +void DoState(PointerWrap &p); + // Set default content file void SetDefaultContentFile(const std::string& _rFilename); @@ -39,8 +43,7 @@ void Update(); // Update Devices void UpdateDevices(); -// Acknowledge command -bool AckCommand(u32 _Address); +void ExecuteCommand(u32 _Address); enum ECommandType { diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h index 8a9db90739..d4c1dfd18e 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h @@ -22,6 +22,8 @@ #include "../HW/Memmap.h" #include "../HW/CPU.h" +class PointerWrap; + class IWII_IPC_HLE_Device { public: @@ -34,6 +36,9 @@ public: virtual ~IWII_IPC_HLE_Device() {} + virtual void DoState(PointerWrap &p) + {} + const std::string& GetDeviceName() const { return m_Name; } u32 GetDeviceID() const { return m_DeviceID; } @@ -114,14 +119,12 @@ protected: } } - // STATE_TO_SAVE const u32 m_Address; u32 Parameter; u32 NumberInBuffer; u32 NumberPayloadBuffer; u32 BufferVector; - u32 BufferSize; struct SBuffer { u32 m_Address, m_Size; }; std::vector InBuffer; @@ -152,9 +155,8 @@ protected: LogTypes::LOG_LEVELS Verbosity = LogTypes::LDEBUG) { GENERIC_LOG(LogType, Verbosity, "======= DumpAsync ======"); - // write return value + u32 BufferOffset = BufferVector; - Memory::Write_U32(1, _CommandAddress + 0x4); for (u32 i = 0; i < NumberInBuffer; i++) { @@ -180,8 +182,6 @@ protected: u32 OutBuffer = Memory::Read_U32(BufferOffset); BufferOffset += 4; u32 OutBufferSize = Memory::Read_U32(BufferOffset); BufferOffset += 4; - Memory::Write_U32(1, _CommandAddress + 0x4); - GENERIC_LOG(LogType, LogTypes::LINFO, "%s - IOCtlV OutBuffer[%i]:", GetDeviceName().c_str(), i); GENERIC_LOG(LogType, LogTypes::LINFO, " OutBuffer: 0x%08x (0x%x):", OutBuffer, OutBufferSize); 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 28a756805b..494d99003b 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 @@ -22,15 +22,10 @@ #include "../Debugger/Debugger_SymbolMap.h" #include "../Host.h" #include "../PluginManager.h" +#include "../HW/WII_IPC.h" +#include "WII_IPC_HLE.h" #include "WII_IPC_HLE_Device_usb.h" - -// 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) @@ -42,10 +37,14 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De , m_HostMaxSCOSize(0) , m_HostNumACLPackets(0) , m_HostNumSCOPackets(0) - , m_pACLBuffer(NULL) - , m_pHCIBuffer(NULL) + , m_HCIBuffer(NULL) + , m_ACLBuffer(NULL) + , m_ACLFrame(0) + , m_LastCmd(NULL) + , m_PacketCount(0) { m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, 0)); + // Connect one Wiimote by default m_ControllerBD.b[0] = 0x11; m_ControllerBD.b[1] = 0x02; @@ -66,6 +65,16 @@ 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() {} +void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p) +{ + p.Do(m_LastCmd); + p.Do(m_PacketCount); + p.Do(m_CtrlSetup); + p.Do(m_HCIBuffer); + p.Do(m_ACLBuffer); + p.Do(m_ACLFrame); +} + // =================================================== // Open bool CWII_IPC_HLE_Device_usb_oh1_57e_305::Open(u32 _CommandAddress, u32 _Mode) @@ -96,27 +105,19 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtl(u32 _CommandAddress) bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress) { /* - - Memory::Write_U8(255, 0x80149950); // BTM LOG - // 3 logs L2Cap - // 4 logs l2_csm$ - + Memory::Write_U8(255, 0x80149950); // BTM LOG // 3 logs L2Cap // 4 logs l2_csm$ Memory::Write_U8(255, 0x80149949); // Security Manager - Memory::Write_U8(255, 0x80149048); // HID + Memory::Write_U8(3, 0x80152058); // low ?? // >= 4 and you will get a lot of event messages of the same type + Memory::Write_U8(1, 0x80152018); // WUD + Memory::Write_U8(1, 0x80151FC8); // DEBUGPrint + Memory::Write_U8(1, 0x80151488); // WPAD_LOG + Memory::Write_U8(1, 0x801514A8); // USB_LOG + Memory::Write_U8(1, 0x801514D8); // WUD_DEBUGPrint + Memory::Write_U8(1, 0x80148E09); // HID LOG +*/ - Memory::Write_U8(3, 0x80152058); // low ?? // >= 4 and you will get a lot of event messages of the same type - - Memory::Write_U8(1, 0x80152018); // WUD - - Memory::Write_U8(1, 0x80151FC8); // DEBUGPrint */ - - - // even it it wasn't very useful yet... - // Memory::Write_U8(1, 0x80151488); // WPAD_LOG - // Memory::Write_U8(1, 0x801514A8); // USB_LOG - // Memory::Write_U8(1, 0x801514D8); // WUD_DEBUGPrint - // Memory::Write_U8(1, 0x80148E09); // HID LOG + bool _SendReply = false; SIOCtlVBuffer CommandBuffer(_CommandAddress); @@ -124,37 +125,31 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress) { case USB_IOCTL_HCI_COMMAND_MESSAGE: { - SHCICommandMessage CtrlSetup; - - // the USB stuff is little endian.. - CtrlSetup.bRequestType = *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address); - CtrlSetup.bRequest = *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[1].m_Address); - CtrlSetup.wValue = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[2].m_Address); - CtrlSetup.wIndex = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[3].m_Address); - CtrlSetup.wLength = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[4].m_Address); - CtrlSetup.m_PayLoadAddr = CommandBuffer.PayloadBuffer[0].m_Address; - CtrlSetup.m_PayLoadSize = CommandBuffer.PayloadBuffer[0].m_Size; + // This is the HCI datapath from CPU to Wiimote, the USB stuff is little endian.. + m_CtrlSetup.bRequestType = *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address); + m_CtrlSetup.bRequest = *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[1].m_Address); + m_CtrlSetup.wValue = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[2].m_Address); + m_CtrlSetup.wIndex = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[3].m_Address); + m_CtrlSetup.wLength = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[4].m_Address); + m_CtrlSetup.m_PayLoadAddr = CommandBuffer.PayloadBuffer[0].m_Address; + m_CtrlSetup.m_PayLoadSize = CommandBuffer.PayloadBuffer[0].m_Size; + m_CtrlSetup.m_Address = CommandBuffer.m_Address; // check termination _dbg_assert_msg_(WII_IPC_WIIMOTE, *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[5].m_Address) == 0, "WIIMOTE: Termination != 0"); -#if 0 - INFO_LOG(WII_IPC_WIIMOTE, "USB_IOCTL_CTRLMSG (0x%08x) - execute command", _CommandAddress); + DEBUG_LOG(WII_IPC_WIIMOTE, "USB_IOCTL_CTRLMSG (0x%08x) - execute command", _CommandAddress); + DEBUG_LOG(WII_IPC_WIIMOTE, " bRequestType: 0x%x", m_CtrlSetup.bRequestType); + DEBUG_LOG(WII_IPC_WIIMOTE, " bRequest: 0x%x", m_CtrlSetup.bRequest); + DEBUG_LOG(WII_IPC_WIIMOTE, " wValue: 0x%x", m_CtrlSetup.wValue); + DEBUG_LOG(WII_IPC_WIIMOTE, " wIndex: 0x%x", m_CtrlSetup.wIndex); + DEBUG_LOG(WII_IPC_WIIMOTE, " wLength: 0x%x", m_CtrlSetup.wLength); + DEBUG_LOG(WII_IPC_WIIMOTE, " m_PayLoadAddr: 0x%x", m_CtrlSetup.m_PayLoadAddr); + DEBUG_LOG(WII_IPC_WIIMOTE, " m_PayLoadSize: 0x%x", m_CtrlSetup.m_PayLoadSize); - DEBUG_LOG(WII_IPC_WIIMOTE, " bRequestType: 0x%x", CtrlSetup.bRequestType); - DEBUG_LOG(WII_IPC_WIIMOTE, " bRequest: 0x%x", CtrlSetup.bRequest); - DEBUG_LOG(WII_IPC_WIIMOTE, " wValue: 0x%x", CtrlSetup.wValue); - DEBUG_LOG(WII_IPC_WIIMOTE, " wIndex: 0x%x", CtrlSetup.wIndex); - DEBUG_LOG(WII_IPC_WIIMOTE, " wLength: 0x%x", CtrlSetup.wLength); -#endif - - ExecuteHCICommandMessage(CtrlSetup); - - // control message has been sent executed - Memory::Write_U32(0, _CommandAddress + 0x4); - - return true; + ExecuteHCICommandMessage(m_CtrlSetup); + // Replies are generated inside } break; @@ -163,29 +158,39 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress) u8 Command = Memory::Read_U8(CommandBuffer.InBuffer[0].m_Address); switch (Command) { - case ACL_DATA_ENDPOINT_READ: + case ACL_DATA_BLK_OUT: { - // write - DumpAsync(CommandBuffer.BufferVector, _CommandAddress, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); + // This is the ACL datapath from CPU to Wiimote + // Here we only need to record the command address in case we need to delay the reply + m_CtrlSetup.m_Address = CommandBuffer.m_Address; - SIOCtlVBuffer pBulkBuffer(_CommandAddress); - UACLHeader* pACLHeader = (UACLHeader*)Memory::GetPointer(pBulkBuffer.PayloadBuffer[0].m_Address); + #if defined(_DEBUG) || defined(DEBUGFAST) + DumpAsync(CommandBuffer.BufferVector, _CommandAddress, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); + #endif + + CtrlBuffer BulkBuffer(_CommandAddress); + UACLHeader* pACLHeader = (UACLHeader*)Memory::GetPointer(BulkBuffer.m_buffer); _dbg_assert_(WII_IPC_WIIMOTE, pACLHeader->BCFlag == 0); _dbg_assert_(WII_IPC_WIIMOTE, pACLHeader->PBFlag == 2); - SendToDevice(pACLHeader->ConnectionHandle, Memory::GetPointer(pBulkBuffer.PayloadBuffer[0].m_Address + 4), pACLHeader->Size); + SendToDevice(pACLHeader->ConnectionHandle, Memory::GetPointer(BulkBuffer.m_buffer + 4), pACLHeader->Size); + m_PacketCount++; + + // If ACLFrame is not used, we can send a reply immediately + // or else we have to delay this reply + if (m_ACLFrame.m_number == 0) + _SendReply = true; } break; case ACL_DATA_ENDPOINT: { - if (m_pACLBuffer) - delete m_pACLBuffer; - m_pACLBuffer = new SIOCtlVBuffer(_CommandAddress); + CtrlBuffer _TempCtrlBuffer(_CommandAddress); + m_ACLBuffer = _TempCtrlBuffer; + // Reply should not be sent here but when this buffer is filled INFO_LOG(WII_IPC_WIIMOTE, "ACL_DATA_ENDPOINT: 0x%08x ", _CommandAddress); - return false; } break; @@ -206,14 +211,11 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress) { case HCI_EVENT_ENDPOINT: { - if (m_pHCIBuffer) - { - ERROR_LOG(WII_IPC_WIIMOTE, "Kill current hci buffer... there could be a comand inside"); - PanicAlert("Kill current hci buffer... there could be a comand inside"); - delete m_pHCIBuffer; - } - m_pHCIBuffer = new SIOCtlVBuffer(_CommandAddress); - return false; + CtrlBuffer _TempCtrlBuffer(_CommandAddress); + m_HCIBuffer = _TempCtrlBuffer; + // Reply should not be sent here but when this buffer is filled + + INFO_LOG(WII_IPC_WIIMOTE, "HCI_EVENT_ENDPOINT: 0x%08x ", _CommandAddress); } break; @@ -230,21 +232,23 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress) { _dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown CWII_IPC_HLE_Device_usb_oh1_57e_305: %x", CommandBuffer.Parameter); - INFO_LOG(WII_IPC_WIIMOTE, "%s - IOCtlV:", GetDeviceName().c_str()); + DEBUG_LOG(WII_IPC_WIIMOTE, "%s - IOCtlV:", GetDeviceName().c_str()); DEBUG_LOG(WII_IPC_WIIMOTE, " Parameter: 0x%x", CommandBuffer.Parameter); DEBUG_LOG(WII_IPC_WIIMOTE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); DEBUG_LOG(WII_IPC_WIIMOTE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); DEBUG_LOG(WII_IPC_WIIMOTE, " BufferVector: 0x%08x", CommandBuffer.BufferVector); - DEBUG_LOG(WII_IPC_WIIMOTE, " BufferSize: 0x%08x", CommandBuffer.BufferSize); + DEBUG_LOG(WII_IPC_WIIMOTE, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address); + DEBUG_LOG(WII_IPC_WIIMOTE, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size); + #if defined(_DEBUG) || defined(DEBUGFAST) DumpAsync(CommandBuffer.BufferVector, _CommandAddress, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); + #endif } break; } // write return value Memory::Write_U32(0, _CommandAddress + 0x4); - - return true; + return (_SendReply); } // ================ @@ -264,208 +268,276 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8 return; } - pWiiMote->SendACLFrame(_pData, _Size); + pWiiMote->ExecuteL2capCmd(_pData, _Size); } + // ================ - // =================================================== -/* Here we queue the ACL frames we receive from the Wiimote plugin. They will consist of - header + data. The header is for example 07 00 41 00 which means size 0x0007 and - channel 0x0041. */ -// ---------------- -void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLFrame(u16 _ConnectionHandle, u8* _pData, u32 _Size) +// Here we send ACL pakcets to CPU. They will consist of header + data. +// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041. +// --------------------------------------------------- + + +// AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately +// rather than enqueue it to some other memory +// But...the only exception is the Wiimote_Plugin +// +void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size) { - INFO_LOG(WII_IPC_WIIMOTE, "Queuing ACL frame."); - - // Queue the packet - ACLFrame frame; - frame.ConnectionHandle = _ConnectionHandle; - frame.data = new u8[_Size]; - memcpy(frame.data, _pData, _Size); - frame.size = _Size; - m_AclFrameQue.push(frame); - - /* Debugging - std::string Temp; - for (u32 j = 0; j < _Size; j++) + if(m_ACLBuffer.m_address != NULL) { - char Buffer[128]; - sprintf(Buffer, "%02x ", frame.data[j]); - Temp.append(Buffer); - } - LOGV(WII_IPC_WIIMOTE, 1, " Size: 0x%08x", _Size); - LOGV(WII_IPC_WIIMOTE, 1, " Data: %s", Temp.c_str()); */ + INFO_LOG(WII_IPC_WIIMOTE, "Sending ACL Packet: 0x%08x ....", m_ACLBuffer.m_address); - g_HCICount++; + UACLHeader* pHeader = (UACLHeader*)Memory::GetPointer(m_ACLBuffer.m_buffer); + pHeader->ConnectionHandle = _ConnectionHandle; + pHeader->BCFlag = 0; + pHeader->PBFlag = 2; + pHeader->Size = _Size; + + // Write the packet to the buffer + memcpy((u8*)pHeader + sizeof(UACLHeader), _pData, _Size); + + // Write the packet size as return value + Memory::Write_U32(sizeof(UACLHeader) + _Size, m_ACLBuffer.m_address + 0x4); + + // Send a reply to indicate ACL buffer is sent + WII_IPCInterface::EnqReply(m_ACLBuffer.m_address); + + // Invalidate ACL buffer + m_ACLBuffer.m_address = NULL; + m_ACLBuffer.m_buffer = NULL; + m_ACLFrame.m_number = 0; + } + else + { + // Actually this temp storage is not quite necessary + // the whole WII_IPC (HLE+USB+BT) won't need it + // but current implementation of WiiMote_Plugin has ruined everything + // although I can fix the Eme_WiiMote but that requires a little change of the plugin spec + // so unless somebody who works on the Real_WiiMote agrees, I won't do that + // + UACLHeader* pHeader = (UACLHeader*)(m_ACLFrame.m_data + m_ACLFrame.m_number * 64); // I belive 64B is enough + pHeader->ConnectionHandle = _ConnectionHandle; + pHeader->BCFlag = 0; + pHeader->PBFlag = 2; + pHeader->Size = _Size; + + memcpy((u8*)pHeader + sizeof(UACLHeader), _pData, _Size); + m_ACLFrame.m_number++; + + if (m_ACLFrame.m_number > 16) + { + ERROR_LOG(WII_IPC_WIIMOTE, "ACL Frame is full, something must be wrong!"); + PanicAlert("WII_IPC_WIIMOTE: ACL Frame is full, something must be wrong!"); + } + } } +// AyuanX: this ugly function is only useful when there are +// multiple L2CAP packets come from WiiMote_Plugin in one cycle +// +void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeACLFrame() +{ + if(m_ACLBuffer.m_address == NULL) + return; + + INFO_LOG(WII_IPC_WIIMOTE, "Purging ACL Frame: 0x%08x ....", m_ACLBuffer.m_address); + + if(m_ACLFrame.m_number > 0) + { + m_ACLFrame.m_number--; + // Fill the buffer + u8* _Address = m_ACLFrame.m_data + m_ACLFrame.m_number * 64; + memcpy(Memory::GetPointer(m_ACLBuffer.m_buffer), _Address, 64); + // Write the packet size as return value + Memory::Write_U32(sizeof(UACLHeader) + ((UACLHeader*)_Address)->Size, m_ACLBuffer.m_address + 0x4); + // Send a reply to indicate ACL buffer is sent + WII_IPCInterface::EnqReply(m_ACLBuffer.m_address); + // Invalidate ACL buffer + m_ACLBuffer.m_address = NULL; + m_ACLBuffer.m_buffer = NULL; + } +} // =================================================== /* See IPC_HLE_PERIOD in SystemTimers.cpp for a documentation of this update. */ // ---------------- u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() { - if (!m_EventQueue.empty() && m_pHCIBuffer) + // Check if last command needs more work + if (m_HCIBuffer.m_address && m_LastCmd) { - SIOCtlVBuffer* pHCIBuffer = m_pHCIBuffer; - m_pHCIBuffer = NULL; - - // copy the event to memory - const SQueuedEvent& rEvent = m_EventQueue.front(); - u8* pHCIEvent = Memory::GetPointer(pHCIBuffer->PayloadBuffer[0].m_Address); - memcpy(pHCIEvent, rEvent.m_buffer, rEvent.m_size); - - // return reply buffer size - Memory::Write_U32((u32)rEvent.m_size, pHCIBuffer->m_Address + 0x4); - - if (rEvent.m_connectionHandle > 0) - { - g_HCICount++; - } - - m_EventQueue.pop(); - - u32 Addr = pHCIBuffer->m_Address; - delete pHCIBuffer; - - return Addr; + ExecuteHCICommandMessage(m_CtrlSetup); + return true; } - // check if we can fill the aclbuffer - if(!m_AclFrameQue.empty() && m_pACLBuffer) + // Check if temp ACL frame is not purged + if (m_ACLFrame.m_number > 0) { - ACLFrame& frame = m_AclFrameQue.front(); - - INFO_LOG(WII_IPC_WIIMOTE, "Sending ACL frame."); - UACLHeader* pHeader = (UACLHeader*)Memory::GetPointer(m_pACLBuffer->PayloadBuffer[0].m_Address); - pHeader->ConnectionHandle = frame.ConnectionHandle; - pHeader->BCFlag = 0; - pHeader->PBFlag = 2; - pHeader->Size = frame.size; - - // Write the frame to the PayloadBuffer - memcpy(Memory::GetPointer(m_pACLBuffer->PayloadBuffer[0].m_Address + sizeof(UACLHeader)), - frame.data, frame.size); - - // return reply buffer size - Memory::Write_U32(sizeof(UACLHeader) + frame.size, m_pACLBuffer->m_Address + 0x4); - - delete [] frame.data; - m_AclFrameQue.pop(); - - u32 Addr = m_pACLBuffer->m_Address; - delete m_pACLBuffer; - m_pACLBuffer = NULL; - - - /* Debugging - std::string Temp; - for (u32 j = 0; j < frame.size; j++) - { - char Buffer[128]; - sprintf(Buffer, "%02x ", frame.data[j]); - Temp.append(Buffer); - } - LOGV(WII_IPC_WIIMOTE, 1, " Size: 0x%08x", frame.size); - LOGV(WII_IPC_WIIMOTE, 1, " Size of UACLHeader: 0x%08x", sizeof(UACLHeader)); - LOGV(WII_IPC_WIIMOTE, 1, " Data: %s", Temp.c_str()); */ - - return Addr; - } - - if ((g_GlobalHandle != 0) && (g_HCICount > 0)) - { - SendEventNumberOfCompletedPackets(g_GlobalHandle, g_HCICount*2); - g_HCICount = 0; - } - - if (m_AclFrameQue.empty()) - { - for (size_t i = 0; i < m_WiiMotes.size(); i++) - { - if (m_WiiMotes[i].Update()) - break; - } - } - - if (m_AclFrameQue.empty()) - { - CPluginManager::GetInstance().GetWiimote(0)->Wiimote_Update(); + PurgeACLFrame(); + if (m_ACLFrame.m_number == 0) + WII_IPCInterface::EnqReply(m_CtrlSetup.m_Address); + return true; } // -------------------------------------------------------------------- /* We wait for ScanEnable to be sent from the game through HCI_CMD_WRITE_SCAN_ENABLE - before we initiate the connection. To avoid doing this for GC games we also - want m_LocalName from CommandWriteLocalName() to be "Wii". + before we initiate the connection. FiRES: TODO find a good solution to do this - JP: Solution to what? When to run SendEventRequestConnection()? - */ - // ------------------------- - - /* I disabled this and disable m_ScanEnable instead to avoid running SendEventRequestConnection() - again. */ - //static bool test = true; /* 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)) + // AyuanX: I don't know the Real Wiimote behavior, so I'll leave it here untouched + // + // Initiate ACL connection + static int counter = (Core::GetRealWiimote() ? 1000 : 0); + if (m_HCIBuffer.m_address && (m_ScanEnable & 0x2)) { counter--; if (counter < 0) - { - //test = false; for (size_t i=0; i < m_WiiMotes.size(); i++) - { if (m_WiiMotes[i].EventPagingChanged(2)) { Host_SetWiiMoteConnectionState(1); + // Create ACL connection SendEventRequestConnection(m_WiiMotes[i]); + return true; } - } + } + + // AyuanX: Actually we don't need to link channels so early + // We can wait until HCI command: CommandReadRemoteFeatures is finished + // Because at this moment, CPU is busy handling HCI commands + // and have no time to respond ACL requests shortly + // But ... whatever, either way works + // + // Link channels when connected + if (m_ACLBuffer.m_address) + { + for (size_t i = 0; i < m_WiiMotes.size(); i++) + { + if (m_WiiMotes[i].LinkChannel()) + return true; } } - return 0; + // AyuanX: This event should be sent periodically or WiiMote will desync automatically + // but not too many or it will jam the bus and cost extra CPU time + // + static u32 FreqDividerSync = 0; + if (m_HCIBuffer.m_address && !WII_IPCInterface::GetAddress() && m_WiiMotes[0].IsLinked()) + { + FreqDividerSync++; + if ((m_PacketCount >0) || (FreqDividerSync > 15)) // Feel free to tweak it + { + FreqDividerSync = 0; + SendEventNumberOfCompletedPackets(m_WiiMotes[0].GetConnectionHandle(), m_PacketCount); + m_PacketCount = 0; + return true; + } + } + + // AyuanX: If we let this Wiimote_Update function running freely + // it will exaust all the HLE time slots and block further CPU commands + // so we have to make sure CPU and other things get the privilege to bypass this + // Besides, decreasing its reporting frequency also brings us great FPS boost + // Now I am making it running at 1/100 frequency of IPC which is already fast enough for human input + // + static u32 FreqDividerMote = 0; + if (m_ACLBuffer.m_address && !WII_IPCInterface::GetAddress() && !m_LastCmd && m_WiiMotes[0].IsLinked()) + { + FreqDividerMote++; + if(FreqDividerMote > 100) // Feel free to tweak it + { + FreqDividerMote = 0; + CPluginManager::GetInstance().GetWiimote(0)->Wiimote_Update(); + return true; + } + } + + return false; } // Events // ----------------- -// This is messages send from the Wiimote to the game, for example RequestConnection() +// Thess messages are sent from the Wiimote to the game, for example RequestConnection() // or ConnectionComplete(). // - +// Our WII_IPC_HLE is so efficient that we could fill the buffer immediately +// rather than enqueue it to some other memory and this will do good for StateSave void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _event) { - m_EventQueue.push(_event); + if (m_HCIBuffer.m_address != NULL) + { + INFO_LOG(WII_IPC_WIIMOTE, "Sending HCI Packet to Address: 0x%08x ....", m_HCIBuffer.m_address); + + memcpy(Memory::GetPointer(m_HCIBuffer.m_buffer), _event.m_buffer, _event.m_size); + + // Calculate buffer size + Memory::Write_U32((u32)_event.m_size, m_HCIBuffer.m_address + 0x4); + + // Send a reply to indicate HCI buffer is filled + WII_IPCInterface::EnqReply(m_HCIBuffer.m_address); + + // Invalidate HCI buffer + m_HCIBuffer.m_address = NULL; + m_HCIBuffer.m_buffer = NULL; + + return; + } + else + { + ERROR_LOG(WII_IPC_WIIMOTE, "Sending HCI Packet failed, HCI Buffer is invald!"); + PanicAlert("WII_IPC_HLE_DEVICE_USB: Sending HCI Packet failed, HCI Buffer is invald!"); + } } + bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventCommandStatus(u16 _Opcode) -{ - SQueuedEvent Event(sizeof(SHCIEventStatus), 0); +{ + // If we haven't sent this event or other events before, we will send it + // If we have, then skip it + if (m_LastCmd == NULL) + { + // Let's make a mark to show further events are scheduled + // besides this should also guarantee we won't send this event twice + // I think 65535 is big enough, so it won't trouble other events who also make use of g_LastCmd + m_LastCmd = 0xFFFF; - SHCIEventStatus* pHCIEvent = (SHCIEventStatus*)Event.m_buffer; - pHCIEvent->EventType = 0x0F; - pHCIEvent->PayloadLength = sizeof(SHCIEventStatus) - 2; - pHCIEvent->Status = 0x0; - pHCIEvent->PacketIndicator = 0x01; - pHCIEvent->Opcode = _Opcode; + SQueuedEvent Event(sizeof(SHCIEventStatus), 0); - AddEventToQueue(Event); + SHCIEventStatus* pHCIEvent = (SHCIEventStatus*)Event.m_buffer; + pHCIEvent->EventType = 0x0F; + pHCIEvent->PayloadLength = sizeof(SHCIEventStatus) - 2; + pHCIEvent->Status = 0x0; + pHCIEvent->PacketIndicator = 0x01; + pHCIEvent->Opcode = _Opcode; - INFO_LOG(WII_IPC_WIIMOTE, "Event: Command Status"); - INFO_LOG(WII_IPC_WIIMOTE, " Opcode: 0x%04x", pHCIEvent->Opcode); + INFO_LOG(WII_IPC_WIIMOTE, "Event: Command Status"); + INFO_LOG(WII_IPC_WIIMOTE, " Opcode: 0x%04x", pHCIEvent->Opcode); - return true; + AddEventToQueue(Event); + + return true; + } + else + { + // If the mark matches, clear it + // if not, keep it untouched + if (m_LastCmd==0xFFFF) + m_LastCmd = NULL; + + return false; + } } @@ -605,7 +677,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestConnection(CWII_IPC_HL pEventRequestConnection->uclass[0] = _rWiiMote.GetClass()[0]; pEventRequestConnection->uclass[1] = _rWiiMote.GetClass()[1]; pEventRequestConnection->uclass[2] = _rWiiMote.GetClass()[2]; - pEventRequestConnection->LinkType = 0x01; + pEventRequestConnection->LinkType = 0x01; // ACL AddEventToQueue(Event); @@ -619,6 +691,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestConnection(CWII_IPC_HL }; #endif + INFO_LOG(WII_IPC_WIIMOTE, "<<<<<<< Request ACL Connection >>>>>>>"); INFO_LOG(WII_IPC_WIIMOTE, "Event: SendEventRequestConnection"); INFO_LOG(WII_IPC_WIIMOTE, " bd: %02x:%02x:%02x:%02x:%02x:%02x", pEventRequestConnection->bdaddr.b[0], pEventRequestConnection->bdaddr.b[1], pEventRequestConnection->bdaddr.b[2], @@ -708,13 +781,8 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventConnectionComplete(bdaddr_t _ CWII_IPC_HLE_WiiMote* pWiimote = AccessWiiMote(_bd); if (pWiimote) - { pWiimote->EventConnectionAccepted(); - } - - g_GlobalHandle = pConnectionComplete->Connection_Handle; - #if MAX_LOGLEVEL >= DEBUG_LEVEL static char s_szLinkType[][128] = { @@ -893,12 +961,12 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventNumberOfCompletedPackets(u16 pNumberOfCompletedPackets->Connection_Handle = _connectionHandle; pNumberOfCompletedPackets->Number_Of_Completed_Packets = _count; - AddEventToQueue(Event); - // Log INFO_LOG(WII_IPC_WIIMOTE, "Event: SendEventNumberOfCompletedPackets"); - INFO_LOG(WII_IPC_WIIMOTE, " Connection_Handle: 0x%04x", pNumberOfCompletedPackets->Connection_Handle); - INFO_LOG(WII_IPC_WIIMOTE, " Number_Of_Completed_Packets: %i", pNumberOfCompletedPackets->Number_Of_Completed_Packets); + DEBUG_LOG(WII_IPC_WIIMOTE, " Connection_Handle: 0x%04x", pNumberOfCompletedPackets->Connection_Handle); + DEBUG_LOG(WII_IPC_WIIMOTE, " Number_Of_Completed_Packets: %i", pNumberOfCompletedPackets->Number_Of_Completed_Packets); + + AddEventToQueue(Event); return true; } @@ -921,12 +989,12 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventAuthenticationCompleted(u16 _ pEventAuthenticationCompleted->Status = 0; pEventAuthenticationCompleted->Connection_Handle = _connectionHandle; - AddEventToQueue(Event); - // Log INFO_LOG(WII_IPC_WIIMOTE, "Event: SendEventAuthenticationCompleted"); INFO_LOG(WII_IPC_WIIMOTE, " Connection_Handle: 0x%04x", pEventAuthenticationCompleted->Connection_Handle); + AddEventToQueue(Event); + return true; } @@ -950,12 +1018,12 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventModeChange(u16 _connectionHan pModeChange->CurrentMode = _mode; pModeChange->Value = _value; - AddEventToQueue(Event); - // Log INFO_LOG(WII_IPC_WIIMOTE, "Event: SendEventModeChange"); - INFO_LOG(WII_IPC_WIIMOTE, " Connection_Handle: 0x%04x", pModeChange->Connection_Handle); - INFO_LOG(WII_IPC_WIIMOTE, " missing other paramter :)"); + DEBUG_LOG(WII_IPC_WIIMOTE, " Connection_Handle: 0x%04x", pModeChange->Connection_Handle); + DEBUG_LOG(WII_IPC_WIIMOTE, " Current Mode: 0x%02x", pModeChange->CurrentMode = _mode); + + AddEventToQueue(Event); return true; } @@ -1003,9 +1071,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom u16 ocf = HCI_OCF(pMsg->Opcode); u16 ogf = HCI_OGF(pMsg->Opcode); - INFO_LOG(WII_IPC_WIIMOTE, "******************************"); - INFO_LOG(WII_IPC_WIIMOTE, "ExecuteHCICommandMessage(0x%04x)(ocf: 0x%02x, ogf: 0x%02x)", - pMsg->Opcode, ocf, ogf); + + // Only show info if this is a new HCI command + // or else we are continuing to execute last command + if(m_LastCmd == NULL) + { + INFO_LOG(WII_IPC_WIIMOTE, "**************************************************"); + INFO_LOG(WII_IPC_WIIMOTE, "ExecuteHCICommandMessage(0x%04x)(ocf: 0x%02x, ogf: 0x%02x)", pMsg->Opcode, ocf, ogf); + } switch(pMsg->Opcode) { @@ -1073,7 +1146,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom break; case HCI_CMD_INQUIRY: - CommandInquiry(pInput); + CommandInquiry(pInput); break; case HCI_CMD_WRITE_INQUIRY_SCAN_TYPE: @@ -1154,14 +1227,13 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom // default: { - u16 _ocf = HCI_OCF(pMsg->Opcode); - u16 _ogf = HCI_OGF(pMsg->Opcode); - - if (_ogf == 0x3f) + // send fake okay msg... + SendEventCommandComplete(pMsg->Opcode, NULL, 0); + + if (ogf == 0x3f) { PanicAlert("Vendor specific HCI command"); - ERROR_LOG(WII_IPC_WIIMOTE, "Command: vendor specific: 0x%04X (ocf: 0x%x)", pMsg->Opcode, _ocf); - + ERROR_LOG(WII_IPC_WIIMOTE, "Command: vendor specific: 0x%04X (ocf: 0x%x)", pMsg->Opcode, ocf); for (int i=0; ilen; i++) { ERROR_LOG(WII_IPC_WIIMOTE, " 0x02%x", pInput[i]); @@ -1169,14 +1241,17 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom } else { - _dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USB_IOCTL_CTRLMSG: 0x%04X (ocf: 0x%x ogf 0x%x)", pMsg->Opcode, _ocf, _ogf); + _dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USB_IOCTL_CTRLMSG: 0x%04X (ocf: 0x%x ogf 0x%x)", pMsg->Opcode, ocf, ogf); } - - // send fake all is okay msg... - SendEventCommandComplete(pMsg->Opcode, NULL, 0); } break; } + + if (m_LastCmd == NULL) + { + // HCI command finished, send a reply to command + WII_IPCInterface::EnqReply(_rHCICommandMessage.m_Address); + } } @@ -1201,10 +1276,11 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadBufferSize(u8* _Input) // reply hci_read_buffer_size_rp Reply; Reply.status = 0x00; - Reply.max_acl_size = 339; - Reply.num_acl_pkts = 10; + Reply.max_acl_size = 0x0FFF; //339; + Reply.num_acl_pkts = 0xFF; //10; Reply.max_sco_size = 64; Reply.num_sco_pkts = 0; + // AyuanX: Are these parameters fixed or adjustable ??? INFO_LOG(WII_IPC_WIIMOTE, "Command: HCI_CMD_READ_BUFFER_SIZE:"); DEBUG_LOG(WII_IPC_WIIMOTE, "return:"); @@ -1297,6 +1373,20 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadStoredLinkKey(u8* _Input) PanicAlert("CommandReadStoredLinkKey"); } + // generate link key + // Let us have some fun :P + if(m_LastCmdmax_acl_size); DEBUG_LOG(WII_IPC_WIIMOTE, " max_sco_size: %i", pHostBufferSize->max_sco_size); @@ -1523,11 +1606,23 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandSetEventFilter(u8* _Input) void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandInquiry(u8* _Input) { - // command parameters - hci_inquiry_cp* pInquiry = (hci_inquiry_cp*)_Input; - u8 lap[HCI_LAP_SIZE]; + if (SendEventCommandStatus(HCI_CMD_INQUIRY)) + return; - memcpy(lap, pInquiry->lap, HCI_LAP_SIZE); + if (m_LastCmd == NULL) + { + SendEventInquiryResponse(); + // Now let's set up a mark + m_LastCmd = HCI_CMD_INQUIRY; + } + else + { + SendEventInquiryComplete(); + // Clean up + m_LastCmd = NULL; + } + + hci_inquiry_cp* pInquiry = (hci_inquiry_cp*)_Input; INFO_LOG(WII_IPC_WIIMOTE, "Command: HCI_CMD_INQUIRY:"); DEBUG_LOG(WII_IPC_WIIMOTE, "write:"); @@ -1535,11 +1630,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandInquiry(u8* _Input) DEBUG_LOG(WII_IPC_WIIMOTE, " LAP[1]: 0x%02x", pInquiry->lap[1]); DEBUG_LOG(WII_IPC_WIIMOTE, " LAP[2]: 0x%02x", pInquiry->lap[2]); DEBUG_LOG(WII_IPC_WIIMOTE, " inquiry_length: %i (N x 1.28) sec", pInquiry->inquiry_length); - DEBUG_LOG(WII_IPC_WIIMOTE, " num_responses: %i (N x 1.28) sec", pInquiry->num_responses); - - SendEventCommandStatus(HCI_CMD_INQUIRY); - SendEventInquiryResponse(); - SendEventInquiryComplete(); + DEBUG_LOG(WII_IPC_WIIMOTE, " num_responses: %i (N x 1.28) sec", pInquiry->num_responses); } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteInquiryScanType(u8* _Input) @@ -1606,6 +1697,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandInquiryCancel(u8* _Input) void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandRemoteNameReq(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_REMOTE_NAME_REQ)) + return; + // command parameters hci_remote_name_req_cp* pRemoteNameReq = (hci_remote_name_req_cp*)_Input; @@ -1618,12 +1712,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandRemoteNameReq(u8* _Input) DEBUG_LOG(WII_IPC_WIIMOTE, " page_scan_mode: %i", pRemoteNameReq->page_scan_mode); DEBUG_LOG(WII_IPC_WIIMOTE, " clock_offset: %i", pRemoteNameReq->clock_offset); - SendEventCommandStatus(HCI_CMD_REMOTE_NAME_REQ); SendEventRemoteNameReq(pRemoteNameReq->bdaddr); } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandCreateCon(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_CREATE_CON)) + return; + // command parameters hci_create_con_cp* pCreateCon = (hci_create_con_cp*)_Input; @@ -1639,15 +1735,32 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandCreateCon(u8* _Input) DEBUG_LOG(WII_IPC_WIIMOTE, " clock_offset: %i", pCreateCon->clock_offset); DEBUG_LOG(WII_IPC_WIIMOTE, " accept_role_switch: %i", pCreateCon->accept_role_switch); - SendEventCommandStatus(HCI_CMD_CREATE_CON); SendEventConnectionComplete(pCreateCon->bdaddr); } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandAcceptCon(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_ACCEPT_CON)) + return; + // command parameters hci_accept_con_cp* pAcceptCon = (hci_accept_con_cp*)_Input; + // this connection wants to be the master + if ((m_LastCmd == NULL)&&(pAcceptCon->role == 0)) + { + SendEventRoleChange(pAcceptCon->bdaddr, true); + // Now let us set up a mark + m_LastCmd = HCI_CMD_ACCEPT_CON; + return; + } + else + { + SendEventConnectionComplete(pAcceptCon->bdaddr); + // Clean up + m_LastCmd = NULL; + } + #if MAX_LOGLEVEL >= DEBUG_LEVEL static char s_szRole[][128] = { @@ -1662,20 +1775,13 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandAcceptCon(u8* _Input) pAcceptCon->bdaddr.b[0], pAcceptCon->bdaddr.b[1], pAcceptCon->bdaddr.b[2], pAcceptCon->bdaddr.b[3], pAcceptCon->bdaddr.b[4], pAcceptCon->bdaddr.b[5]); DEBUG_LOG(WII_IPC_WIIMOTE, " role: %s", s_szRole[pAcceptCon->role]); - - SendEventCommandStatus(HCI_CMD_ACCEPT_CON); - - // this connection wants to be the master - if (pAcceptCon->role == 0) - { - SendEventRoleChange(pAcceptCon->bdaddr, true); - } - - SendEventConnectionComplete(pAcceptCon->bdaddr); } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadClockOffset(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_READ_CLOCK_OFFSET)) + return; + // command parameters hci_read_clock_offset_cp* pReadClockOffset = (hci_read_clock_offset_cp*)_Input; @@ -1683,16 +1789,17 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadClockOffset(u8* _Input) DEBUG_LOG(WII_IPC_WIIMOTE, "Input:"); DEBUG_LOG(WII_IPC_WIIMOTE, " ConnectionHandle: 0x%02x", pReadClockOffset->con_handle); - SendEventCommandStatus(HCI_CMD_READ_CLOCK_OFFSET); SendEventReadClockOffsetComplete(pReadClockOffset->con_handle); - // CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(pReadClockOffset->con_handle); // SendEventRequestLinkKey(pWiiMote->GetBD()); } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadRemoteVerInfo(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_READ_REMOTE_VER_INFO)) + return; + // command parameters hci_read_remote_ver_info_cp* pReadRemoteVerInfo = (hci_read_remote_ver_info_cp*)_Input; @@ -1700,12 +1807,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadRemoteVerInfo(u8* _Input) DEBUG_LOG(WII_IPC_WIIMOTE, "Input:"); DEBUG_LOG(WII_IPC_WIIMOTE, " ConnectionHandle: 0x%02x", pReadRemoteVerInfo->con_handle); - SendEventCommandStatus(HCI_CMD_READ_REMOTE_VER_INFO); SendEventReadRemoteVerInfo(pReadRemoteVerInfo->con_handle); } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadRemoteFeatures(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_READ_REMOTE_FEATURES)) + return; + // command parameters hci_read_remote_features_cp* pReadRemoteFeatures = (hci_read_remote_features_cp*)_Input; @@ -1713,12 +1822,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadRemoteFeatures(u8* _Input) DEBUG_LOG(WII_IPC_WIIMOTE, "Input:"); DEBUG_LOG(WII_IPC_WIIMOTE, " ConnectionHandle: 0x%04x", pReadRemoteFeatures->con_handle); - SendEventCommandStatus(HCI_CMD_READ_REMOTE_FEATURES); SendEventReadRemoteFeatures(pReadRemoteFeatures->con_handle); } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkPolicy(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_WRITE_LINK_POLICY_SETTINGS)) + return; + // command parameters hci_write_link_policy_settings_cp* pLinkPolicy = (hci_write_link_policy_settings_cp*)_Input; @@ -1727,8 +1838,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkPolicy(u8* _Input) DEBUG_LOG(WII_IPC_WIIMOTE, " ConnectionHandle: 0x%04x", pLinkPolicy->con_handle); DEBUG_LOG(WII_IPC_WIIMOTE, " Policy: 0x%04x", pLinkPolicy->settings); - SendEventCommandStatus(HCI_CMD_WRITE_LINK_POLICY_SETTINGS); - CWII_IPC_HLE_WiiMote* pWiimote = AccessWiiMote(pLinkPolicy->con_handle); if (pWiimote) { @@ -1738,6 +1847,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkPolicy(u8* _Input) void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandAuthenticationRequested(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_AUTH_REQ)) + return; + // command parameters hci_auth_req_cp* pAuthReq = (hci_auth_req_cp*)_Input; @@ -1745,12 +1857,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandAuthenticationRequested(u8* _In DEBUG_LOG(WII_IPC_WIIMOTE, "Input:"); DEBUG_LOG(WII_IPC_WIIMOTE, " ConnectionHandle: 0x%04x", pAuthReq->con_handle); - SendEventCommandStatus(HCI_CMD_AUTH_REQ); SendEventAuthenticationCompleted(pAuthReq->con_handle); } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandSniffMode(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_SNIFF_MODE)) + return; + // command parameters hci_sniff_mode_cp* pSniffMode = (hci_sniff_mode_cp*)_Input; @@ -1762,12 +1876,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandSniffMode(u8* _Input) DEBUG_LOG(WII_IPC_WIIMOTE, " attempt: 0x%04x", pSniffMode->attempt); DEBUG_LOG(WII_IPC_WIIMOTE, " timeout: 0x%04x", pSniffMode->timeout); - SendEventCommandStatus(HCI_CMD_SNIFF_MODE); SendEventModeChange(pSniffMode->con_handle, 0x02, pSniffMode->max_interval); // 0x02 - sniff mode } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDisconnect(u8* _Input) { + if(SendEventCommandStatus(HCI_CMD_DISCONNECT)) + return; + // command parameters hci_discon_cp* pDiscon = (hci_discon_cp*)_Input; @@ -1776,14 +1892,15 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDisconnect(u8* _Input) DEBUG_LOG(WII_IPC_WIIMOTE, " ConnectionHandle: 0x%04x", pDiscon->con_handle); DEBUG_LOG(WII_IPC_WIIMOTE, " Reason: 0x%02x", pDiscon->reason); - SendEventCommandStatus(HCI_CMD_DISCONNECT); SendEventDisconnect(pDiscon->con_handle, pDiscon->reason); +// AyuanX : Disconnecting WiiMote is a bad idea because we don't support reconnect yet +// so let's don't do it +/* CWII_IPC_HLE_WiiMote* pWiimote = AccessWiiMote(pDiscon->con_handle); if (pWiimote) - { pWiimote->EventDisconnect(); - } +*/ static bool OneShotMessage = true; if (OneShotMessage) @@ -1977,3 +2094,4 @@ bool CWII_IPC_HLE_Device_usb_oh0::IOCtlV(u32 _CommandAddress) Memory::Write_U32(0, _CommandAddress + 0x4); return true; } + diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h index e98ec47e9e..1787f0f890 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h @@ -18,11 +18,11 @@ #ifndef _WII_IPC_HLE_DEVICE_USB_H_ #define _WII_IPC_HLE_DEVICE_USB_H_ -#include "WII_IPC_HLE_Device.h" #include "hci.h" #include #include - +#include "WII_IPC_HLE.h" +#include "WII_IPC_HLE_Device.h" #include "WII_IPC_HLE_WiiMote.h" @@ -38,13 +38,6 @@ union UACLHeader u32 Hex; }; -struct ACLFrame -{ - u16 ConnectionHandle; - u8* data; - u32 size; -}; - struct SQueuedEvent { u8 m_buffer[1024]; @@ -58,7 +51,7 @@ struct SQueuedEvent if (m_size > 1024) { // i know this code sux... - PanicAlert("SQueuedEvent: allocate a to big buffer!!"); + PanicAlert("SQueuedEvent: allocate too big buffer!!"); } } }; @@ -79,7 +72,8 @@ public: virtual u32 Update(); - void SendACLFrame(u16 _ConnectionHandle, u8* _pData, u32 _Size); + void SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size); + void PurgeACLFrame(); //hack for wiimote plugin @@ -89,6 +83,8 @@ public: CWII_IPC_HLE_WiiMote* AccessWiiMote(const bdaddr_t& _rAddr); CWII_IPC_HLE_WiiMote* AccessWiiMote(u16 _ConnectionHandle); + void DoState(PointerWrap &p); + private: enum @@ -106,7 +102,7 @@ private: enum { HCI_EVENT_ENDPOINT = 0x81, - ACL_DATA_ENDPOINT_READ = 0x02, + ACL_DATA_BLK_OUT = 0x02, ACL_DATA_ENDPOINT = 0x82, }; @@ -121,6 +117,39 @@ private: u32 m_PayLoadAddr; u32 m_PayLoadSize; + u32 m_Address; + }; + + struct ACLFrame + { + u32 m_number; + u8 m_data[1024]; + + ACLFrame(int num) + : m_number(num) + { + } + }; + + struct CtrlBuffer + { + u32 m_address; + u32 m_buffer; + + CtrlBuffer(u32 _Address) + : m_address(_Address) + { + if(_Address == NULL) + { + m_buffer = NULL; + } + else + { + u32 _BufferVector = Memory::Read_U32(_Address + 0x18); + u32 _InBufferNum = Memory::Read_U32(_Address + 0x10); + m_buffer = Memory::Read_U32(_BufferVector + _InBufferNum * 8); + } + } }; bdaddr_t m_ControllerBD; @@ -138,13 +167,14 @@ private: u16 m_HostNumSCOPackets; typedef std::queue CEventQueue; - typedef std::queue CACLFrameQueue; - CEventQueue m_EventQueue; - CACLFrameQueue m_AclFrameQue; - - SIOCtlVBuffer* m_pACLBuffer; - SIOCtlVBuffer* m_pHCIBuffer; + // STATE_TO_SAVE + SHCICommandMessage m_CtrlSetup; + CtrlBuffer m_HCIBuffer; + CtrlBuffer m_ACLBuffer; + ACLFrame m_ACLFrame; + u32 m_LastCmd; + int m_PacketCount; // Events void AddEventToQueue(const SQueuedEvent& _event); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp index 8cb55a5175..cfc119c5dc 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp @@ -33,6 +33,7 @@ static CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb; CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* _pHost, int _Number) : m_Connected(false) + , m_Linked(false) , m_HIDControlChannel_Connected(false) , m_HIDControlChannel_ConnectedWait(false) , m_HIDControlChannel_Config(false) @@ -47,7 +48,7 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* { s_Usb = _pHost; - INFO_LOG(WII_IPC_WIIMOTE, "Wiimote %i constructed", _Number); + INFO_LOG(WII_IPC_WIIMOTE, "Wiimote #%i constructed", _Number); m_BD.b[0] = 0x11; m_BD.b[1] = 0x02; @@ -89,25 +90,24 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* // // - -bool CWII_IPC_HLE_WiiMote::Update() +bool CWII_IPC_HLE_WiiMote::LinkChannel() { - if (m_Connected == false) + if ((m_Connected == false) || (m_Linked == true)) return false; - // try to connect HIDP_CONTROL_CHANNEL + // try to connect HID_CONTROL_CHANNEL if (!m_HIDControlChannel_Connected) { if (m_HIDControlChannel_ConnectedWait) return false; m_HIDControlChannel_ConnectedWait = true; - SendConnectionRequest(0x0040, HIDP_CONTROL_CHANNEL); - + // The CID is fixed, other CID will be rejected + SendConnectionRequest(0x0040, HID_CONTROL_CHANNEL); return true; } - // try to config HIDP_CONTROL_CHANNEL + // try to config HID_CONTROL_CHANNEL if (!m_HIDControlChannel_Config) { if (m_HIDControlChannel_ConfigWait) @@ -127,6 +127,7 @@ bool CWII_IPC_HLE_WiiMote::Update() return false; m_HIDInterruptChannel_ConnectedWait = true; + // The CID is fixed, other CID will be rejected SendConnectionRequest(0x0041, HID_INTERRUPT_CHANNEL); return true; } @@ -144,11 +145,75 @@ bool CWII_IPC_HLE_WiiMote::Update() return true; } + m_Linked = true; UpdateStatus(); return false; } +// =================================================== +/* Send a status report to the status bar. */ +// ---------------- +void CWII_IPC_HLE_WiiMote::ShowStatus(const void* _pData) +{ + // Check if it's enabled + SCoreStartupParameter& StartUp = SConfig::GetInstance().m_LocalCoreStartupParameter; + bool LedsOn = StartUp.bWiiLeds; + bool SpeakersOn = StartUp.bWiiSpeakers; + + const u8* data = (const u8*)_pData; + + // Get the last four bits with LED info + if (LedsOn) + { + if (data[1] == 0x11) + { + int led_bits = (data[2] >> 4); + Host_UpdateLeds(led_bits); + } + } + + int speaker_bits = 0; + + if (SpeakersOn) + { + u8 Bits = 0; + switch (data[1]) + { + case 0x14: // Enable and disable speakers + if (data[2] == 0x02) // Off + Bits = 0; + else if (data[2] == 0x06) // On + Bits = 1; + Host_UpdateSpeakerStatus(0, Bits); + break; + + case 0x19: // Mute and unmute + // Get the value + if (data[2] == 0x02) // Unmute + Bits = 1; + else if (data[2] == 0x06) // Mute + Bits = 0; + Host_UpdateSpeakerStatus(1, Bits); + break; + // Write to speaker registry, or write sound + case 0x16: + case 0x18: + // Turn on the activity light + Host_UpdateSpeakerStatus(2, 1); + break; + } + } +} + +// Turn off the activity icon again +void CWII_IPC_HLE_WiiMote::UpdateStatus() +{ + // Check if it's enabled + if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiSpeakers) + return; + Host_UpdateStatus(); +} // // @@ -165,11 +230,13 @@ bool CWII_IPC_HLE_WiiMote::Update() void CWII_IPC_HLE_WiiMote::EventConnectionAccepted() { m_Connected = true; + m_Linked = false; } void CWII_IPC_HLE_WiiMote::EventDisconnect() { m_Connected = false; + m_Linked = false; } bool CWII_IPC_HLE_WiiMote::EventPagingChanged(u8 _pageMode) @@ -210,22 +277,20 @@ void CWII_IPC_HLE_WiiMote::EventCommandWriteLinkPolicy() // - // =================================================== -/* This function send ACL frams from the Wii to Wiimote_ControlChannel() in the Wiimote. - It's called from SendToDevice() in WII_IPC_HLE_Device_usb.cpp. */ -// ---------------- -void CWII_IPC_HLE_WiiMote::SendACLFrame(u8* _pData, u32 _Size) +// This function receives L2CAP commands from the CPU +// It's called from SendToDevice() in WII_IPC_HLE_Device_usb.cpp. +// --------------------------------------------------- +void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size) { - // Debugger::PrintDataBuffer(LogTypes::WIIMOTE, _pData, _Size, "SendACLFrame: "); + // Debugger::PrintDataBuffer(LogTypes::WIIMOTE, _pData, _Size, "SendACLPacket: "); // parse the command SL2CAP_Header* pHeader = (SL2CAP_Header*)_pData; u8* pData = _pData + sizeof(SL2CAP_Header); u32 DataSize = _Size - sizeof(SL2CAP_Header); - - INFO_LOG(WII_IPC_WIIMOTE, "L2Cap-SendFrame: Channel 0x%04x, Len 0x%x, DataSize 0x%x", - pHeader->CID, pHeader->Length, DataSize); + INFO_LOG(WII_IPC_WIIMOTE, "++++++++++++++++++++++++++++++++++++++"); + INFO_LOG(WII_IPC_WIIMOTE, "Execute L2CAP Command: Cid 0x%04x, Len 0x%x, DataSize 0x%x", pHeader->CID, pHeader->Length, DataSize); if(pHeader->Length != DataSize) { @@ -241,8 +306,9 @@ void CWII_IPC_HLE_WiiMote::SendACLFrame(u8* _pData, u32 _Size) default: { - _dbg_assert_msg_(WII_IPC_WIIMOTE, DoesChannelExist(pHeader->CID), "SendACLFrame to unknown channel %i", pHeader->CID); + _dbg_assert_msg_(WII_IPC_WIIMOTE, DoesChannelExist(pHeader->CID), "L2CAP: SendACLPacket to unknown channel %i", pHeader->CID); CChannelMap::iterator itr= m_Channel.find(pHeader->CID); + Common::PluginWiimote* mote = CPluginManager::GetInstance().GetWiimote(0); if (itr != m_Channel.end()) { @@ -253,13 +319,15 @@ void CWII_IPC_HLE_WiiMote::SendACLFrame(u8* _pData, u32 _Size) HandleSDP(pHeader->CID, pData, DataSize); break; - case HIDP_CONTROL_CHANNEL: + case HID_CONTROL_CHANNEL: mote->Wiimote_ControlChannel(rChannel.DCID, pData, DataSize); + // Call Wiimote Plugin break; case HID_INTERRUPT_CHANNEL: ShowStatus(pData); mote->Wiimote_InterruptChannel(rChannel.DCID, pData, DataSize); + // Call Wiimote Plugin break; default: @@ -272,72 +340,6 @@ void CWII_IPC_HLE_WiiMote::SendACLFrame(u8* _pData, u32 _Size) break; } } - - -// =================================================== -/* Send a status report to the status bar. */ -// ---------------- -void CWII_IPC_HLE_WiiMote::ShowStatus(const void* _pData) -{ - // Check if it's enabled - SCoreStartupParameter& StartUp = SConfig::GetInstance().m_LocalCoreStartupParameter; - bool LedsOn = StartUp.bWiiLeds; - bool SpeakersOn = StartUp.bWiiSpeakers; - - const u8* data = (const u8*)_pData; - - // Get the last four bits with LED info - if (LedsOn) - { - if (data[1] == 0x11) - { - int led_bits = (data[2] >> 4); - Host_UpdateLeds(led_bits); - } - } - - int speaker_bits = 0; - - if (SpeakersOn) - { - u8 Bits = 0; - switch (data[1]) - { - case 0x14: // Enable and disable speakers - if (data[2] == 0x02) // Off - Bits = 0; - else if (data[2] == 0x06) // On - Bits = 1; - Host_UpdateSpeakerStatus(0, Bits); - break; - - case 0x19: // Mute and unmute - // Get the value - if (data[2] == 0x02) // Unmute - Bits = 1; - else if (data[2] == 0x06) // Mute - Bits = 0; - Host_UpdateSpeakerStatus(1, Bits); - break; - // Write to speaker registry, or write sound - case 0x16: - case 0x18: - // Turn on the activity light - Host_UpdateSpeakerStatus(2, 1); - break; - } - } -} - -// Turn off the activity icon again -void CWII_IPC_HLE_WiiMote::UpdateStatus() -{ - // Check if it's enabled - if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiSpeakers) - return; - Host_UpdateStatus(); -} - // ================ void CWII_IPC_HLE_WiiMote::SignalChannel(u8* _pData, u32 _Size) @@ -350,34 +352,34 @@ void CWII_IPC_HLE_WiiMote::SignalChannel(u8* _pData, u32 _Size) switch(pCommand->code) { - case L2CAP_CONN_REQ: - CommandConnectionReq(pCommand->ident, _pData, pCommand->len); + case L2CAP_COMMAND_REJ: + ERROR_LOG(WII_IPC_WIIMOTE, "SignalChannel - L2CAP_COMMAND_REJ (something went wrong)." + "Try to replace your SYSCONF file with a new copy." + ,pCommand->code); + PanicAlert( + "SignalChannel - L2CAP_COMMAND_REJ (something went wrong)." + "Try to replace your SYSCONF file with a new copy." + ,pCommand->code); break; - case L2CAP_CONF_REQ: - CommandCofigurationReq(pCommand->ident, _pData, pCommand->len); + case L2CAP_CONN_REQ: + ReceiveConnectionReq(pCommand->ident, _pData, pCommand->len); break; case L2CAP_CONN_RSP: - CommandConnectionResponse(pCommand->ident, _pData, pCommand->len); + ReceiveConnectionResponse(pCommand->ident, _pData, pCommand->len); break; - case L2CAP_DISCONN_REQ: - CommandDisconnectionReq(pCommand->ident, _pData, pCommand->len); + case L2CAP_CONF_REQ: + ReceiveConfigurationReq(pCommand->ident, _pData, pCommand->len); break; case L2CAP_CONF_RSP: - CommandConfigurationResponse(pCommand->ident, _pData, pCommand->len); + ReceiveConfigurationResponse(pCommand->ident, _pData, pCommand->len); break; - case L2CAP_COMMAND_REJ: - ERROR_LOG(WII_IPC_WIIMOTE, "SignalChannel - L2CAP_COMMAND_REJ (something went wrong). Try to replace your" - "SYSCONF file with a new copy." - ,pCommand->code); - PanicAlert( - "SignalChannel - L2CAP_COMMAND_REJ (something went wrong). Try to replace your" - "SYSCONF file with a new copy." - ,pCommand->code); + case L2CAP_DISCONN_REQ: + ReceiveDisconnectionReq(pCommand->ident, _pData, pCommand->len); break; default: @@ -390,21 +392,18 @@ void CWII_IPC_HLE_WiiMote::SignalChannel(u8* _pData, u32 _Size) } } - // // // // -// --- Send Commands To Device +// --- Receive Commands from CPU // // // // // - - -void CWII_IPC_HLE_WiiMote::CommandConnectionReq(u8 _Ident, u8* _pData, u32 _Size) +void CWII_IPC_HLE_WiiMote::ReceiveConnectionReq(u8 _Ident, u8* _pData, u32 _Size) { SL2CAP_CommandConnectionReq* pCommandConnectionReq = (SL2CAP_CommandConnectionReq*)_pData; @@ -414,7 +413,7 @@ void CWII_IPC_HLE_WiiMote::CommandConnectionReq(u8 _Ident, u8* _pData, u32 _Size rChannel.SCID = pCommandConnectionReq->scid; rChannel.DCID = pCommandConnectionReq->scid; - INFO_LOG(WII_IPC_WIIMOTE, " CommandConnectionReq"); + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] ReceiveConnectionRequest"); DEBUG_LOG(WII_IPC_WIIMOTE, " Ident: 0x%02x", _Ident); DEBUG_LOG(WII_IPC_WIIMOTE, " PSM: 0x%04x", rChannel.PSM); DEBUG_LOG(WII_IPC_WIIMOTE, " SCID: 0x%04x", rChannel.SCID); @@ -427,31 +426,58 @@ void CWII_IPC_HLE_WiiMote::CommandConnectionReq(u8 _Ident, u8* _pData, u32 _Size Rsp.result = 0x00; Rsp.status = 0x00; + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] SendConnectionResponse"); SendCommandToACL(_Ident, L2CAP_CONN_RSP, sizeof(SL2CAP_ConnectionResponse), (u8*)&Rsp); +} - // update state machine - if (rChannel.PSM == HIDP_CONTROL_CHANNEL) +void CWII_IPC_HLE_WiiMote::ReceiveConnectionResponse(u8 _Ident, u8* _pData, u32 _Size) +{ + l2cap_conn_rsp* rsp = (l2cap_conn_rsp*)_pData; + + _dbg_assert_(WII_IPC_WIIMOTE, _Size == sizeof(l2cap_conn_rsp)); + + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] ReceiveConnectionResponse"); + DEBUG_LOG(WII_IPC_WIIMOTE, " DCID: 0x%04x", rsp->dcid); + DEBUG_LOG(WII_IPC_WIIMOTE, " SCID: 0x%04x", rsp->scid); + DEBUG_LOG(WII_IPC_WIIMOTE, " Result: 0x%04x", rsp->result); + DEBUG_LOG(WII_IPC_WIIMOTE, " Status: 0x%04x", rsp->status); + + _dbg_assert_(WII_IPC_WIIMOTE, rsp->result == 0); + _dbg_assert_(WII_IPC_WIIMOTE, rsp->status == 0); + _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(rsp->scid)); + + SChannel& rChannel = m_Channel[rsp->scid]; + rChannel.DCID = rsp->dcid; + + // + // AyuanX: I'm commenting this out because CPU thinks he is faster than WiiMote + // and basically CPU will take the initiative to config channel + // in any case we don't want to race against CPU, or we are doomed + // so we wait for CPU to request first + // + /* + if (rChannel.PSM == HID_CONTROL_CHANNEL) m_HIDControlChannel_Connected = true; if (rChannel.PSM == HID_INTERRUPT_CHANNEL) m_HIDInterruptChannel_Connected = true; + */ } -void CWII_IPC_HLE_WiiMote::CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Size) +void CWII_IPC_HLE_WiiMote::ReceiveConfigurationReq(u8 _Ident, u8* _pData, u32 _Size) { - INFO_LOG(WII_IPC_WIIMOTE, "*******************************************************"); u32 Offset = 0; SL2CAP_CommandConfigurationReq* pCommandConfigReq = (SL2CAP_CommandConfigurationReq*)_pData; _dbg_assert_(WII_IPC_WIIMOTE, pCommandConfigReq->flags == 0x00); // 1 means that the options are send in multi-packets - _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(pCommandConfigReq->dcid)); + SChannel& rChannel = m_Channel[pCommandConfigReq->dcid]; - INFO_LOG(WII_IPC_WIIMOTE, " CommandCofigurationReq"); - INFO_LOG(WII_IPC_WIIMOTE, " Ident: 0x%02x", _Ident); - INFO_LOG(WII_IPC_WIIMOTE, " DCID: 0x%04x", pCommandConfigReq->dcid); - INFO_LOG(WII_IPC_WIIMOTE, " Flags: 0x%04x", pCommandConfigReq->flags); + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] ReceiveConfigurationRequest"); + DEBUG_LOG(WII_IPC_WIIMOTE, " Ident: 0x%02x", _Ident); + DEBUG_LOG(WII_IPC_WIIMOTE, " DCID: 0x%04x", pCommandConfigReq->dcid); + DEBUG_LOG(WII_IPC_WIIMOTE, " Flags: 0x%04x", pCommandConfigReq->flags); Offset += sizeof(SL2CAP_CommandConfigurationReq); @@ -478,7 +504,11 @@ void CWII_IPC_HLE_WiiMote::CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Si _dbg_assert_(WII_IPC_WIIMOTE, pOptions->length == 2); SL2CAP_OptionsMTU* pMTU = (SL2CAP_OptionsMTU*)&_pData[Offset]; rChannel.MTU = pMTU->MTU; - INFO_LOG(WII_IPC_WIIMOTE, " Config MTU: 0x%04x", pMTU->MTU); + DEBUG_LOG(WII_IPC_WIIMOTE, " Config MTU: 0x%04x", pMTU->MTU); + // AyuanX: My experiment shows that the MTU is always set to 640 bytes + // This means that we only need temp_frame_size of 640B instead 1024B + // Actually I've never seen a frame bigger than 64B + // But... who cares of several KB mem today? Never mind } break; @@ -487,7 +517,7 @@ void CWII_IPC_HLE_WiiMote::CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Si _dbg_assert_(WII_IPC_WIIMOTE, pOptions->length == 2); SL2CAP_OptionsFlushTimeOut* pFlushTimeOut = (SL2CAP_OptionsFlushTimeOut*)&_pData[Offset]; rChannel.FlushTimeOut = pFlushTimeOut->TimeOut; - INFO_LOG(WII_IPC_WIIMOTE, " Config FlushTimeOut: 0x%04x", pFlushTimeOut->TimeOut); + DEBUG_LOG(WII_IPC_WIIMOTE, " Config FlushTimeOut: 0x%04x", pFlushTimeOut->TimeOut); } break; @@ -503,44 +533,25 @@ void CWII_IPC_HLE_WiiMote::CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Si RespLen += OptionSize; } + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] SendConfigurationResponse"); SendCommandToACL(_Ident, L2CAP_CONF_RSP, RespLen, TempBuffer); - INFO_LOG(WII_IPC_WIIMOTE, "*******************************************************"); -} - -void CWII_IPC_HLE_WiiMote::CommandConnectionResponse(u8 _Ident, u8* _pData, u32 _Size) -{ - l2cap_conn_rsp* rsp = (l2cap_conn_rsp*)_pData; - - _dbg_assert_(WII_IPC_WIIMOTE, _Size == sizeof(l2cap_conn_rsp)); - - INFO_LOG(WII_IPC_WIIMOTE, " CommandConnectionResponse"); - DEBUG_LOG(WII_IPC_WIIMOTE, " DCID: 0x%04x", rsp->dcid); - DEBUG_LOG(WII_IPC_WIIMOTE, " SCID: 0x%04x", rsp->scid); - DEBUG_LOG(WII_IPC_WIIMOTE, " Result: 0x%04x", rsp->result); - DEBUG_LOG(WII_IPC_WIIMOTE, " Status: 0x%04x", rsp->status); - - _dbg_assert_(WII_IPC_WIIMOTE, rsp->result == 0); - _dbg_assert_(WII_IPC_WIIMOTE, rsp->status == 0); - - _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(rsp->scid)); - SChannel& rChannel = m_Channel[rsp->scid]; - rChannel.DCID = rsp->dcid; // update state machine - if (rChannel.PSM == HIDP_CONTROL_CHANNEL) + if (rChannel.PSM == HID_CONTROL_CHANNEL) m_HIDControlChannel_Connected = true; if (rChannel.PSM == HID_INTERRUPT_CHANNEL) m_HIDInterruptChannel_Connected = true; + } -void CWII_IPC_HLE_WiiMote::CommandConfigurationResponse(u8 _Ident, u8* _pData, u32 _Size) +void CWII_IPC_HLE_WiiMote::ReceiveConfigurationResponse(u8 _Ident, u8* _pData, u32 _Size) { l2cap_conf_rsp* rsp = (l2cap_conf_rsp*)_pData; _dbg_assert_(WII_IPC_WIIMOTE, _Size == sizeof(l2cap_conf_rsp)); - INFO_LOG(WII_IPC_WIIMOTE, " CommandConfigurationResponse"); + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] ReceiveConfigurationResponse"); DEBUG_LOG(WII_IPC_WIIMOTE, " SCID: 0x%04x", rsp->scid); DEBUG_LOG(WII_IPC_WIIMOTE, " Flags: 0x%04x", rsp->flags); DEBUG_LOG(WII_IPC_WIIMOTE, " Result: 0x%04x", rsp->result); @@ -549,21 +560,22 @@ void CWII_IPC_HLE_WiiMote::CommandConfigurationResponse(u8 _Ident, u8* _pData, u // update state machine SChannel& rChannel = m_Channel[rsp->scid]; - if (rChannel.PSM == HIDP_CONTROL_CHANNEL) + + if (rChannel.PSM == HID_CONTROL_CHANNEL) m_HIDControlChannel_Config = true; if (rChannel.PSM == HID_INTERRUPT_CHANNEL) m_HIDInterruptChannel_Config = true; + } -void CWII_IPC_HLE_WiiMote::CommandDisconnectionReq(u8 _Ident, u8* _pData, u32 _Size) +void CWII_IPC_HLE_WiiMote::ReceiveDisconnectionReq(u8 _Ident, u8* _pData, u32 _Size) { SL2CAP_CommandDisconnectionReq* pCommandDisconnectionReq = (SL2CAP_CommandDisconnectionReq*)_pData; - // create the channel _dbg_assert_(WII_IPC_WIIMOTE, m_Channel.find(pCommandDisconnectionReq->scid) != m_Channel.end()); - INFO_LOG(WII_IPC_WIIMOTE, " CommandDisconnectionReq"); + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] ReceiveDisconnectionReq"); DEBUG_LOG(WII_IPC_WIIMOTE, " Ident: 0x%02x", _Ident); DEBUG_LOG(WII_IPC_WIIMOTE, " SCID: 0x%04x", pCommandDisconnectionReq->dcid); DEBUG_LOG(WII_IPC_WIIMOTE, " DCID: 0x%04x", pCommandDisconnectionReq->scid); @@ -573,23 +585,22 @@ void CWII_IPC_HLE_WiiMote::CommandDisconnectionReq(u8 _Ident, u8* _pData, u32 _S Rsp.scid = pCommandDisconnectionReq->scid; Rsp.dcid = pCommandDisconnectionReq->dcid; + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] SendDisconnectionResponse"); SendCommandToACL(_Ident, L2CAP_DISCONN_RSP, sizeof(SL2CAP_CommandDisconnectionResponse), (u8*)&Rsp); } - // // // // -// --- Send Commands To Device +// --- Send Commands To CPU // // // // // - - +// We assume WiiMote is always connected void CWII_IPC_HLE_WiiMote::SendConnectionRequest(u16 scid, u16 psm) { // create the channel @@ -601,13 +612,14 @@ void CWII_IPC_HLE_WiiMote::SendConnectionRequest(u16 scid, u16 psm) cr.psm = psm; cr.scid = scid; - INFO_LOG(WII_IPC_WIIMOTE, " SendConnectionRequest()"); + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] SendConnectionRequest"); DEBUG_LOG(WII_IPC_WIIMOTE, " Psm: 0x%04x", cr.psm); DEBUG_LOG(WII_IPC_WIIMOTE, " Scid: 0x%04x", cr.scid); SendCommandToACL(L2CAP_CONN_REQ, L2CAP_CONN_REQ, sizeof(l2cap_conn_req), (u8*)&cr); } +// We don't initiatively disconnet Wiimote though ... void CWII_IPC_HLE_WiiMote::SendDisconnectRequest(u16 scid) { // create the channel @@ -617,7 +629,7 @@ void CWII_IPC_HLE_WiiMote::SendDisconnectRequest(u16 scid) cr.dcid = rChannel.DCID; cr.scid = rChannel.SCID; - INFO_LOG(WII_IPC_WIIMOTE, " SendDisconnectionRequest()"); + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] SendDisconnectionRequest"); DEBUG_LOG(WII_IPC_WIIMOTE, " Dcid: 0x%04x", cr.dcid); DEBUG_LOG(WII_IPC_WIIMOTE, " Scid: 0x%04x", cr.scid); @@ -659,13 +671,10 @@ void CWII_IPC_HLE_WiiMote::SendConfigurationRequest(u16 scid, u16* MTU, u16* Flu *(u16*)&Buffer[Offset] = *FlushTimeOut; Offset += 2; } - INFO_LOG(WII_IPC_WIIMOTE, " SendConfigurationRequest()"); + INFO_LOG(WII_IPC_WIIMOTE, "[ACL] SendConfigurationRequest"); DEBUG_LOG(WII_IPC_WIIMOTE, " Dcid: 0x%04x", cr->dcid); DEBUG_LOG(WII_IPC_WIIMOTE, " Flags: 0x%04x", cr->flags); - // hack: - static u8 ident = 99; - ident++; SendCommandToACL(L2CAP_CONF_REQ, L2CAP_CONF_REQ, Offset, Buffer); } @@ -681,7 +690,6 @@ void CWII_IPC_HLE_WiiMote::SendConfigurationRequest(u16 scid, u16* MTU, u16* Flu // // - #define SDP_UINT8 0x08 #define SDP_UINT16 0x09 #define SDP_UINT32 0x0A @@ -718,7 +726,7 @@ void CWII_IPC_HLE_WiiMote::SDPSendServiceSearchResponse(u16 cid, u16 Transaction pHeader->Length = (u16)(Offset - sizeof(SL2CAP_Header)); - m_pHost->SendACLFrame(GetConnectionHandle(), DataFrame, pHeader->Length + sizeof(SL2CAP_Header)); + m_pHost->SendACLPacket(GetConnectionHandle(), DataFrame, pHeader->Length + sizeof(SL2CAP_Header)); } u32 ParseCont(u8* pCont) @@ -746,10 +754,12 @@ int ParseAttribList(u8* pAttribIDList, u16& _startID, u16& _endID) u32 attribOffset = 0; CBigEndianBuffer attribList(pAttribIDList); - u8 sequence = attribList.Read8(attribOffset); attribOffset++; _dbg_assert_(WII_IPC_WIIMOTE, sequence == SDP_SEQ8); + u8 sequence = attribList.Read8(attribOffset); attribOffset++; u8 seqSize = attribList.Read8(attribOffset); attribOffset++; u8 typeID = attribList.Read8(attribOffset); attribOffset++; + _dbg_assert_(WII_IPC_WIIMOTE, sequence == SDP_SEQ8); + if (typeID == SDP_UINT32) { _startID = attribList.Read16(attribOffset); attribOffset += 2; @@ -759,7 +769,7 @@ int ParseAttribList(u8* pAttribIDList, u16& _startID, u16& _endID) { _startID = attribList.Read16(attribOffset); attribOffset += 2; _endID = _startID; - WARN_LOG(WII_IPC_WIIMOTE, "Read just a single attrib - not tested"); + DEBUG_LOG(WII_IPC_WIIMOTE, "Read just a single attrib - not tested"); PanicAlert("Read just a single attrib - not tested"); } @@ -799,9 +809,9 @@ void CWII_IPC_HLE_WiiMote::SDPSendServiceAttributeResponse(u16 cid, u16 Transact memcpy(buffer.GetPointer(Offset), pPacket, packetSize); Offset += packetSize; pHeader->Length = (u16)(Offset - sizeof(SL2CAP_Header)); - m_pHost->SendACLFrame(GetConnectionHandle(), DataFrame, pHeader->Length + sizeof(SL2CAP_Header)); + m_pHost->SendACLPacket(GetConnectionHandle(), DataFrame, pHeader->Length + sizeof(SL2CAP_Header)); -// Debugger::PrintDataBuffer(LogTypes::WIIMOTE, DataFrame, pHeader->Length + sizeof(SL2CAP_Header), "test response: "); + // Debugger::PrintDataBuffer(LogTypes::WIIMOTE, DataFrame, pHeader->Length + sizeof(SL2CAP_Header), "test response: "); } void CWII_IPC_HLE_WiiMote::HandleSDP(u16 cid, u8* _pData, u32 _Size) @@ -812,7 +822,7 @@ void CWII_IPC_HLE_WiiMote::HandleSDP(u16 cid, u8* _pData, u32 _Size) switch(buffer.Read8(0)) { - // SDP_ServiceSearchRequest + // SDP_ServiceSearchRequest case 0x02: { WARN_LOG(WII_IPC_WIIMOTE, "!!! SDP_ServiceSearchRequest !!!"); @@ -829,7 +839,7 @@ void CWII_IPC_HLE_WiiMote::HandleSDP(u16 cid, u8* _pData, u32 _Size) } break; - // SDP_ServiceAttributeRequest + // SDP_ServiceAttributeRequest case 0x04: { WARN_LOG(WII_IPC_WIIMOTE, "!!! SDP_ServiceAttributeRequest !!!"); @@ -867,8 +877,6 @@ void CWII_IPC_HLE_WiiMote::HandleSDP(u16 cid, u8* _pData, u32 _Size) // // - - void CWII_IPC_HLE_WiiMote::SendCommandToACL(u8 _Ident, u8 _Code, u8 _CommandLength, u8* _pCommandData) { u8 DataFrame[1024]; @@ -885,22 +893,22 @@ void CWII_IPC_HLE_WiiMote::SendCommandToACL(u8 _Ident, u8 _Code, u8 _CommandLeng memcpy(&DataFrame[Offset], _pCommandData, _CommandLength); - INFO_LOG(WII_IPC_WIIMOTE, " SendCommandToACL (answer)"); + DEBUG_LOG(WII_IPC_WIIMOTE, " SendCommandToACL (to CPU)"); DEBUG_LOG(WII_IPC_WIIMOTE, " Ident: 0x%02x", _Ident); DEBUG_LOG(WII_IPC_WIIMOTE, " Code: 0x%02x", _Code); // send .... - m_pHost->SendACLFrame(GetConnectionHandle(), DataFrame, pHeader->Length + sizeof(SL2CAP_Header)); + m_pHost->SendACLPacket(GetConnectionHandle(), DataFrame, pHeader->Length + sizeof(SL2CAP_Header)); - // Debugger::PrintDataBuffer(LogTypes::WIIMOTE, DataFrame, pHeader->Length + sizeof(SL2CAP_Header), "m_pHost->SendACLFrame: "); + // Debugger::PrintDataBuffer(LogTypes::WIIMOTE, DataFrame, pHeader->Length + sizeof(SL2CAP_Header), "m_pHost->SendACLPacket: "); } // =================================================== -/* On a second boot the _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(scid)) makes a report. However - the game eventually starts and the Wiimote connects, but it takes at least ten seconds. */ -// ---------------- -void CWII_IPC_HLE_WiiMote::SendL2capData(u16 scid, const void* _pData, u32 _Size) +// On a second boot the _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(scid)) makes a report. +// However the game eventually starts and the Wiimote connects, but it takes at least ten seconds. +// --------------------------------------------------- +void CWII_IPC_HLE_WiiMote::ReceiveL2capData(u16 scid, const void* _pData, u32 _Size) { // Allocate DataFrame u8 DataFrame[1024]; @@ -921,11 +929,11 @@ void CWII_IPC_HLE_WiiMote::SendL2capData(u16 scid, const void* _pData, u32 _Size // Update Offset to the final size of the report Offset += _Size; - // Send the report - m_pHost->SendACLFrame(GetConnectionHandle(), DataFrame, Offset); - // Update the status bar Host_SetWiiMoteConnectionState(2); + + // Send the report + m_pHost->SendACLPacket(GetConnectionHandle(), DataFrame, Offset); } @@ -942,7 +950,7 @@ namespace Core DEBUG_LOG(WII_IPC_WIIMOTE, " Data: %s", ArrayToString(pData, _Size, 0, 50).c_str()); DEBUG_LOG(WII_IPC_WIIMOTE, " Channel: %u", _channelID); - s_Usb->m_WiiMotes[0].SendL2capData(_channelID, _pData, _Size); + s_Usb->m_WiiMotes[0].ReceiveL2capData(_channelID, _pData, _Size); DEBUG_LOG(WII_IPC_WIIMOTE, "========================================================="); } } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h index fbfdddfe4a..84bbbfc1c8 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h @@ -26,7 +26,7 @@ class CWII_IPC_HLE_Device_usb_oh1_57e_305; enum { SDP_CHANNEL = 0x01, - HIDP_CONTROL_CHANNEL = 0x11, + HID_CONTROL_CHANNEL = 0x11, HID_INTERRUPT_CHANNEL= 0x13, // L2CAP command codes @@ -192,9 +192,13 @@ public: // ugly Host handling.... // we really have to clean all this code - bool Update(); + bool LinkChannel(); bool IsConnected() const { return m_Connected; } - + bool IsLinked() const { return m_Linked; } + void ShowStatus(const void* _pData); // Show status + void UpdateStatus(); // Update status + void ExecuteL2capCmd(u8* _pData, u32 _Size); // From CPU + void ReceiveL2capData(u16 scid, const void* _pData, u32 _Size); // From wiimote void EventConnectionAccepted(); void EventDisconnect(); @@ -202,33 +206,20 @@ public: void EventCommandWriteLinkPolicy(); const bdaddr_t& GetBD() const { return m_BD; } - const uint8_t* GetClass() const { return uclass; } - u16 GetConnectionHandle() const { return m_ControllerConnectionHandle; } - const u8* GetFeatures() const { return features; } - const char* GetName() const { return m_Name.c_str(); } - u8 GetLMPVersion() const { return lmp_version; } - u16 GetLMPSubVersion() const { return lmp_subversion; } - u8 GetManufactorID() const { return 0xF; } // Broadcom Corporation - - void SendACLFrame(u8* _pData, u32 _Size); // To wiimote - void ShowStatus(const void* _pData); // Show status - void UpdateStatus(); // Update status - - void SendL2capData(u16 scid, const void* _pData, u32 _Size); // From wiimote - const u8* GetLinkKey() const { return m_LinkKey; } private: // state machine bool m_Connected; + bool m_Linked; bool m_HIDControlChannel_Connected; bool m_HIDControlChannel_ConnectedWait; bool m_HIDControlChannel_Config; @@ -238,25 +229,15 @@ private: bool m_HIDInterruptChannel_Config; bool m_HIDInterruptChannel_ConfigWait; - - // STATE_TO_SAVE bdaddr_t m_BD; - u16 m_ControllerConnectionHandle; - uint8_t uclass[HCI_CLASS_SIZE]; - u8 features[HCI_FEATURES_SIZE]; - u8 lmp_version; - u16 lmp_subversion; - u8 m_LinkKey[16]; - std::string m_Name; - CWII_IPC_HLE_Device_usb_oh1_57e_305* m_pHost; struct SChannel @@ -285,13 +266,11 @@ private: void SendConfigurationRequest(u16 _SCID, u16* _pMTU = NULL, u16* _pFlushTimeOut = NULL); void SendDisconnectRequest(u16 _SCID); - void CommandConnectionReq(u8 _Ident, u8* _pData, u32 _Size); - void CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Size); - void CommandConnectionResponse(u8 _Ident, u8* _pData, u32 _Size); - void CommandDisconnectionReq(u8 _Ident, u8* _pData, u32 _Size); - void CommandConfigurationResponse(u8 _Ident, u8* _pData, u32 _Size); - - + void ReceiveConnectionReq(u8 _Ident, u8* _pData, u32 _Size); + void ReceiveConnectionResponse(u8 _Ident, u8* _pData, u32 _Size); + void ReceiveDisconnectionReq(u8 _Ident, u8* _pData, u32 _Size); + void ReceiveConfigurationReq(u8 _Ident, u8* _pData, u32 _Size); + void ReceiveConfigurationResponse(u8 _Ident, u8* _pData, u32 _Size); // some new ugly stuff // diff --git a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp index 5e0997a242..f42b547b32 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp @@ -37,7 +37,7 @@ Callback_WiimoteInput() CWII_IPC_HLE_WiiMote::SendL2capData() WII_IPC_HLE_Device_usb.cpp: - CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLFrame() + CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket() at that point the message is queued and will be sent by the next CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() */ @@ -69,22 +69,20 @@ namespace WiiMoteEmu // Update the data reporting mode -void WmDataReporting(u16 _channelID, wm_data_reporting* dr) +void WmReportMode(u16 _channelID, wm_report_mode* dr) { - DEBUG_LOG(WIIMOTE, " Set Data reporting mode"); + INFO_LOG(WIIMOTE, "Set data report mode"); DEBUG_LOG(WIIMOTE, " Rumble: %x", dr->rumble); DEBUG_LOG(WIIMOTE, " Continuous: %x", dr->continuous); DEBUG_LOG(WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time); DEBUG_LOG(WIIMOTE, " Mode: 0x%02x", dr->mode); - DEBUG_LOG(WIIMOTE, "Data reporting:"); - DEBUG_LOG(WIIMOTE, " Continuous: %x", dr->continuous); - DEBUG_LOG(WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time); - DEBUG_LOG(WIIMOTE, " Mode: 0x%02x", dr->mode); - DEBUG_LOG(WIIMOTE, " Channel: 0x%04x", _channelID); - + + g_ReportingAuto = dr->all_the_time; g_ReportingMode = dr->mode; g_ReportingChannel = _channelID; - switch(dr->mode) // See Wiimote_Update() + + // Validation check + switch(dr->mode) { case WM_REPORT_CORE: case WM_REPORT_CORE_ACCEL: @@ -95,9 +93,6 @@ void WmDataReporting(u16 _channelID, wm_data_reporting* dr) default: PanicAlert("Wiimote: Unsupported reporting mode 0x%x", dr->mode); } - - // WmSendAck(_channelID, WM_DATA_REPORTING); - } @@ -106,7 +101,7 @@ void WmDataReporting(u16 _channelID, wm_data_reporting* dr) void SendReportCore(u16 _channelID) { u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE); + u32 Offset = WriteWmReportHdr(DataFrame, WM_REPORT_CORE); wm_report_core* pReport = (wm_report_core*)(DataFrame + Offset); Offset += sizeof(wm_report_core); @@ -115,12 +110,14 @@ void SendReportCore(u16 _channelID) FillReportInfo(pReport->c); #endif - INFO_LOG(WIIMOTE, " SendReportCore()"); + INFO_LOG(WIIMOTE, " SendReportCore(0x30)"); + DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID); + DEBUG_LOG(WIIMOTE, " Size: %08x", Offset); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); // Debugging - ReadDebugging(true, DataFrame, Offset); + //ReadDebugging(true, DataFrame, Offset); } @@ -128,7 +125,7 @@ void SendReportCore(u16 _channelID) void SendReportCoreAccel(u16 _channelID) { u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL); + u32 Offset = WriteWmReportHdr(DataFrame, WM_REPORT_CORE_ACCEL); wm_report_core_accel* pReport = (wm_report_core_accel*)(DataFrame + Offset); Offset += sizeof(wm_report_core_accel); @@ -140,20 +137,20 @@ void SendReportCoreAccel(u16 _channelID) #endif INFO_LOG(WIIMOTE, " SendReportCoreAccel (0x31)"); - INFO_LOG(WIIMOTE, " Channel: %04x", _channelID); - INFO_LOG(WIIMOTE, " Offset: %08x", Offset); + DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID); + DEBUG_LOG(WIIMOTE, " Size: %08x", Offset); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); // Debugging - ReadDebugging(true, DataFrame, Offset); + //ReadDebugging(true, DataFrame, Offset); } /* Case 0x33: Core Buttons and Accelerometer with 12 IR bytes */ void SendReportCoreAccelIr12(u16 _channelID) { u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_IR12); + u32 Offset = WriteWmReportHdr(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); @@ -169,13 +166,14 @@ void SendReportCoreAccelIr12(u16 _channelID) { memset(&pReport->ir[2], 0xff, sizeof(wm_ir_extended)); memset(&pReport->ir[3], 0xff, sizeof(wm_ir_extended)); - INFO_LOG(WIIMOTE, " SendReportCoreAccelIr12()"); - INFO_LOG(WIIMOTE, " Offset: %08x", Offset); + INFO_LOG(WIIMOTE, " SendReportCoreAccelIr12(0x33)"); + DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID); + DEBUG_LOG(WIIMOTE, " Size: %08x", Offset); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); // Debugging - ReadDebugging(true, DataFrame, Offset); + //ReadDebugging(true, DataFrame, Offset); } @@ -183,7 +181,7 @@ void SendReportCoreAccelIr12(u16 _channelID) { void SendReportCoreAccelExt16(u16 _channelID) { u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_EXT16); + u32 Offset = WriteWmReportHdr(DataFrame, WM_REPORT_CORE_ACCEL_EXT16); wm_report_core_accel_ext16* pReport = (wm_report_core_accel_ext16*)(DataFrame + Offset); Offset += sizeof(wm_report_core_accel_ext16); @@ -209,18 +207,18 @@ void SendReportCoreAccelExt16(u16 _channelID) #if defined(HAVE_WX) && HAVE_WX FillReportClassicExtension(_ext); #endif -//TODO // Copy _ext to pReport->ext + // Copy _ext to pReport->ext memcpy(&pReport->ext, &_ext, sizeof(_ext)); } INFO_LOG(WIIMOTE, " SendReportCoreAccelExt16 (0x35)"); - INFO_LOG(WIIMOTE, " Channel: %04x", _channelID); - INFO_LOG(WIIMOTE, " Offset: %08x", Offset); + DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID); + DEBUG_LOG(WIIMOTE, " Size: %08x", Offset); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); // Debugging - ReadDebugging(true, DataFrame, Offset); + //ReadDebugging(true, DataFrame, Offset); } @@ -228,7 +226,7 @@ void SendReportCoreAccelExt16(u16 _channelID) void SendReportCoreAccelIr10Ext(u16 _channelID) { u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_IR10_EXT6); + u32 Offset = WriteWmReportHdr(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); @@ -267,12 +265,14 @@ void SendReportCoreAccelIr10Ext(u16 _channelID) memcpy(&pReport->ext, &_GH3_ext, sizeof(_GH3_ext)); } - INFO_LOG(WIIMOTE, " SendReportCoreAccelIr10Ext()"); + INFO_LOG(WIIMOTE, " SendReportCoreAccelIr10Ext(0x37)"); + DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID); + DEBUG_LOG(WIIMOTE, " Size: %08x", Offset); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); // Debugging - ReadDebugging(true, DataFrame, Offset); + //ReadDebugging(true, DataFrame, Offset); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp index fd3af76015..f96e7b9cb4 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp @@ -48,6 +48,7 @@ u8 g_RegExt[WIIMOTE_REG_EXT_SIZE]; u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE]; u8 g_RegIr[WIIMOTE_REG_IR_SIZE]; +bool g_ReportingAuto; // Auto report or passive report u8 g_ReportingMode; // The reporting mode and channel id u16 g_ReportingChannel; diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h index 84ea66ca71..eccfe00145 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h @@ -80,6 +80,7 @@ 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 bool g_ReportingAuto; extern u8 g_ReportingMode; extern u16 g_ReportingChannel; diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index 236b98cebd..63b0a3c0ca 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -373,6 +373,7 @@ void ExtensionChecksum(u8 * Calibration) // Set initial valuesm this done both in Init and Shutdown void ResetVariables() { + g_ReportingAuto = false; g_ReportingMode = 0; g_ReportingChannel = 0; g_Encryption = false; @@ -465,11 +466,10 @@ void Initialize() void DoState(PointerWrap &p) { - return; // TODO: Shorten the list p.Do(g_Leds); - //p.Do(g_Speaker); - //p.Do(g_SpeakerVoice); + p.Do(g_Speaker); + p.Do(g_SpeakerVoice); p.Do(g_IR); p.DoArray(g_Eeprom, WIIMOTE_EEPROM_SIZE); p.DoArray(g_RegSpeaker, WIIMOTE_REG_SPEAKER_SIZE); @@ -477,23 +477,23 @@ void DoState(PointerWrap &p) p.DoArray(g_RegExtTmp, WIIMOTE_REG_EXT_SIZE); p.DoArray(g_RegIr, WIIMOTE_REG_IR_SIZE); + p.Do(g_ReportingAuto); p.Do(g_ReportingMode); p.Do(g_ReportingChannel); - p.Do(AckDelay); - p.Do(g_ExtKey); p.Do(g_Encryption); - p.Do(NumPads); - p.Do(NumGoodPads); - p.Do(joyinfo); - p.DoArray(PadState, 4); - p.DoArray(PadMapping, 4); + //p.Do(NumPads); + //p.Do(NumGoodPads); + //p.Do(joyinfo); + //p.DoArray(PadState, 4); + //p.DoArray(PadMapping, 4); - p.Do(g_Wiimote_kbd); - p.Do(g_NunchuckExt); - p.Do(g_ClassicContExt); + //p.Do(g_Wiimote_kbd); + //p.Do(g_NunchuckExt); + //p.Do(g_ClassicContExt); + return; } /* This is not needed if we call FreeLibrary() when we stop a game, but if it's @@ -528,62 +528,19 @@ void Shutdown(void) if (SDL_WasInit(0)) SDL_Quit(); } - -/* 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 in Zelda - TP. You may have to increase - this value for other things to work, for example in the wpad demo I had to - set it to at least 3 for the Sound to be able to turned on (I have an update - rate of around 150 fps in the wpad demo) */ -void CreateAckDelay(u8 _ChannelID, u16 _ReportID) -{ - // Settings - int GlobalDelay = 2; - - // Queue an acknowledgment - wm_ackdelay Tmp; - Tmp.Delay = GlobalDelay; - Tmp.ChannelID = _ChannelID; - Tmp.ReportID = (u8)_ReportID; - AckDelay.push_back(Tmp); -} - - -void CheckAckDelay() -{ - for (int i = 0; i < (int)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--; - - //INFO_LOG(WIIMOTE, "%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) { - //INFO_LOG(WIIMOTE, "Emu InterruptChannel"); - - DEBUG_LOG(WIIMOTE, "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. */ - InterruptDebugging(true, data); + //InterruptDebugging(true, (const void*)_pData); + + hid_packet* hidp = (hid_packet*)_pData; + + INFO_LOG(WIIMOTE, "Emu InterruptChannel (type: 0x%02x, param: 0x%02x)", hidp->type, hidp->param); - hid_packet* hidp = (hid_packet*) data; switch(hidp->type) { case HID_TYPE_DATA: @@ -612,11 +569,20 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) // that, also if we do *we should update the 0x22 to have // the core keys* otherwise the game will think we release // the key every time it rumbles + + // AyuanX: Since I've rewritten the whole WII_IPC & WII_IPC_HLE & USB & BT + // finally we can get rid of this AckDelay issue, HAHA! + // + /* + const u8* data = (const u8*)_pData; if(!(data[1] == WM_READ_DATA && data[2] == 0x00) && !(data[1] == WM_REQUEST_STATUS) && !(data[1] == WM_WRITE_SPEAKER_DATA) && !(data[1] == WM_RUMBLE)) - if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) CreateAckDelay((u8)_channelID, (u16)sr->channel); + if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) + CreateAckDelay((u8)_channelID, (u16)sr->wm); + */ + } break; @@ -636,47 +602,36 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) { - //INFO_LOG(WIIMOTE, "Emu ControlChannel"); + hid_packet* hidp = (hid_packet*)_pData; - const u8* data = (const u8*)_pData; - // Dump raw data - { - INFO_LOG(WIIMOTE, "Wiimote_ControlChannel"); - std::string Temp = ArrayToString(data, 0, _Size); - DEBUG_LOG(WIIMOTE, " Data: %s", Temp.c_str()); - } + INFO_LOG(WIIMOTE, "Emu ControlChannel (type: 0x%02x, param: 0x%02x)", hidp->type, hidp->param); - 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"); - } + PanicAlert("HID_TYPE_HANDSHAKE - %s", (hidp->param == HID_PARAM_INPUT) ? "INPUT" : "OUPUT"); break; case HID_TYPE_SET_REPORT: if (hidp->param == HID_PARAM_INPUT) { - PanicAlert("HID_TYPE_SET_REPORT input"); + PanicAlert("HID_TYPE_SET_REPORT - INPUT"); } else { - HidOutputReport(_channelID, (wm_report*)hidp->data); - - // Return handshake + // AyuanX: My experiment shows Control Channel is never used + // In case it happens, we will send back a handshake which means report failed/rejected + // (TO_BE_VERIFIED) + // u8 handshake = 0; g_WiimoteInitialize.pWiimoteInput(_channelID, &handshake, 1); + + PanicAlert("HID_TYPE_DATA - OUTPUT: Ambiguous Control Channel Report!"); } break; case HID_TYPE_DATA: - PanicAlert("HID_TYPE_DATA %s", hidp->type, hidp->param == HID_PARAM_INPUT ? "input" : "output"); + PanicAlert("HID_TYPE_DATA - %s", (hidp->param == HID_PARAM_INPUT) ? "INPUT" : "OUTPUT"); break; default: @@ -693,9 +648,10 @@ void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) of times per second. */ void Update() { + if(g_ReportingAuto == false) + return; + readKeyboard(); - //LOG(WIIMOTE, "Wiimote_Update"); - //INFO_LOG(WIIMOTE, "Emu Update: %i", g_ReportingMode); // Check if the pad state should be updated if ((g_Config.Trigger.Type == g_Config.Trigger.TRIGGER || g_Config.Trigger.Type == g_Config.Trigger.ANALOG1 || g_Config.Trigger.Type == g_Config.Trigger.ANALOG2 @@ -712,17 +668,25 @@ void Update() { 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; + 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(); } + void readKeyboard() { #if defined(HAVE_X11) && HAVE_X11 diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp index e24bc357d9..5f60c794ba 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp @@ -65,74 +65,88 @@ namespace WiiMoteEmu 0x2 = Disable 0x6 = Enable */ -void HidOutputReport(u16 _channelID, wm_report* sr) { - INFO_LOG(WIIMOTE, "HidOutputReport (0x%02x)", sr->channel); - std::string Temp; +void HidOutputReport(u16 _channelID, wm_report* sr) +{ + INFO_LOG(WIIMOTE, "HidOutputReport (cid: 0x%02x, wm: 0x%02x)", _channelID, sr->wm); - switch(sr->channel) + switch(sr->wm) { - case WM_RUMBLE: + case WM_RUMBLE: // 0x10 // TODO: Implement rumble for real wiimotes 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 - if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) WmRequestStatus(_channelID, (wm_request_status*)sr->data); - //Temp = ArrayToString(sr->data, sizeof(wm_request_status), 0); - //DEBUG_LOG(WIIMOTE, "%s: InterruptChannel: %s", Tm().c_str(), Temp.c_str()); - break; - case WM_READ_DATA: // 0x17 - if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) WmReadData(_channelID, (wm_read_data*)sr->data); + + case WM_REPORT_MODE: // 0x12 + WmReportMode(_channelID, (wm_report_mode*)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 - WARN_LOG(WIIMOTE, " IR Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); - DEBUG_LOG(WIIMOTE, "IR Enable/Disable 0x%02x: 0x%02x", sr->channel, sr->data[0]); + // This enables or disables the IR lights, we update the global variable g_IR + // so that WmRequestStatus() knows about it + INFO_LOG(WIIMOTE, "WM IR Enable: 0x%02x", sr->data[0]); if(sr->data[0] == 0x02) g_IR = 0; else if(sr->data[0] == 0x06) g_IR = 1; break; + case WM_SPEAKER_ENABLE: // 0x14 + INFO_LOG(WIIMOTE, "WM Speaker Enable: 0x%02x", sr->data[0]); + if(sr->data[0] == 0x02) g_Speaker = 0; + else if(sr->data[0] == 0x06) g_Speaker = 1; + break; + + case WM_REQUEST_STATUS: // 0x15 + if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) + WmRequestStatus(_channelID, (wm_request_status*)sr->data); + break; + case WM_WRITE_DATA: // 0x16 WmWriteData(_channelID, (wm_write_data*)sr->data); break; - case WM_SPEAKER_ENABLE: // 0x14 - INFO_LOG(WIIMOTE, " WM Speaker Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); - //DEBUG_LOG(WIIMOTE, "Speaker Enable/Disable 0x%02x: 0x%02x", 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: // 0x19 - INFO_LOG(WIIMOTE, " WM Mute Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); - //DEBUG_LOG(WIIMOTE, "Speaker Mute/Unmute 0x%02x: 0x%02x", sr->channel, sr->data[0]); - if(sr->data[0] == 0x02) g_SpeakerVoice = 0; // g_SpeakerVoice - else if(sr->data[0] == 0x06) g_SpeakerVoice = 1; + case WM_READ_DATA: // 0x17 + if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) + WmReadData(_channelID, (wm_read_data*)sr->data); break; + case WM_WRITE_SPEAKER_DATA: // 0x18 break; + case WM_SPEAKER_MUTE: // 0x19 + INFO_LOG(WIIMOTE, "WM Mute Enable: 0x%02x", 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); + PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->wm); return; } + + // Send general feedback except the following types + // as these ones generate their own feedbacks + if ((sr->wm != WM_RUMBLE) + && (sr->wm != WM_READ_DATA) + && (sr->wm != WM_REQUEST_STATUS) + && (sr->wm != WM_WRITE_SPEAKER_DATA) + ) + { + WmSendAck(_channelID, sr->wm); + } } /* Generate the right header for wm reports. The returned values is the length of the header before the data begins. It's always two for all reports 0x20 - 0x22, 0x30 - 0x37 */ -int WriteWmReport(u8* dst, u8 channel) +int WriteWmReportHdr(u8* dst, u8 wm) { // Update the first byte to 0xa1 u32 Offset = 0; - hid_packet* pHidHeader = (hid_packet*)(dst + Offset); + hid_packet* pHidHeader = (hid_packet*)dst; Offset += sizeof(hid_packet); pHidHeader->type = HID_TYPE_DATA; pHidHeader->param = HID_PARAM_INPUT; @@ -140,59 +154,44 @@ int WriteWmReport(u8* dst, u8 channel) // Update the second byte to the current report type 0x20 - 0x22, 0x30 - 0x37 wm_report* pReport = (wm_report*)(dst + Offset); Offset += sizeof(wm_report); - pReport->channel = channel; + pReport->wm = wm; return Offset; } /* LED (blue lights) report. */ -void WmLeds(u16 _channelID, wm_leds* leds) { - INFO_LOG(WIIMOTE, " Set LEDs Leds: %x Rumble: %x", leds->leds, leds->rumble); +void WmLeds(u16 _channelID, wm_leds* leds) +{ + INFO_LOG(WIIMOTE, "Set LEDs: %x, Rumble: %x", leds->leds, leds->rumble); g_Leds = leds->leds; } -/* 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) +/* This will generate the 0x22 acknowledgement for most Input reports. + It has the form of "a1 22 00 00 _reportID 00". + The first two bytes are the core buttons data, + 00 00 means nothing is pressed. + The last byte is the success code 00. */ +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); + // Write DataFrame header + u32 Offset = WriteWmReportHdr(DataFrame, WM_ACK_DATA); wm_acknowledge* pData = (wm_acknowledge*)(DataFrame + Offset); - pData->Channel = WM_WRITE_DATA_REPLY; - pData->unk0 = 0; - pData->unk1 = 0; + pData->buttons = 0; pData->reportID = _reportID; pData->errorID = 0; Offset += sizeof(wm_acknowledge); - INFO_LOG(WIIMOTE, " WMSendAck()"); - INFO_LOG(WIIMOTE, " Report ID: %02x", _reportID); - //std::string Temp = ArrayToString(DataFrame, Offset, 0); - //LOGV(WIIMOTE, 2, " Data: %s", Temp.c_str()); - //DEBUG_LOG(WIIMOTE, "%s: WMSendAck: %s", Tm(true).c_str(), Temp.c_str()); - - /* Debug. Write the report for extension registry writes. - if((_reportID == 0x16 || _reportID == 0x17) && ((address >> 16) & 0xfe) == 0xa4) - { - DEBUG_LOG(WIIMOTE, "WMSendAck Report ID: %02x Encryption: %02x", _reportID, g_RegExt[0xf0]); - DEBUG_LOG(WIIMOTE, "Data: %s", Temp.c_str()); - }*/ + DEBUG_LOG(WIIMOTE, "WMSendAck"); + DEBUG_LOG(WIIMOTE, " Report ID: %02x", _reportID); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); // Debugging - ReadDebugging(true, DataFrame, Offset); + //ReadDebugging(true, DataFrame, Offset); } @@ -201,17 +200,14 @@ void WmReadData(u16 _channelID, wm_read_data* rd) { u32 address = convert24bit(rd->address); u16 size = convert16bit(rd->size); - std::string Temp; - INFO_LOG(WIIMOTE, "Read data Address space: %x", rd->space); - INFO_LOG(WIIMOTE, "Read data Address: 0x%06x", address); - INFO_LOG(WIIMOTE, "Read data Size: 0x%04x", size); - INFO_LOG(WIIMOTE, "Read data Rumble: %x", rd->rumble); - - //u32 _address = address; - std::string Tmp; // Debugging + + INFO_LOG(WIIMOTE, "Read data"); + DEBUG_LOG(WIIMOTE, " Read data Space: %x", rd->space); + DEBUG_LOG(WIIMOTE, " Read data Address: 0x%06x", address); + DEBUG_LOG(WIIMOTE, " Read data Size: 0x%04x", size); /* Now we determine what address space we are reading from. Space 0 is - Eeprom and space 1 and 2 is the registers. */ + Eeprom and space 1 and 2 are the registers. */ if(rd->space == WM_SPACE_EEPROM) { if (address + size > WIIMOTE_EEPROM_SIZE) @@ -219,7 +215,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd) PanicAlert("WmReadData: address + size out of bounds"); return; } - SendReadDataReply(_channelID, g_Eeprom + address, address, (u8)size); + SendReadDataReply(_channelID, g_Eeprom + address, address, (int)size); /*DEBUG_LOG(WIIMOTE, "Read RegEeprom: Size: %i, Address: %08x, Offset: %08x", size, address, (address & 0xffff));*/ } @@ -232,62 +228,38 @@ void WmReadData(u16 _channelID, wm_read_data* rd) case 0xA2: block = g_RegSpeaker; blockSize = WIIMOTE_REG_SPEAKER_SIZE; - INFO_LOG(WIIMOTE, " Case 0xa2: g_RegSpeaker"); - /*Tmp = ArrayToString(g_RegSpeaker, size, (address & 0xffff)); - //LOGV(WIIMOTE, 0, " Data: %s", Temp.c_str()); - DEBUG_LOG(WIIMOTE, "Read RegSpkr: Size %i Address %08x Offset %08x\nData %s", - size, address, (address & 0xffff), Tmp.c_str());*/ + DEBUG_LOG(WIIMOTE, " Case 0xa2: g_RegSpeaker"); break; case 0xA4: block = g_RegExt; blockSize = WIIMOTE_REG_EXT_SIZE; - INFO_LOG(WIIMOTE, " Case 0xa4: Read ExtReg"); - /*Tmp = ArrayToString(g_RegExt, size, (address & 0xffff), 40); - //LOGV(WIIMOTE, 0, " Data: %s", Temp.c_str()); - DEBUG_LOG(WIIMOTE, "Read RegExt: Size %i Address %08x Offset %08x\nData %s", - size, address, (address & 0xffff), Tmp.c_str());*/ + DEBUG_LOG(WIIMOTE, " Case 0xa4: ExtReg"); break; -// case 0xA6: -// block = g_RegMotionPlus; -// block[0xFC] = 0xA6; -// block[0xFD] = 0x20; -// block[0xFE] = 0x00; -// block[0xFF] = 0x05; -// blockSize = WIIMOTE_REG_EXT_SIZE; -// INFO_LOG(WIIMOTE, " Case 0xa6: MotionPlusReg [%x]", address); - /* - Tmp = ArrayToString(block, size, (address & 0xffff)); - //LOGV(WIIMOTE, 0, " Data: %s", Temp.c_str()); - INFO_LOG(WIIMOTE, "Read MotionPlusReg: Size %i Address %08x Offset %08x\nData %s", - size, address, (address & 0xffff), Tmp.c_str()); - */ -// break; +/* + case 0xA6: + block = g_RegMotionPlus; + block[0xFC] = 0xA6; + block[0xFD] = 0x20; + block[0xFE] = 0x00; + block[0xFF] = 0x05; + blockSize = WIIMOTE_REG_EXT_SIZE; + DEBUG_LOG(WIIMOTE, " Case 0xa6: MotionPlusReg [%x]", address); + break; +*/ case 0xB0: block = g_RegIr; blockSize = WIIMOTE_REG_IR_SIZE; - INFO_LOG(WIIMOTE, " Case: 0xb0 g_RegIr"); - /*Tmp = ArrayToString(g_RegIr, size, (address & 0xffff)); - //LOGV(WIIMOTE, 0, " Data: %s", Temp.c_str()); - DEBUG_LOG(WIIMOTE, "Read RegIR: Size %i Address %08x Offset %08x\nData %s", - size, address, (address & 0xffff), Tmp.c_str());*/ + DEBUG_LOG(WIIMOTE, " Case 0xb0: g_RegIr"); break; + default: ERROR_LOG(WIIMOTE, "WmReadData: bad register block!"); return; } - // Encrypt data that is read from the Wiimote Extension Register if(((address >> 16) & 0xfe) == 0xa4) { - /* Debugging - DEBUG_LOG(WIIMOTE, "WmReadData Address: %08x Offset: %08x Size: %i byte", - address, address & 0xffff, (u8)size); - // Debugging - u32 offset = address & 0xffff; - std::string Temp = ArrayToString(g_RegExt, size, offset); - DEBUG_LOG(WIIMOTE, "Unencrypted data:\n%s", Temp.c_str());*/ - // Check if encrypted reads is on if(g_RegExt[0xf0] == 0xaa) { @@ -300,16 +272,12 @@ void WmReadData(u16 _channelID, wm_read_data* rd) // Update the block that SendReadDataReply will eventually send to the Wii block = g_RegExtTmp; - - /* Debugging: Show the encrypted data - std::string Temp = ArrayToString(g_RegExtTmp, size, offset); - DEBUG_LOG(WIIMOTE, "Encrypted data:\n%s", Temp.c_str());*/ } } - //------------- address &= 0xFFFF; - if(address + size > blockSize) { + if(address + size > blockSize) + { PanicAlert("WmReadData: address + size out of bounds! [%d %d %d]", address, size, blockSize); return; } @@ -321,7 +289,6 @@ void WmReadData(u16 _channelID, wm_read_data* rd) { PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x)!", size, rd->space); } - } /* Here we produce the actual 0x21 Input report that we send to the Wii. The @@ -331,11 +298,11 @@ void WmReadData(u16 _channelID, wm_read_data* rd) 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. - _Base: The data beginning at _Base[0] _Address: The starting address inside - the registry, this is used to check for out of bounds reading _Size: The - total size to send - */ -void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size) + _Base: The data beginning at _Base[0] + _Address: The starting address inside the registry, this is used to check for out of bounds reading + _Size: The total size to send +*/ +void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, int _Size) { int dataOffset = 0; const u8* data = (const u8*)_Base; @@ -344,29 +311,27 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size) { u8 DataFrame[1024]; // Write the first two bytes to DataFrame - u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY); + u32 Offset = WriteWmReportHdr(DataFrame, WM_READ_DATA_REPLY); // Limit the size to 16 bytes - int copySize = _Size; - if (copySize > 16) copySize = 16; + int copySize = (_Size > 16) ? 16 : _Size; + // AyuanX: the MTU is 640B though... what a waste! - // Connect pReply->data to the almost empty DataFrame wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset); - // Now we increase Offset to the final size of the report Offset += sizeof(wm_read_data_reply); - // Add header values + pReply->buttons = 0; pReply->error = 0; // 0x1 means two bytes, 0xf means 16 bytes - pReply->size = (copySize - 1) & 0xf; + pReply->size = copySize - 1; pReply->address = Common::swap16(_Address + dataOffset); + // Clear the mem first + memset(pReply->data, 0, 16); + // Write a pice of _Base to DataFrame memcpy(pReply->data, data + dataOffset, copySize); - // Check if we have less than 16 bytes left to send - if(copySize < 16) memset(pReply->data + copySize, 0, 16 - copySize); - // Update DataOffset for the next loop dataOffset += copySize; @@ -382,31 +347,25 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size) } // Logging - INFO_LOG(WIIMOTE, " SendReadDataReply()"); - DEBUG_LOG(WIIMOTE, " Buttons: 0x%04x", pReply->buttons); - DEBUG_LOG(WIIMOTE, " Error: 0x%x", pReply->error); - DEBUG_LOG(WIIMOTE, " Size: 0x%x", pReply->size); - DEBUG_LOG(WIIMOTE, " Address: 0x%04x", pReply->address); - /*DEBUG_LOG(WIIMOTE, " SendReadDataReply()"); - DEBUG_LOG(WIIMOTE, " Offset: 0x%x", Offset); - DEBUG_LOG(WIIMOTE, " dataOffset: 0x%x", dataOffset); - DEBUG_LOG(WIIMOTE, " copySize: 0x%x", copySize); - DEBUG_LOG(WIIMOTE, " Size: 0x%x", pReply->size); - DEBUG_LOG(WIIMOTE, " Address: 0x%04x", Common::swap16(pReply->address));*/ - //std::string Temp = ArrayToString(data, 0x40); - //DEBUG_LOG(WIIMOTE, "Data:\n%s", Temp.c_str()); + DEBUG_LOG(WIIMOTE, "SendReadDataReply"); + DEBUG_LOG(WIIMOTE, " Buttons: 0x%04x", pReply->buttons); + DEBUG_LOG(WIIMOTE, " Error: 0x%x", pReply->error); + DEBUG_LOG(WIIMOTE, " Size: 0x%x", pReply->size); + DEBUG_LOG(WIIMOTE, " Address: 0x%04x", pReply->address); + +#if defined(_DEBUG) || defined(DEBUGFAST) + std::string Temp = ArrayToString(DataFrame, Offset); + ERROR_LOG(WIIMOTE, "Data: %s", Temp.c_str()); +#endif // Send a piece g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + // Update the size that is left _Size -= copySize; // Debugging - ReadDebugging(true, DataFrame, Offset); - } - - if (_Size != 0) { - PanicAlert("WiiMote-Plugin: SendReadDataReply() failed"); + //ReadDebugging(true, DataFrame, Offset); } } @@ -414,14 +373,12 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size) /* Write data to Wiimote and Extensions registers. */ void WmWriteData(u16 _channelID, wm_write_data* wd) { - u32 address = convert24bit(wd->address); - INFO_LOG(WIIMOTE, "Write data"); - DEBUG_LOG(WIIMOTE, " Address space: %x", wd->space); - DEBUG_LOG(WIIMOTE, " Address: 0x%06x", address); - DEBUG_LOG(WIIMOTE, " Size: 0x%02x", wd->size); - DEBUG_LOG(WIIMOTE, " Rumble: %x", wd->rumble); - //std::string Temp = ArrayToString(wd->data, wd->size); - //LOGV(WIIMOTE, 0, " Data: %s", Temp.c_str()); + u32 address = convert24bit(wd->address); + + INFO_LOG(WIIMOTE, "Write data"); + DEBUG_LOG(WIIMOTE, " Space: %x", wd->space); + DEBUG_LOG(WIIMOTE, " Address: 0x%06x", address); + DEBUG_LOG(WIIMOTE, " Size: 0x%02x", wd->size); // Write to EEPROM if(wd->size <= 16 && wd->space == WM_SPACE_EEPROM) @@ -432,8 +389,6 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) return; } memcpy(g_Eeprom + address, wd->data, wd->size); - /*DEBUG_LOG(WIIMOTE, "Write RegEeprom: Size: %i, Address: %08x, Offset: %08x", - wd->size, address, (address & 0xffff));*/ } // Write to registers else if(wd->size <= 16 && (wd->space == WM_SPACE_REGS1 || wd->space == WM_SPACE_REGS2)) @@ -445,35 +400,26 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) case 0xA2: block = g_RegSpeaker; blockSize = WIIMOTE_REG_SPEAKER_SIZE; - INFO_LOG(WIIMOTE, " Case 0xa2: RegSpeaker"); - /*DEBUG_LOG(WIIMOTE, "Write RegSpeaker: Size: %i, Address: %08x, Offset: %08x", - wd->size, address, (address & 0xffff)); - DEBUG_LOG(WIIMOTE, "Data: %s", Temp.c_str());*/ + DEBUG_LOG(WIIMOTE, " Case 0xa2: RegSpeaker"); break; case 0xA4: block = g_RegExt; // Extension Controller register blockSize = WIIMOTE_REG_EXT_SIZE; - INFO_LOG(WIIMOTE, " Case 0xa4: ExtReg"); - /*DEBUG_LOG(WIIMOTE, "Write RegExt Size: %i Address: %08x Offset: %08x ", - wd->size, address, (address & 0xffff)); - DEBUG_LOG(WIIMOTE, "Data: %s", Temp.c_str());*/ + DEBUG_LOG(WIIMOTE, " Case 0xa4: ExtReg"); break; -// case 0xA6: -// block = g_RegMotionPlus; -// blockSize = WIIMOTE_REG_EXT_SIZE; -// INFO_LOG(WIIMOTE, " Case 0xa6: MotionPlusReg [%x] Write ", address); - /*INFO_LOG(WIIMOTE, "Write MotionPlusReg Size: %i Address: %08x Offset: %08x ", - wd->size, address, (address & 0xffff)); -// INFO_LOG(WIIMOTE, "Data: %s", Temp.c_str());*/ -// break; +/* + case 0xA6: + block = g_RegMotionPlus; + blockSize = WIIMOTE_REG_EXT_SIZE; + DEBUG_LOG(WIIMOTE, " Case 0xa6: MotionPlusReg [%x]", address); + break; +*/ case 0xB0: block = g_RegIr; blockSize = WIIMOTE_REG_IR_SIZE; - INFO_LOG(WIIMOTE, " Case 0xb0: RegIr"); - /*DEBUG_LOG(WIIMOTE, "Write RegIR Size: %i Address: %08x Offset: %08x ", - wd->size, address, (address & 0xffff)); - DEBUG_LOG(WIIMOTE, "Data: %s", Temp.c_str());*/ + INFO_LOG(WIIMOTE, " Case 0xb0: RegIr"); break; + default: ERROR_LOG(WIIMOTE, "WmWriteData: bad register block!"); PanicAlert("WmWriteData: bad register block!"); @@ -492,66 +438,57 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) // 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. - DEBUG_LOG(WIIMOTE, "Data: %s", Temp.c_str()); - DEBUG_LOG(WIIMOTE, "Current address: %08x", 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 { + } + 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); } + /* Here we produce a 0x20 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, int Extension) { - INFO_LOG(WIIMOTE, " Request Status: Rumble: %x Channel: %04x", - rs->rumble, _channelID); - - //SendStatusReport(); u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_STATUS_REPORT); + u32 Offset = WriteWmReportHdr(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 + pStatus->battery_low = 0; // battery is okay + pStatus->battery = 0x5f; // fully charged /* 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 // Check if we have a specific order about the extension status if (Extension == -1) { - // Read config value for this one + // Read config value for the first time if(g_Config.iExtensionConnected == EXT_NONE) pStatus->extension = 0; else @@ -565,15 +502,14 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension) pStatus->extension = 0; } - INFO_LOG(WIIMOTE, " Extension: %x", pStatus->extension); - INFO_LOG(WIIMOTE, " SendStatusReport() Flags: 0x%02x Battery: %d" - ,pStatus->padding1[2], pStatus->battery); + INFO_LOG(WIIMOTE, "Request Status"); + DEBUG_LOG(WIIMOTE, " Extension: %x", pStatus->extension); + DEBUG_LOG(WIIMOTE, " Flags: 0x%02x", pStatus->padding1[2]); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); - // Debugging - ReadDebugging(true, DataFrame, Offset); + //ReadDebugging(true, DataFrame, Offset); } } // WiiMoteEmu diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h index a83f689084..9a4b4f8655 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h @@ -42,17 +42,17 @@ void WmReadData(u16 _channelID, wm_read_data* rd); void WmWriteData(u16 _channelID, wm_write_data* wd); void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension = -1); void WmRequestStatus_(u16 _channelID, int a); -void WmDataReporting(u16 _channelID, wm_data_reporting* dr); +void WmReportMode(u16 _channelID, wm_report_mode* dr); -void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size); void SendReportCoreAccel(u16 _channelID); void SendReportCoreAccelIr12(u16 _channelID); void SendReportCore(u16 _channelID); void SendReportCoreAccelExt16(u16 _channelID); void SendReportCoreAccelIr10Ext(u16 _channelID); -int WriteWmReport(u8* dst, u8 channel); -void WmSendAck(u16 _channelID, u8 _reportID, u32 address); +int WriteWmReportHdr(u8* dst, u8 wm); +void WmSendAck(u16 _channelID, u8 _reportID); +void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, int _Size); void FillReportAcc(wm_accel& _acc); void FillReportInfo(wm_core& _core); diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index 015d639abd..1efb8dbcef 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -343,10 +343,6 @@ int IsKey(int Key) // Wiimote core buttons void FillReportInfo(wm_core& _core) { - /* This has to be filled with zeroes (and not for example 0xff) because when no buttons are pressed the - value is 00 00 */ - memset(&_core, 0x00, sizeof(wm_core)); - // Check that Dolphin is in focus if (!IsFocus()) return; @@ -436,7 +432,7 @@ void SingleShake(u8 &_y, u8 &_z, int i) /* Tilting Wiimote with gamepad. We can guess that the game will calculate a Wiimote pitch and use it as a measure of the tilting of the Wiimote. We are - interested in this tilting range 90° to -90° */ + interested in this tilting range 90?to -90?*/ void TiltWiimoteGamepad(float &Roll, float &Pitch) { // Return if we have no pads @@ -460,7 +456,7 @@ void TiltWiimoteGamepad(float &Roll, float &Pitch) float Tl = (float)_Tl; float Tr = (float)_Tr; - // Save the Range in degrees, 45° and 90° are good values in some games + // Save the Range in degrees, 45?and 90?are good values in some games float RollRange = (float)g_Config.Trigger.Range.Roll; float PitchRange = (float)g_Config.Trigger.Range.Pitch; diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index 1f9dae90ef..86f7116f81 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -269,10 +269,9 @@ void Shutdown(void) void DoState(unsigned char **ptr, int mode) { PointerWrap p(ptr, mode); - - return; // TODO: Shorten the list + //p.Do(g_EmulatorRunning); //p.Do(g_ISOId); p.Do(g_FrameOpen); @@ -280,16 +279,18 @@ void DoState(unsigned char **ptr, int mode) p.Do(g_RealWiiMoteInitialized); p.Do(g_EmulatedWiiMoteInitialized); p.Do(g_WiimoteUnexpectedDisconnect); - p.Do(g_UpdateCounter); - p.Do(g_UpdateTime); - p.Do(g_UpdateRate); - p.Do(g_UpdateWriteScreen); - p.Do(g_UpdateTimeList); + //p.Do(g_UpdateCounter); + //p.Do(g_UpdateTime); + //p.Do(g_UpdateRate); + //p.Do(g_UpdateWriteScreen); + //p.Do(g_UpdateTimeList); #if HAVE_WIIUSE WiiMoteReal::DoState(p); #endif WiiMoteEmu::DoState(p); + + return; } @@ -305,7 +306,7 @@ void Wiimote_InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) // Debugging { - DEBUG_LOG(WIIMOTE, "Wiimote_Input"); + DEBUG_LOG(WIIMOTE, "Wiimote_InterruptChannel"); DEBUG_LOG(WIIMOTE, " Channel ID: %04x", _channelID); std::string Temp = ArrayToString(data, _Size); DEBUG_LOG(WIIMOTE, " Data: %s", Temp.c_str()); @@ -333,6 +334,7 @@ void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _Size) DEBUG_LOG(WIIMOTE, "Wiimote Disconnected"); g_EmulatorRunning = false; g_WiimoteUnexpectedDisconnect = true; + #if defined(HAVE_WX) && HAVE_WX if (m_BasicConfigFrame) m_BasicConfigFrame->UpdateGUI(); #endif @@ -344,7 +346,6 @@ void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _Size) DEBUG_LOG(WIIMOTE, "Wiimote_ControlChannel"); std::string Temp = ArrayToString(data, _Size); DEBUG_LOG(WIIMOTE, " Data: %s", Temp.c_str()); - //PanicAlert("Wiimote_ControlChannel"); } //if (!g_RealWiiMotePresent) @@ -372,8 +373,8 @@ void Wiimote_Update() } g_UpdateWriteScreen++; } - #endif + // This functions will send: // Emulated Wiimote: Only data reports 0x30-0x37 // Real Wiimote: Both data reports 0x30-0x37 and all other read reports @@ -638,7 +639,7 @@ void ReadDebugging(bool Emu, const void* _pData, int Size) } break; - case WM_WRITE_DATA_REPLY: // 0x22 + case WM_ACK_DATA: // 0x22 size = sizeof(wm_acknowledge) - 1; Name = "REPLY"; break; @@ -820,7 +821,6 @@ void ReadDebugging(bool Emu, const void* _pData, int Size) void InterruptDebugging(bool Emu, const void* _pData) { - // const u8* data = (const u8*)_pData; std::string Name; @@ -840,9 +840,9 @@ void InterruptDebugging(bool Emu, const void* _pData) size = sizeof(wm_leds); if (g_DebugComm) Name.append("WM_LEDS"); break; - case WM_DATA_REPORTING: // 0x12 - size = sizeof(wm_data_reporting); - if (g_DebugComm) Name.append("WM_DATA_REPORTING"); + case WM_REPORT_MODE: // 0x12 + size = sizeof(wm_report_mode); + if (g_DebugComm) Name.append("WM_REPORT_MODE"); break; case WM_REQUEST_STATUS: // 0x15 size = sizeof(wm_request_status); diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h index f209891d2c..f12c8bd991 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h @@ -45,7 +45,7 @@ struct hid_packet { //source: http://wiibrew.org/wiki/Wiimote struct wm_report { - u8 channel; + u8 wm; u8 data[0]; }; @@ -57,8 +57,8 @@ struct wm_leds { u8 leds : 4; }; -#define WM_DATA_REPORTING 0x12 -struct wm_data_reporting { +#define WM_REPORT_MODE 0x12 +struct wm_report_mode { u8 rumble : 1; u8 continuous : 1; u8 all_the_time : 1; @@ -98,12 +98,10 @@ struct wm_write_data u8 data[16]; }; -#define WM_WRITE_DATA_REPLY 0x22 //empty, afaik +#define WM_ACK_DATA 0x22 struct wm_acknowledge { - u8 Channel; - u8 unk0; // Core buttons state (wm_core), can be zero - u8 unk1; + u16 buttons; u8 reportID; u8 errorID; };