My first commit :)
Fixed more memory leaks when doing state load. Now all file devices(handles) are stored in state, and this will fix some crash after loading state. Warning: Do NOT Save/Load state before game title is shown and controllable, or else you will get a corrupt state. If you encounter "Emu WiiMote Desync" frequently, please report the condition (PS: To recover from wiimote desync, just load a saved state) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4608 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
6a46befc2a
commit
29774c35e8
|
@ -74,13 +74,48 @@ public:
|
|||
(*ptr) += size;
|
||||
}
|
||||
|
||||
// Store maps to file. Very useful.
|
||||
template<class T>
|
||||
void Do(std::map<unsigned int, T> &x) {
|
||||
void Do(std::map<unsigned int, T> &x)
|
||||
{
|
||||
// TODO
|
||||
PanicAlert("Do(map<>) does not yet work.");
|
||||
}
|
||||
|
||||
void Do(std::map<unsigned int, std::string> &x)
|
||||
{
|
||||
unsigned int number = (unsigned int)x.size();
|
||||
Do(number);
|
||||
switch (mode) {
|
||||
case MODE_READ:
|
||||
{
|
||||
x.clear();
|
||||
while (number > 0)
|
||||
{
|
||||
unsigned int first;
|
||||
Do(first);
|
||||
std::string second;
|
||||
Do(second);
|
||||
x[first] = second;
|
||||
--number;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MODE_WRITE:
|
||||
case MODE_MEASURE:
|
||||
{
|
||||
std::map<unsigned int, std::string>::iterator itr = x.begin();
|
||||
while (number > 0)
|
||||
{
|
||||
Do(itr->first);
|
||||
Do(itr->second);
|
||||
--number;
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Store vectors.
|
||||
template<class T>
|
||||
void Do(std::vector<T> &x) {
|
||||
|
|
|
@ -74,6 +74,9 @@ typedef std::map<u32, IWII_IPC_HLE_Device*> TDeviceMap;
|
|||
TDeviceMap g_DeviceMap;
|
||||
|
||||
// STATE_TO_SAVE
|
||||
typedef std::map<u32, std::string> TFileNameMap;
|
||||
TFileNameMap g_FileNameMap;
|
||||
|
||||
u32 g_LastDeviceID = 0x13370000;
|
||||
std::string g_DefaultContentFile;
|
||||
|
||||
|
@ -85,16 +88,15 @@ 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())
|
||||
{
|
||||
if (itr->second)
|
||||
if(itr->second)
|
||||
delete itr->second;
|
||||
++itr;
|
||||
}
|
||||
g_DeviceMap.clear();
|
||||
g_FileNameMap.clear();
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
|
@ -130,8 +132,6 @@ IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID)
|
|||
return g_DeviceMap[_ID];
|
||||
|
||||
// ID = 0 just means it hasn't been created yet
|
||||
_dbg_assert_msg_(WII_IPC, _ID == 0, "IOP tries to access an unknown device 0x%x", _ID);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ IWII_IPC_HLE_Device* CreateDevice(u32 _DeviceID, const std::string& _rDeviceName
|
|||
|
||||
|
||||
// Let the game read the setting.txt file
|
||||
void CopySettingsFile(std::string DeviceName)
|
||||
void CopySettingsFile(std::string& DeviceName)
|
||||
{
|
||||
std::string Source = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP;
|
||||
if(Core::GetStartupParameter().bNTSC)
|
||||
|
@ -259,14 +259,43 @@ void CopySettingsFile(std::string DeviceName)
|
|||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(g_LastDeviceID);
|
||||
//p.Do(g_DefaultContentFile);
|
||||
p.Do(g_DefaultContentFile);
|
||||
|
||||
// AyuanX: I think maybe we really should create devices statically at initilization
|
||||
// AyuanX: I think we should seperate hardware from file handle
|
||||
// and create hardware at initilization instead of runtime allocation when first accessed
|
||||
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!");
|
||||
PanicAlert("WII_IPC_HLE: Save/Load State failed, Device /dev/usb/oh1/57e/305 doesn't exist!");
|
||||
|
||||
// Let's just hope hardware device IDs are constant throughout the game
|
||||
// If there is any ID overlapping between hardware IDs and file IDs, we are dead
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
{
|
||||
// Delete file Handles
|
||||
TFileNameMap::const_iterator itr = g_FileNameMap.begin();
|
||||
while (itr != g_FileNameMap.end())
|
||||
{
|
||||
delete g_DeviceMap[itr->first];
|
||||
g_DeviceMap.erase(itr->first);
|
||||
++itr;
|
||||
}
|
||||
// Load file names
|
||||
p.Do(g_FileNameMap);
|
||||
// Rebuild file handles
|
||||
itr = g_FileNameMap.begin();
|
||||
while (itr != g_FileNameMap.end())
|
||||
{
|
||||
g_DeviceMap[itr->first] = new CWII_IPC_HLE_Device_FileIO(itr->first, itr->second);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p.Do(g_FileNameMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ExecuteCommand(u32 _Address)
|
||||
|
@ -307,15 +336,16 @@ void ExecuteCommand(u32 _Address)
|
|||
g_LastDeviceID++;
|
||||
|
||||
CmdSuccess = pDevice->Open(_Address, Mode);
|
||||
if(pDevice->GetDeviceName().find("/dev/") == std::string::npos
|
||||
|| pDevice->GetDeviceName().c_str() == std::string("/dev/fs"))
|
||||
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, CmdSuccess=%i)",
|
||||
g_FileNameMap[CurrentDeviceID] = DeviceName;
|
||||
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, DeviceID=%08x, Mode=%i, CmdSuccess=%i)",
|
||||
pDevice->GetDeviceName().c_str(), CurrentDeviceID, Mode, (int)CmdSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_LOG(WII_IPC_HLE, "IOP: Open (Device=%s, DeviceID=%08x, Mode=%i)",
|
||||
INFO_LOG(WII_IPC_HLE, "IOP: Open Device (Device=%s, DeviceID=%08x, Mode=%i)",
|
||||
pDevice->GetDeviceName().c_str(), CurrentDeviceID, Mode);
|
||||
}
|
||||
}
|
||||
|
@ -438,7 +468,10 @@ void ExecuteCommand(u32 _Address)
|
|||
ERROR_LOG(WII_IPC_HLE, "IOP: Reply to unknown device ID (DeviceID=%i)", DeviceID);
|
||||
|
||||
if (ClosedDeviceID > 0 && (ClosedDeviceID == DeviceID))
|
||||
{
|
||||
DeleteDeviceByID(DeviceID);
|
||||
g_FileNameMap.erase(DeviceID);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "ChunkFile.h"
|
||||
|
||||
class IWII_IPC_HLE_Device;
|
||||
|
||||
namespace WII_IPC_HLE_Interface
|
||||
{
|
||||
// Init
|
||||
|
@ -31,12 +33,24 @@ void Shutdown();
|
|||
// Reset
|
||||
void Reset();
|
||||
|
||||
void DeleteDeviceByID(u32 ID);
|
||||
|
||||
u32 GetDeviceIDByName(const std::string& _rDeviceName);
|
||||
|
||||
IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID);
|
||||
|
||||
void DeleteDeviceByID(u32 _ID);
|
||||
|
||||
IWII_IPC_HLE_Device* CreateDevice(u32 _DeviceID, const std::string& _rDeviceName);
|
||||
|
||||
// Do State
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
// Set default content file
|
||||
void SetDefaultContentFile(const std::string& _rFilename);
|
||||
|
||||
void CopySettingsFile(std::string& DeviceName);
|
||||
|
||||
// Update
|
||||
void Update();
|
||||
|
||||
|
|
|
@ -411,6 +411,14 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
|
|||
ERROR_LOG(WII_IPC_DVD, "DVDLowAudioBufferConfig");
|
||||
break;
|
||||
|
||||
// New Super Mario Bros.Wii sends these cmds
|
||||
// but it seems we don't need to implement anything
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
WARN_LOG(WII_IPC_DVD, "unimplemented cmd 0x%08x (Buffer 0x%08x, 0x%x)",
|
||||
Command, _BufferOut, _BufferOutSize);
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(WII_IPC_DVD, "unknown cmd 0x%08x (Buffer 0x%08x, 0x%x)",
|
||||
Command, _BufferOut, _BufferOutSize);
|
||||
|
|
|
@ -38,8 +38,9 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De
|
|||
, m_HostNumACLPackets(0)
|
||||
, m_HostNumSCOPackets(0)
|
||||
, m_HCIBuffer(NULL)
|
||||
, m_HCIPool(0)
|
||||
, m_ACLBuffer(NULL)
|
||||
, m_ACLFrame(0)
|
||||
, m_ACLPool(0)
|
||||
, m_LastCmd(NULL)
|
||||
, m_PacketCount(0)
|
||||
{
|
||||
|
@ -63,7 +64,9 @@ 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()
|
||||
{}
|
||||
{
|
||||
m_WiiMotes.clear();
|
||||
}
|
||||
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p)
|
||||
{
|
||||
|
@ -71,8 +74,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p)
|
|||
p.Do(m_PacketCount);
|
||||
p.Do(m_CtrlSetup);
|
||||
p.Do(m_HCIBuffer);
|
||||
p.Do(m_HCIPool);
|
||||
p.Do(m_ACLBuffer);
|
||||
p.Do(m_ACLFrame);
|
||||
p.Do(m_ACLPool);
|
||||
}
|
||||
|
||||
// ===================================================
|
||||
|
@ -138,7 +142,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress)
|
|||
// check termination
|
||||
_dbg_assert_msg_(WII_IPC_WIIMOTE, *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[5].m_Address) == 0,
|
||||
"WIIMOTE: Termination != 0");
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
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);
|
||||
|
@ -147,6 +151,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress)
|
|||
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);
|
||||
#endif
|
||||
|
||||
ExecuteHCICommandMessage(m_CtrlSetup);
|
||||
// Replies are generated inside
|
||||
|
@ -177,9 +182,9 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress)
|
|||
SendToDevice(pACLHeader->ConnectionHandle, Memory::GetPointer(BulkBuffer.m_buffer + 4), pACLHeader->Size);
|
||||
m_PacketCount++;
|
||||
|
||||
// If ACLFrame is not used, we can send a reply immediately
|
||||
// If ACLPool is not used, we can send a reply immediately
|
||||
// or else we have to delay this reply
|
||||
if (m_ACLFrame.m_number == 0)
|
||||
if (m_ACLPool.m_number == 0)
|
||||
_SendReply = true;
|
||||
}
|
||||
break;
|
||||
|
@ -279,10 +284,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8
|
|||
// 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
|
||||
// But...the only exception comes from the Wiimote_Plugin
|
||||
//
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
||||
{
|
||||
|
@ -308,48 +312,49 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u
|
|||
// Invalidate ACL buffer
|
||||
m_ACLBuffer.m_address = NULL;
|
||||
m_ACLBuffer.m_buffer = NULL;
|
||||
m_ACLFrame.m_number = 0;
|
||||
}
|
||||
else if ((sizeof(UACLHeader) + _Size) > 64 )
|
||||
{
|
||||
ERROR_LOG(WII_IPC_HLE, "ACL Packet size is too big! (>64B)");
|
||||
PanicAlert("WII_IPC_HLE: ACL Packet size is too big! (>64B)");
|
||||
}
|
||||
else if (m_ACLPool.m_number >= 16)
|
||||
{
|
||||
ERROR_LOG(WII_IPC_HLE, "ACL Pool is full, something must be wrong!");
|
||||
PanicAlert("WII_IPC_HLE: ACL Pool is full, something must be wrong!");
|
||||
}
|
||||
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
|
||||
UACLHeader* pHeader = (UACLHeader*)(m_ACLPool.m_data + m_ACLPool.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!");
|
||||
}
|
||||
m_ACLPool.m_number++;
|
||||
}
|
||||
}
|
||||
|
||||
// AyuanX: this ugly function is only useful when there are
|
||||
// multiple L2CAP packets come from WiiMote_Plugin in one cycle
|
||||
// The normal hardware behavior is like this:
|
||||
// e.g. if you have 3 packets to send you have to send them one by one in 3 cycles
|
||||
// and this is the mechanism how our IPC works
|
||||
// but current implementation of WiiMote_Plugin doesn't comply with this rule
|
||||
// It acts like sending all the 3 packets in one cycle and idling around in the other two cycles
|
||||
// that's why we need this contingent ACL pool
|
||||
//
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeACLFrame()
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeACLPool()
|
||||
{
|
||||
if(m_ACLBuffer.m_address == NULL)
|
||||
return;
|
||||
|
||||
INFO_LOG(WII_IPC_WIIMOTE, "Purging ACL Frame: 0x%08x ....", m_ACLBuffer.m_address);
|
||||
INFO_LOG(WII_IPC_WIIMOTE, "Purging ACL Pool: 0x%08x ....", m_ACLBuffer.m_address);
|
||||
|
||||
if(m_ACLFrame.m_number > 0)
|
||||
if(m_ACLPool.m_number > 0)
|
||||
{
|
||||
m_ACLFrame.m_number--;
|
||||
m_ACLPool.m_number--;
|
||||
// Fill the buffer
|
||||
u8* _Address = m_ACLFrame.m_data + m_ACLFrame.m_number * 64;
|
||||
u8* _Address = m_ACLPool.m_data + m_ACLPool.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);
|
||||
|
@ -366,6 +371,15 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeACLFrame()
|
|||
// ----------------
|
||||
u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||
{
|
||||
// Check if HCI Pool is not purged
|
||||
if (m_HCIPool.m_number > 0)
|
||||
{
|
||||
PurgeHCIPool();
|
||||
if (m_HCIPool.m_number == 0)
|
||||
WII_IPCInterface::EnqReply(m_CtrlSetup.m_Address);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if last command needs more work
|
||||
if (m_HCIBuffer.m_address && m_LastCmd)
|
||||
{
|
||||
|
@ -373,11 +387,11 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
return true;
|
||||
}
|
||||
|
||||
// Check if temp ACL frame is not purged
|
||||
if (m_ACLFrame.m_number > 0)
|
||||
// Check if ACL Pool is not purged
|
||||
if (m_ACLPool.m_number > 0)
|
||||
{
|
||||
PurgeACLFrame();
|
||||
if (m_ACLFrame.m_number == 0)
|
||||
PurgeACLPool();
|
||||
if (m_ACLPool.m_number == 0)
|
||||
WII_IPCInterface::EnqReply(m_CtrlSetup.m_Address);
|
||||
return true;
|
||||
}
|
||||
|
@ -427,14 +441,15 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// AyuanX: This event should be sent periodically after ACL connection is accepted
|
||||
// or CPU will disconnect WiiMote automatically
|
||||
// but don't send 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())
|
||||
if (m_HCIBuffer.m_address && !WII_IPCInterface::GetAddress() && m_WiiMotes[0].IsConnected())
|
||||
{
|
||||
FreqDividerSync++;
|
||||
if ((m_PacketCount >0) || (FreqDividerSync > 15)) // Feel free to tweak it
|
||||
if ((m_PacketCount > 0) || (FreqDividerSync > 30)) // Feel free to tweak it
|
||||
{
|
||||
FreqDividerSync = 0;
|
||||
SendEventNumberOfCompletedPackets(m_WiiMotes[0].GetConnectionHandle(), m_PacketCount);
|
||||
|
@ -453,7 +468,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
if (m_ACLBuffer.m_address && !WII_IPCInterface::GetAddress() && !m_LastCmd && m_WiiMotes[0].IsLinked())
|
||||
{
|
||||
FreqDividerMote++;
|
||||
if(FreqDividerMote > 100) // Feel free to tweak it
|
||||
if(FreqDividerMote > 99) // Feel free to tweak it
|
||||
{
|
||||
FreqDividerMote = 0;
|
||||
CPluginManager::GetInstance().GetWiimote(0)->Wiimote_Update();
|
||||
|
@ -474,6 +489,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
|
||||
// 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)
|
||||
{
|
||||
if (m_HCIBuffer.m_address != NULL)
|
||||
|
@ -491,16 +507,54 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
|
|||
// Invalidate HCI buffer
|
||||
m_HCIBuffer.m_address = NULL;
|
||||
m_HCIBuffer.m_buffer = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
else if (_event.m_size > 64)
|
||||
{
|
||||
ERROR_LOG(WII_IPC_HLE, "HCI Packet size too big! (>64B)");
|
||||
PanicAlert("WII_IPC_HLE: HCI Packet size too big! (>64B)");
|
||||
}
|
||||
else if (m_HCIPool.m_number >= 16)
|
||||
{
|
||||
ERROR_LOG(WII_IPC_HLE, "HCI Pool is full, something must be wrong!");
|
||||
PanicAlert("WII_IPC_HLE: HCI Pool is full, something must be wrong!");
|
||||
}
|
||||
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!");
|
||||
memcpy(m_HCIPool.m_data + m_HCIPool.m_number * 64, _event.m_buffer, _event.m_size);
|
||||
// HCI Packet doesn't contain size info inside, so we have to store it somewhere
|
||||
m_HCIPool.m_size[m_HCIPool.m_number] = _event.m_size;
|
||||
m_HCIPool.m_number++;
|
||||
}
|
||||
}
|
||||
|
||||
// Generally, CPU should send us a valid HCI buffer before issuing any HCI command
|
||||
// but since we don't know the exact frequency at which IPC should be running
|
||||
// so when IPC is running too fast that CPU can't catch up
|
||||
// then CPU(actually it is the usb driver) sometimes throws out a command before sending us a HCI buffer
|
||||
// So I put this contingent HCI Pool here until we figure out the true reason
|
||||
//
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeHCIPool()
|
||||
{
|
||||
if(m_HCIBuffer.m_address == NULL)
|
||||
return;
|
||||
|
||||
INFO_LOG(WII_IPC_WIIMOTE, "Purging HCI Pool: 0x%08x ....", m_HCIBuffer.m_address);
|
||||
|
||||
if(m_HCIPool.m_number > 0)
|
||||
{
|
||||
m_HCIPool.m_number--;
|
||||
// Fill the buffer
|
||||
u8* _Address = m_HCIPool.m_data + m_HCIPool.m_number * 64;
|
||||
memcpy(Memory::GetPointer(m_HCIBuffer.m_buffer), _Address, 64);
|
||||
// Write the packet size as return value
|
||||
Memory::Write_U32(m_HCIPool.m_size[m_HCIPool.m_number], m_HCIBuffer.m_address + 0x4);
|
||||
// Send a reply to indicate ACL buffer is sent
|
||||
WII_IPCInterface::EnqReply(m_HCIBuffer.m_address);
|
||||
// Invalidate ACL buffer
|
||||
m_HCIBuffer.m_address = NULL;
|
||||
m_HCIBuffer.m_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventCommandStatus(u16 _Opcode)
|
||||
{
|
||||
|
@ -744,7 +798,10 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventLinkKeyNotification(const CWI
|
|||
DEBUG_LOG(WII_IPC_WIIMOTE, " bd: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
pEventLinkKey->bdaddr.b[0], pEventLinkKey->bdaddr.b[1], pEventLinkKey->bdaddr.b[2],
|
||||
pEventLinkKey->bdaddr.b[3], pEventLinkKey->bdaddr.b[4], pEventLinkKey->bdaddr.b[5]);
|
||||
|
||||
#if MAX_LOGLEVEL >= DEBUG_LEVEL
|
||||
LOG_LinkKey(pEventLinkKey->LinkKey);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
};
|
||||
|
@ -1247,9 +1304,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom
|
|||
break;
|
||||
}
|
||||
|
||||
if (m_LastCmd == NULL)
|
||||
if ((m_LastCmd == NULL) && (m_HCIPool.m_number == 0))
|
||||
{
|
||||
// HCI command finished, send a reply to command
|
||||
// If HCI command is finished and HCI pool is empty, send a reply to command
|
||||
WII_IPCInterface::EnqReply(_rHCICommandMessage.m_Address);
|
||||
}
|
||||
}
|
||||
|
@ -1375,7 +1432,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadStoredLinkKey(u8* _Input)
|
|||
|
||||
// generate link key
|
||||
// Let us have some fun :P
|
||||
if(m_LastCmd<m_WiiMotes.size())
|
||||
if(m_LastCmd < m_WiiMotes.size())
|
||||
{
|
||||
SendEventLinkKeyNotification(m_WiiMotes[m_LastCmd]);
|
||||
m_LastCmd++;
|
||||
|
@ -1900,6 +1957,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDisconnect(u8* _Input)
|
|||
CWII_IPC_HLE_WiiMote* pWiimote = AccessWiiMote(pDiscon->con_handle);
|
||||
if (pWiimote)
|
||||
pWiimote->EventDisconnect();
|
||||
|
||||
// Here we should enable scan so reconnect is possible
|
||||
m_ScanEnable = 0x2;
|
||||
*/
|
||||
|
||||
static bool OneShotMessage = true;
|
||||
|
|
|
@ -73,7 +73,8 @@ public:
|
|||
virtual u32 Update();
|
||||
|
||||
void SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size);
|
||||
void PurgeACLFrame();
|
||||
void PurgeACLPool();
|
||||
void PurgeHCIPool();
|
||||
|
||||
//hack for wiimote plugin
|
||||
|
||||
|
@ -120,12 +121,24 @@ private:
|
|||
u32 m_Address;
|
||||
};
|
||||
|
||||
struct ACLFrame
|
||||
struct ACLPool
|
||||
{
|
||||
u32 m_number;
|
||||
u8 m_data[1024];
|
||||
u8 m_data[1024]; // Capacity: 64B x 16
|
||||
|
||||
ACLFrame(int num)
|
||||
ACLPool(int num)
|
||||
: m_number(num)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct HCIPool
|
||||
{
|
||||
u32 m_number;
|
||||
u8 m_data[1024]; // Capacity: 64B x 16
|
||||
u8 m_size[16];
|
||||
|
||||
HCIPool(int num)
|
||||
: m_number(num)
|
||||
{
|
||||
}
|
||||
|
@ -171,8 +184,9 @@ private:
|
|||
// STATE_TO_SAVE
|
||||
SHCICommandMessage m_CtrlSetup;
|
||||
CtrlBuffer m_HCIBuffer;
|
||||
HCIPool m_HCIPool;
|
||||
CtrlBuffer m_ACLBuffer;
|
||||
ACLFrame m_ACLFrame;
|
||||
ACLPool m_ACLPool;
|
||||
u32 m_LastCmd;
|
||||
int m_PacketCount;
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
|||
0x00, // Minus
|
||||
0x36, // Period
|
||||
0x37, // '/'
|
||||
0x34, // 'љ'
|
||||
0x34, // ' '
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
@ -331,7 +331,7 @@ u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
|||
0x2D, // ')'
|
||||
0x32, // '\'
|
||||
0x2F, // '^'
|
||||
0x00, // 'В'
|
||||
0x00, // ' '
|
||||
0x38, // '!'
|
||||
0x00, // Nothing interesting past this point.
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ void TiltTest(u8 x, u8 y, u8 z)
|
|||
|
||||
|
||||
/* Angles adjustment for the upside down state when both roll and pitch is
|
||||
used. When the absolute values of the angles go over 90° the Wiimote is
|
||||
used. When the absolute values of the angles go over 90 the Wiimote is
|
||||
upside down and these adjustments are needed. */
|
||||
void AdjustAngles(float &Roll, float &Pitch)
|
||||
{
|
||||
|
|
|
@ -432,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
|
||||
|
@ -456,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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue