mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
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;
|
(*ptr) += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store maps to file. Very useful.
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void Do(std::map<unsigned int, T> &x) {
|
void Do(std::map<unsigned int, T> &x)
|
||||||
|
{
|
||||||
// TODO
|
// TODO
|
||||||
PanicAlert("Do(map<>) does not yet work.");
|
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.
|
// Store vectors.
|
||||||
template<class T>
|
template<class T>
|
||||||
void Do(std::vector<T> &x) {
|
void Do(std::vector<T> &x) {
|
||||||
|
@ -74,6 +74,9 @@ typedef std::map<u32, IWII_IPC_HLE_Device*> TDeviceMap;
|
|||||||
TDeviceMap g_DeviceMap;
|
TDeviceMap g_DeviceMap;
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
|
typedef std::map<u32, std::string> TFileNameMap;
|
||||||
|
TFileNameMap g_FileNameMap;
|
||||||
|
|
||||||
u32 g_LastDeviceID = 0x13370000;
|
u32 g_LastDeviceID = 0x13370000;
|
||||||
std::string g_DefaultContentFile;
|
std::string g_DefaultContentFile;
|
||||||
|
|
||||||
@ -85,16 +88,15 @@ void Init()
|
|||||||
|
|
||||||
void Reset()
|
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();
|
TDeviceMap::const_iterator itr = g_DeviceMap.begin();
|
||||||
while (itr != g_DeviceMap.end())
|
while (itr != g_DeviceMap.end())
|
||||||
{
|
{
|
||||||
if (itr->second)
|
if(itr->second)
|
||||||
delete itr->second;
|
delete itr->second;
|
||||||
++itr;
|
++itr;
|
||||||
}
|
}
|
||||||
g_DeviceMap.clear();
|
g_DeviceMap.clear();
|
||||||
|
g_FileNameMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
@ -130,8 +132,6 @@ IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID)
|
|||||||
return g_DeviceMap[_ID];
|
return g_DeviceMap[_ID];
|
||||||
|
|
||||||
// ID = 0 just means it hasn't been created yet
|
// 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;
|
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
|
// 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;
|
std::string Source = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP;
|
||||||
if(Core::GetStartupParameter().bNTSC)
|
if(Core::GetStartupParameter().bNTSC)
|
||||||
@ -259,14 +259,43 @@ void CopySettingsFile(std::string DeviceName)
|
|||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
p.Do(g_LastDeviceID);
|
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")));
|
IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(GetDeviceIDByName(std::string("/dev/usb/oh1/57e/305")));
|
||||||
if (pDevice)
|
if (pDevice)
|
||||||
pDevice->DoState(p);
|
pDevice->DoState(p);
|
||||||
else
|
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)
|
void ExecuteCommand(u32 _Address)
|
||||||
@ -307,15 +336,16 @@ void ExecuteCommand(u32 _Address)
|
|||||||
g_LastDeviceID++;
|
g_LastDeviceID++;
|
||||||
|
|
||||||
CmdSuccess = pDevice->Open(_Address, Mode);
|
CmdSuccess = pDevice->Open(_Address, Mode);
|
||||||
if(pDevice->GetDeviceName().find("/dev/") == std::string::npos
|
if(pDevice->GetDeviceName().find("/dev/") == std::string::npos)
|
||||||
|| pDevice->GetDeviceName().c_str() == std::string("/dev/fs"))
|
// || 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);
|
pDevice->GetDeviceName().c_str(), CurrentDeviceID, Mode, (int)CmdSuccess);
|
||||||
}
|
}
|
||||||
else
|
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);
|
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);
|
ERROR_LOG(WII_IPC_HLE, "IOP: Reply to unknown device ID (DeviceID=%i)", DeviceID);
|
||||||
|
|
||||||
if (ClosedDeviceID > 0 && (ClosedDeviceID == DeviceID))
|
if (ClosedDeviceID > 0 && (ClosedDeviceID == DeviceID))
|
||||||
|
{
|
||||||
DeleteDeviceByID(DeviceID);
|
DeleteDeviceByID(DeviceID);
|
||||||
|
g_FileNameMap.erase(DeviceID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include "ChunkFile.h"
|
#include "ChunkFile.h"
|
||||||
|
|
||||||
|
class IWII_IPC_HLE_Device;
|
||||||
|
|
||||||
namespace WII_IPC_HLE_Interface
|
namespace WII_IPC_HLE_Interface
|
||||||
{
|
{
|
||||||
// Init
|
// Init
|
||||||
@ -31,12 +33,24 @@ void Shutdown();
|
|||||||
// Reset
|
// Reset
|
||||||
void 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
|
// Do State
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
|
|
||||||
// Set default content file
|
// Set default content file
|
||||||
void SetDefaultContentFile(const std::string& _rFilename);
|
void SetDefaultContentFile(const std::string& _rFilename);
|
||||||
|
|
||||||
|
void CopySettingsFile(std::string& DeviceName);
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
void 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");
|
ERROR_LOG(WII_IPC_DVD, "DVDLowAudioBufferConfig");
|
||||||
break;
|
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:
|
default:
|
||||||
ERROR_LOG(WII_IPC_DVD, "unknown cmd 0x%08x (Buffer 0x%08x, 0x%x)",
|
ERROR_LOG(WII_IPC_DVD, "unknown cmd 0x%08x (Buffer 0x%08x, 0x%x)",
|
||||||
Command, _BufferOut, _BufferOutSize);
|
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_HostNumACLPackets(0)
|
||||||
, m_HostNumSCOPackets(0)
|
, m_HostNumSCOPackets(0)
|
||||||
, m_HCIBuffer(NULL)
|
, m_HCIBuffer(NULL)
|
||||||
|
, m_HCIPool(0)
|
||||||
, m_ACLBuffer(NULL)
|
, m_ACLBuffer(NULL)
|
||||||
, m_ACLFrame(0)
|
, m_ACLPool(0)
|
||||||
, m_LastCmd(NULL)
|
, m_LastCmd(NULL)
|
||||||
, m_PacketCount(0)
|
, 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()
|
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)
|
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_PacketCount);
|
||||||
p.Do(m_CtrlSetup);
|
p.Do(m_CtrlSetup);
|
||||||
p.Do(m_HCIBuffer);
|
p.Do(m_HCIBuffer);
|
||||||
|
p.Do(m_HCIPool);
|
||||||
p.Do(m_ACLBuffer);
|
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
|
// check termination
|
||||||
_dbg_assert_msg_(WII_IPC_WIIMOTE, *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[5].m_Address) == 0,
|
_dbg_assert_msg_(WII_IPC_WIIMOTE, *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[5].m_Address) == 0,
|
||||||
"WIIMOTE: Termination != 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, "USB_IOCTL_CTRLMSG (0x%08x) - execute command", _CommandAddress);
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, " bRequestType: 0x%x", m_CtrlSetup.bRequestType);
|
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, " 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, " 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_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, " m_PayLoadSize: 0x%x", m_CtrlSetup.m_PayLoadSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
ExecuteHCICommandMessage(m_CtrlSetup);
|
ExecuteHCICommandMessage(m_CtrlSetup);
|
||||||
// Replies are generated inside
|
// 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);
|
SendToDevice(pACLHeader->ConnectionHandle, Memory::GetPointer(BulkBuffer.m_buffer + 4), pACLHeader->Size);
|
||||||
m_PacketCount++;
|
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
|
// or else we have to delay this reply
|
||||||
if (m_ACLFrame.m_number == 0)
|
if (m_ACLPool.m_number == 0)
|
||||||
_SendReply = true;
|
_SendReply = true;
|
||||||
}
|
}
|
||||||
break;
|
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.
|
// 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
|
// AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately
|
||||||
// rather than enqueue it to some other memory
|
// 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)
|
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
|
// Invalidate ACL buffer
|
||||||
m_ACLBuffer.m_address = NULL;
|
m_ACLBuffer.m_address = NULL;
|
||||||
m_ACLBuffer.m_buffer = 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
|
else
|
||||||
{
|
{
|
||||||
// Actually this temp storage is not quite necessary
|
UACLHeader* pHeader = (UACLHeader*)(m_ACLPool.m_data + m_ACLPool.m_number * 64); // I belive 64B is enough
|
||||||
// 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->ConnectionHandle = _ConnectionHandle;
|
||||||
pHeader->BCFlag = 0;
|
pHeader->BCFlag = 0;
|
||||||
pHeader->PBFlag = 2;
|
pHeader->PBFlag = 2;
|
||||||
pHeader->Size = _Size;
|
pHeader->Size = _Size;
|
||||||
|
|
||||||
memcpy((u8*)pHeader + sizeof(UACLHeader), _pData, _Size);
|
memcpy((u8*)pHeader + sizeof(UACLHeader), _pData, _Size);
|
||||||
m_ACLFrame.m_number++;
|
m_ACLPool.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
|
// The normal hardware behavior is like this:
|
||||||
// multiple L2CAP packets come from WiiMote_Plugin in one cycle
|
// 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)
|
if(m_ACLBuffer.m_address == NULL)
|
||||||
return;
|
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
|
// 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);
|
memcpy(Memory::GetPointer(m_ACLBuffer.m_buffer), _Address, 64);
|
||||||
// Write the packet size as return value
|
// Write the packet size as return value
|
||||||
Memory::Write_U32(sizeof(UACLHeader) + ((UACLHeader*)_Address)->Size, m_ACLBuffer.m_address + 0x4);
|
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()
|
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
|
// Check if last command needs more work
|
||||||
if (m_HCIBuffer.m_address && m_LastCmd)
|
if (m_HCIBuffer.m_address && m_LastCmd)
|
||||||
{
|
{
|
||||||
@ -373,11 +387,11 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if temp ACL frame is not purged
|
// Check if ACL Pool is not purged
|
||||||
if (m_ACLFrame.m_number > 0)
|
if (m_ACLPool.m_number > 0)
|
||||||
{
|
{
|
||||||
PurgeACLFrame();
|
PurgeACLPool();
|
||||||
if (m_ACLFrame.m_number == 0)
|
if (m_ACLPool.m_number == 0)
|
||||||
WII_IPCInterface::EnqReply(m_CtrlSetup.m_Address);
|
WII_IPCInterface::EnqReply(m_CtrlSetup.m_Address);
|
||||||
return true;
|
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
|
// AyuanX: This event should be sent periodically after ACL connection is accepted
|
||||||
// but not too many or it will jam the bus and cost extra CPU time
|
// 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;
|
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++;
|
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;
|
FreqDividerSync = 0;
|
||||||
SendEventNumberOfCompletedPackets(m_WiiMotes[0].GetConnectionHandle(), m_PacketCount);
|
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())
|
if (m_ACLBuffer.m_address && !WII_IPCInterface::GetAddress() && !m_LastCmd && m_WiiMotes[0].IsLinked())
|
||||||
{
|
{
|
||||||
FreqDividerMote++;
|
FreqDividerMote++;
|
||||||
if(FreqDividerMote > 100) // Feel free to tweak it
|
if(FreqDividerMote > 99) // Feel free to tweak it
|
||||||
{
|
{
|
||||||
FreqDividerMote = 0;
|
FreqDividerMote = 0;
|
||||||
CPluginManager::GetInstance().GetWiimote(0)->Wiimote_Update();
|
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
|
// 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
|
// 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)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _event)
|
||||||
{
|
{
|
||||||
if (m_HCIBuffer.m_address != NULL)
|
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
|
// Invalidate HCI buffer
|
||||||
m_HCIBuffer.m_address = NULL;
|
m_HCIBuffer.m_address = NULL;
|
||||||
m_HCIBuffer.m_buffer = 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
|
else
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_WIIMOTE, "Sending HCI Packet failed, HCI Buffer is invald!");
|
memcpy(m_HCIPool.m_data + m_HCIPool.m_number * 64, _event.m_buffer, _event.m_size);
|
||||||
PanicAlert("WII_IPC_HLE_DEVICE_USB: Sending HCI Packet failed, HCI Buffer is invald!");
|
// 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)
|
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",
|
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[0], pEventLinkKey->bdaddr.b[1], pEventLinkKey->bdaddr.b[2],
|
||||||
pEventLinkKey->bdaddr.b[3], pEventLinkKey->bdaddr.b[4], pEventLinkKey->bdaddr.b[5]);
|
pEventLinkKey->bdaddr.b[3], pEventLinkKey->bdaddr.b[4], pEventLinkKey->bdaddr.b[5]);
|
||||||
|
|
||||||
|
#if MAX_LOGLEVEL >= DEBUG_LEVEL
|
||||||
LOG_LinkKey(pEventLinkKey->LinkKey);
|
LOG_LinkKey(pEventLinkKey->LinkKey);
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@ -1247,9 +1304,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom
|
|||||||
break;
|
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);
|
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
|
// generate link key
|
||||||
// Let us have some fun :P
|
// Let us have some fun :P
|
||||||
if(m_LastCmd<m_WiiMotes.size())
|
if(m_LastCmd < m_WiiMotes.size())
|
||||||
{
|
{
|
||||||
SendEventLinkKeyNotification(m_WiiMotes[m_LastCmd]);
|
SendEventLinkKeyNotification(m_WiiMotes[m_LastCmd]);
|
||||||
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);
|
CWII_IPC_HLE_WiiMote* pWiimote = AccessWiiMote(pDiscon->con_handle);
|
||||||
if (pWiimote)
|
if (pWiimote)
|
||||||
pWiimote->EventDisconnect();
|
pWiimote->EventDisconnect();
|
||||||
|
|
||||||
|
// Here we should enable scan so reconnect is possible
|
||||||
|
m_ScanEnable = 0x2;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool OneShotMessage = true;
|
static bool OneShotMessage = true;
|
||||||
|
@ -73,7 +73,8 @@ public:
|
|||||||
virtual u32 Update();
|
virtual u32 Update();
|
||||||
|
|
||||||
void SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size);
|
void SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size);
|
||||||
void PurgeACLFrame();
|
void PurgeACLPool();
|
||||||
|
void PurgeHCIPool();
|
||||||
|
|
||||||
//hack for wiimote plugin
|
//hack for wiimote plugin
|
||||||
|
|
||||||
@ -120,12 +121,24 @@ private:
|
|||||||
u32 m_Address;
|
u32 m_Address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ACLFrame
|
struct ACLPool
|
||||||
{
|
{
|
||||||
u32 m_number;
|
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)
|
: m_number(num)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -171,8 +184,9 @@ private:
|
|||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
SHCICommandMessage m_CtrlSetup;
|
SHCICommandMessage m_CtrlSetup;
|
||||||
CtrlBuffer m_HCIBuffer;
|
CtrlBuffer m_HCIBuffer;
|
||||||
|
HCIPool m_HCIPool;
|
||||||
CtrlBuffer m_ACLBuffer;
|
CtrlBuffer m_ACLBuffer;
|
||||||
ACLFrame m_ACLFrame;
|
ACLPool m_ACLPool;
|
||||||
u32 m_LastCmd;
|
u32 m_LastCmd;
|
||||||
int m_PacketCount;
|
int m_PacketCount;
|
||||||
|
|
||||||
|
@ -323,7 +323,7 @@ u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
|||||||
0x00, // Minus
|
0x00, // Minus
|
||||||
0x36, // Period
|
0x36, // Period
|
||||||
0x37, // '/'
|
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,
|
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, // ')'
|
0x2D, // ')'
|
||||||
0x32, // '\'
|
0x32, // '\'
|
||||||
0x2F, // '^'
|
0x2F, // '^'
|
||||||
0x00, // 'В'
|
0x00, // ' '
|
||||||
0x38, // '!'
|
0x38, // '!'
|
||||||
0x00, // Nothing interesting past this point.
|
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
|
/* 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. */
|
upside down and these adjustments are needed. */
|
||||||
void AdjustAngles(float &Roll, float &Pitch)
|
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
|
/* 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
|
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)
|
void TiltWiimoteGamepad(float &Roll, float &Pitch)
|
||||||
{
|
{
|
||||||
// Return if we have no pads
|
// Return if we have no pads
|
||||||
@ -456,7 +456,7 @@ void TiltWiimoteGamepad(float &Roll, float &Pitch)
|
|||||||
float Tl = (float)_Tl;
|
float Tl = (float)_Tl;
|
||||||
float Tr = (float)_Tr;
|
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 RollRange = (float)g_Config.Trigger.Range.Roll;
|
||||||
float PitchRange = (float)g_Config.Trigger.Range.Pitch;
|
float PitchRange = (float)g_Config.Trigger.Range.Pitch;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user